From 63d9357482d977f110c1b1804d827bb81d513cfa Mon Sep 17 00:00:00 2001 From: eksperimental Date: Sat, 7 Feb 2015 22:05:02 +0700 Subject: Improve success message when 2 tests have passed **2 tests have passed.** instead of **All 2 tests passed.** --- lib/eunit/src/eunit_tty.erl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/eunit/src/eunit_tty.erl b/lib/eunit/src/eunit_tty.erl index f21b2da3d3..65a306c1cf 100644 --- a/lib/eunit/src/eunit_tty.erl +++ b/lib/eunit/src/eunit_tty.erl @@ -67,6 +67,8 @@ terminate({ok, Data}, St) -> end, if Pass =:= 1 -> fwrite(" Test passed.\n"); + Pass =:= 2 -> + fwrite(" 2 tests passed.\n"); true -> fwrite(" All ~w tests passed.\n", [Pass]) end -- cgit v1.2.3 From fa2b944f13fc85bdee593e1896c61ca2e3a7def9 Mon Sep 17 00:00:00 2001 From: soranoba Date: Sat, 14 Mar 2015 15:03:49 +0900 Subject: Fix file:position (not raw mode) When it called the "file:position", it subtract the size that was read into the buffer, and returns the value. However, it has been discarded buffer and correct position is lost, if "file:postion" returns error. --- lib/kernel/src/file_io_server.erl | 7 ++++++- lib/kernel/test/file_SUITE.erl | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl index 0e9ff5bc0f..d0ad43afbf 100644 --- a/lib/kernel/src/file_io_server.erl +++ b/lib/kernel/src/file_io_server.erl @@ -256,7 +256,12 @@ file_request(close, {stop,normal,?PRIM_FILE:close(Handle),State#state{buf= <<>>}}; file_request({position,At}, #state{handle=Handle,buf=Buf}=State) -> - std_reply(position(Handle, At, Buf), State); + case position(Handle, At, Buf) of + {error, _Reason}=Reply -> + {error,Reply,State}; + Reply -> + {reply,Reply,State#state{buf= <<>>}} + end; file_request(truncate, #state{handle=Handle}=State) -> case ?PRIM_FILE:truncate(Handle) of diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 2ce2303ba3..2911635db7 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -47,7 +47,7 @@ -export([cur_dir_0/1, cur_dir_1/1, make_del_dir/1, list_dir/1,list_dir_error/1, untranslatable_names/1, untranslatable_names_error/1, - pos1/1, pos2/1]). + pos1/1, pos2/1, pos3/1]). -export([close/1, consult1/1, path_consult/1, delete/1]). -export([ eval1/1, path_eval/1, script1/1, path_script/1, open1/1, @@ -1219,6 +1219,20 @@ pos2(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +pos3(suite) -> []; +pos3(doc) -> ["When it does not use raw mode, file:postiion had a bug."]; +pos3(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line RootDir = ?config(data_dir, Config), + ?line Name = filename:join(RootDir, "realmen.html.gz"), + + ?line {ok, Fd} = ?FILE_MODULE:open(Name, [read, binary]), + ?line {ok, _} = ?FILE_MODULE:read(Fd, 5), + ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof, -1}), + %% Here ok had returned =( + ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur, -10}), + ?line test_server:timetrap_cancel(Dog), + ok. file_info_basic_file(suite) -> []; file_info_basic_file(doc) -> []; -- cgit v1.2.3 From 2801f3dae373f1cf22f8a7113f1a53cd242ed62f Mon Sep 17 00:00:00 2001 From: Zandra Hird Date: Fri, 10 Apr 2015 12:41:56 +0200 Subject: fix snmp_conf check imask bug This change is originally from John Heizenberg. --- lib/snmp/src/misc/snmp_conf.erl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index 153c8070c2..c456ed3b9b 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -1004,6 +1004,8 @@ check_imask(IMask) when is_list(IMask) -> do_check_imask(IMask), {ok, IMask}. +do_check_imask([]) -> + ok; do_check_imask([0|IMask]) -> do_check_imask(IMask); do_check_imask([1|IMask]) -> -- cgit v1.2.3 From 8266a6056ff3b4292d98485665e5444addd689b6 Mon Sep 17 00:00:00 2001 From: Danil Zagoskin Date: Sat, 2 May 2015 00:40:53 +0300 Subject: kernel: inet6_tcp_dist: reuse inet_tcp_dist code inet6_tcp_dist module is an old copy of inet_tcp_dist with changed address family. New features (such as listening port range, interface and generic options) are implemented in inet_tcp_dist only, inet6_tcp_dist looks abandoned (it does not even have tests). This patch makes inet_tcp_dist internals work with abstract driver, and inet6_tcp_dist becomes just a thin wrapper for it. --- lib/kernel/src/inet6_tcp.erl | 19 ++ lib/kernel/src/inet6_tcp_dist.erl | 365 +------------------------------------- lib/kernel/src/inet_tcp.erl | 16 +- lib/kernel/src/inet_tcp_dist.erl | 159 +++++++++-------- 4 files changed, 129 insertions(+), 430 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl index c714b2bee0..b31f05b08a 100644 --- a/lib/kernel/src/inet6_tcp.erl +++ b/lib/kernel/src/inet6_tcp.erl @@ -24,10 +24,29 @@ -export([controlling_process/2]). -export([fdopen/2]). +-export([family/0, mask/2, parse_address/1]). -export([getserv/1, getaddr/1, getaddr/2, getaddrs/1, getaddrs/2]). -include("inet_int.hrl"). +%% my address family +family() -> inet6. + +%% Apply netmask on address +mask({M1,M2,M3,M4,M5,M6,M7,M8}, {IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8}) -> + {M1 band IP1, + M2 band IP2, + M3 band IP3, + M4 band IP4, + M5 band IP5, + M6 band IP6, + M7 band IP7, + M8 band IP8 }. + +%% Parse address string +parse_address(Host) -> + inet_parse:ipv6strict_address(Host). + %% inet_tcp port lookup getserv(Port) when is_integer(Port) -> {ok, Port}; getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,tcp). diff --git a/lib/kernel/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl index 459fdc2ad5..1488bf41f3 100644 --- a/lib/kernel/src/inet6_tcp_dist.erl +++ b/lib/kernel/src/inet6_tcp_dist.erl @@ -23,28 +23,6 @@ -export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). -%% internal exports - --export([accept_loop/2,do_accept/6,do_setup/6, getstat/1,tick/1]). - --import(error_logger,[error_msg/2]). - --include("net_address.hrl"). - - - --define(to_port(Socket, Data, Opts), - case inet6_tcp:send(Socket, Data, Opts) of - {error, closed} -> - self() ! {tcp_closed, Socket}, - {error, closed}; - R -> - R - end). - - --include("dist.hrl"). --include("dist_util.hrl"). %% ------------------------------------------------------------ %% Select this protocol based on node name @@ -52,14 +30,7 @@ %% ------------------------------------------------------------ select(Node) -> - case split_node(atom_to_list(Node), $@, []) of - [_, Host] -> - case inet:getaddr(Host,inet6) of - {ok,_} -> true; - _ -> false - end; - _ -> false - end. + inet_tcp_dist:gen_select(inet6_tcp, Node). %% ------------------------------------------------------------ %% Create the listen socket, i.e. the port that this erlang @@ -67,59 +38,14 @@ select(Node) -> %% ------------------------------------------------------------ listen(Name) -> - case inet6_tcp:listen(0, [{active, false}, {packet,2}]) of - {ok, Socket} -> - TcpAddress = get_tcp_address(Socket), - {_,Port} = TcpAddress#net_address.address, - case erl_epmd:register_node(Name, Port) of - {ok, Creation} -> - {ok, {Socket, TcpAddress, Creation}}; - Error -> - Error - end; - Error -> - Error - end. + inet_tcp_dist:gen_listen(inet6_tcp, Name). %% ------------------------------------------------------------ %% Accepts new connection attempts from other Erlang nodes. %% ------------------------------------------------------------ accept(Listen) -> - spawn_opt(?MODULE, accept_loop, [self(), Listen], [link, {priority, max}]). - -accept_loop(Kernel, Listen) -> - case inet6_tcp:accept(Listen) of - {ok, Socket} -> - Kernel ! {accept,self(),Socket,inet6,tcp}, - _ = controller(Kernel, Socket), - accept_loop(Kernel, Listen); - Error -> - exit(Error) - end. - -controller(Kernel, Socket) -> - receive - {Kernel, controller, Pid} -> - flush_controller(Pid, Socket), - inet6_tcp:controlling_process(Socket, Pid), - flush_controller(Pid, Socket), - Pid ! {self(), controller}; - {Kernel, unsupported_protocol} -> - exit(unsupported_protocol) - end. - -flush_controller(Pid, Socket) -> - receive - {tcp, Socket, Data} -> - Pid ! {tcp, Socket, Data}, - flush_controller(Pid, Socket); - {tcp_closed, Socket} -> - Pid ! {tcp_closed, Socket}, - flush_controller(Pid, Socket) - after 0 -> - ok - end. + inet_tcp_dist:gen_accept(inet6_tcp, Listen). %% ------------------------------------------------------------ %% Accepts a new connection attempt from another Erlang node. @@ -127,85 +53,7 @@ flush_controller(Pid, Socket) -> %% ------------------------------------------------------------ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> - spawn_opt(?MODULE, do_accept, - [self(), AcceptPid, Socket, MyNode, Allowed, SetupTime], - [link, {priority, max}]). - -do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> - receive - {AcceptPid, controller} -> - Timer = dist_util:start_timer(SetupTime), - case check_ip(Socket) of - true -> - HSData = #hs_data{ - kernel_pid = Kernel, - this_node = MyNode, - socket = Socket, - timer = Timer, - this_flags = 0, - allowed = Allowed, - f_send = fun(S,D) -> inet6_tcp:send(S,D) end, - f_recv = fun(S,N,T) -> inet6_tcp:recv(S,N,T) - end, - f_setopts_pre_nodeup = - fun(S) -> - inet:setopts(S, - [{active, false}, - {packet, 4}, - nodelay()]) - end, - f_setopts_post_nodeup = - fun(S) -> - inet:setopts(S, - [{active, true}, - {deliver, port}, - {packet, 4}, - nodelay()]) - end, - f_getll = fun(S) -> - inet:getll(S) - end, - f_address = fun get_remote_id/2, - mf_tick = fun ?MODULE:tick/1, - mf_getstat = fun ?MODULE:getstat/1 - }, - dist_util:handshake_other_started(HSData); - {false,IP} -> - error_msg("** Connection attempt from " - "disallowed IP ~w ** ~n", [IP]), - ?shutdown(no_node) - end - end. - - -%% we may not always want the nodelay behaviour -%% for performance reasons - -nodelay() -> - case application:get_env(kernel, dist_nodelay) of - undefined -> - {nodelay, true}; - {ok, true} -> - {nodelay, true}; - {ok, false} -> - {nodelay, false}; - _ -> - {nodelay, true} - end. - - -%% ------------------------------------------------------------ -%% Get remote information about a Socket. -%% ------------------------------------------------------------ - -get_remote_id(Socket, Node) -> - {ok, Address} = inet:peername(Socket), - [_, Host] = split_node(atom_to_list(Node), $@, []), - #net_address { - address = Address, - host = Host, - protocol = tcp, - family = inet6 }. + inet_tcp_dist:gen_accept_connection(inet6_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime). %% ------------------------------------------------------------ %% Setup a new connection to another Erlang node. @@ -213,214 +61,13 @@ get_remote_id(Socket, Node) -> %% ------------------------------------------------------------ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> - spawn_opt(?MODULE, do_setup, - [self(), Node, Type, MyNode, LongOrShortNames, SetupTime], - [link, {priority, max}]). - -do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> - ?trace("~p~n",[{?MODULE,self(),setup,Node}]), - [Name, Address] = splitnode(Node, LongOrShortNames), - case inet:getaddr(Address, inet6) of - {ok, Ip} -> - Timer = dist_util:start_timer(SetupTime), - case erl_epmd:port_please(Name, Ip) of - {port, TcpPort, Version} -> - ?trace("port_please(~p) -> version ~p~n", - [Node,Version]), - dist_util:reset_timer(Timer), - case inet6_tcp:connect(Ip, TcpPort, - [{active, false}, - {packet,2}]) of - {ok, Socket} -> - HSData = #hs_data{ - kernel_pid = Kernel, - other_node = Node, - this_node = MyNode, - socket = Socket, - timer = Timer, - this_flags = 0, - other_version = Version, - f_send = fun inet6_tcp:send/2, - f_recv = fun inet6_tcp:recv/3, - f_setopts_pre_nodeup = - fun(S) -> - inet:setopts - (S, - [{active, false}, - {packet, 4}, - nodelay()]) - end, - f_setopts_post_nodeup = - fun(S) -> - inet:setopts - (S, - [{active, true}, - {deliver, port}, - {packet, 4}, - nodelay()]) - end, - f_getll = fun inet:getll/1, - f_address = - fun(_,_) -> - #net_address { - address = {Ip,TcpPort}, - host = Address, - protocol = tcp, - family = inet6} - end, - mf_tick = fun ?MODULE:tick/1, - mf_getstat = fun ?MODULE:getstat/1, - request_type = Type - }, - dist_util:handshake_we_started(HSData); - _ -> - %% Other Node may have closed since - %% port_please ! - ?trace("other node (~p) " - "closed since port_please.~n", - [Node]), - ?shutdown(Node) - end; - _ -> - ?trace("port_please (~p) " - "failed.~n", [Node]), - ?shutdown(Node) - end; - __Other -> - ?trace("inet_getaddr(~p) " - "failed (~p).~n", [Node,__Other]), - ?shutdown(Node) - end. + inet_tcp_dist:gen_setup(inet6_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime). %% %% Close a socket. %% close(Socket) -> inet6_tcp:close(Socket). - - -%% If Node is illegal terminate the connection setup!! -splitnode(Node, LongOrShortNames) -> - case split_node(atom_to_list(Node), $@, []) of - [Name|Tail] when Tail =/= [] -> - Host = lists:append(Tail), - case split_node(Host, $., []) of - [_] when LongOrShortNames =:= longnames -> - case inet_parse:ipv6strict_address(Host) of - {ok, _} -> - [Name, Host]; - _ -> - error_msg("** System running to use " - "fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), - ?shutdown(Node) - end; - L when length(L) > 1, LongOrShortNames =:= shortnames -> - error_msg("** System NOT running to use fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), - ?shutdown(Node); - _ -> - [Name, Host] - end; - [_] -> - error_msg("** Nodename ~p illegal, no '@' character **~n", - [Node]), - ?shutdown(Node); - _ -> - error_msg("** Nodename ~p illegal **~n", [Node]), - ?shutdown(Node) - end. - -split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])]; -split_node([H|T], Chr, Ack) -> split_node(T, Chr, [H|Ack]); -split_node([], _, Ack) -> [lists:reverse(Ack)]. - -%% ------------------------------------------------------------ -%% Fetch local information about a Socket. -%% ------------------------------------------------------------ -get_tcp_address(Socket) -> - {ok, Address} = inet:sockname(Socket), - {ok, Host} = inet:gethostname(), - #net_address { - address = Address, - host = Host, - protocol = tcp, - family = inet6 - }. - -%% ------------------------------------------------------------ -%% Do only accept new connection attempts from nodes at our -%% own LAN, if the check_ip environment parameter is true. -%% ------------------------------------------------------------ -check_ip(Socket) -> - case application:get_env(check_ip) of - {ok, true} -> - case get_ifs(Socket) of - {ok, IFs, IP} -> - check_ip(IFs, IP); - _ -> - ?shutdown(no_node) - end; - _ -> - true - end. - -get_ifs(Socket) -> - case inet:peername(Socket) of - {ok, {IP, _}} -> - case inet:getif(Socket) of - {ok, IFs} -> {ok, IFs, IP}; - Error -> Error - end; - Error -> - Error - end. - -check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) -> - case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of - {M, M} -> true; - _ -> check_ip(IFs, PeerIP) - end; -check_ip([], PeerIP) -> - {false, PeerIP}. -mask({M1,M2,M3,M4,M5,M6,M7,M8}, {IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8}) -> - {M1 band IP1, - M2 band IP2, - M3 band IP3, - M4 band IP4, - M5 band IP5, - M6 band IP6, - M7 band IP7, - M8 band IP8 }. - is_node_name(Node) when is_atom(Node) -> - case split_node(atom_to_list(Node), $@, []) of - [_,_Host] -> true; - _ -> false - end; -is_node_name(_Node) -> - false. -tick(Sock) -> - ?to_port(Sock,[],[force]). -getstat(Socket) -> - case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of - {ok, Stat} -> - split_stat(Stat,0,0,0); - Error -> - Error - end. - -split_stat([{recv_cnt, R}|Stat], _, W, P) -> - split_stat(Stat, R, W, P); -split_stat([{send_cnt, W}|Stat], R, _, P) -> - split_stat(Stat, R, W, P); -split_stat([{send_pend, P}|Stat], R, W, _) -> - split_stat(Stat, R, W, P); -split_stat([], R, W, P) -> - {ok, R, W, P}. - + inet_tcp_dist:is_node_name(Node). diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl index 4c2db16ce3..71d35ca8c6 100644 --- a/lib/kernel/src/inet_tcp.erl +++ b/lib/kernel/src/inet_tcp.erl @@ -26,11 +26,25 @@ -export([controlling_process/2]). -export([fdopen/2]). +-export([family/0, mask/2, parse_address/1]). -export([getserv/1, getaddr/1, getaddr/2, getaddrs/1, getaddrs/2]). - -include("inet_int.hrl"). +%% my address family +family() -> inet. + +%% Apply netmask on address +mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) -> + {M1 band IP1, + M2 band IP2, + M3 band IP3, + M4 band IP4}. + +%% Parse address string +parse_address(Host) -> + inet_parse:ipv4strict_address(Host). + %% inet_tcp port lookup getserv(Port) when is_integer(Port) -> {ok, Port}; getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,tcp). diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl index 835dcf2705..6603687dc0 100644 --- a/lib/kernel/src/inet_tcp_dist.erl +++ b/lib/kernel/src/inet_tcp_dist.erl @@ -23,9 +23,13 @@ -export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). +%% Generalized dist API +-export([gen_listen/2, gen_accept/2, gen_accept_connection/6, + gen_setup/6, gen_select/2]). + %% internal exports --export([accept_loop/2,do_accept/6,do_setup/6,getstat/1,tick/1]). +-export([accept_loop/3,do_accept/7,do_setup/7,getstat/1]). -import(error_logger,[error_msg/2]). @@ -33,15 +37,6 @@ --define(to_port(Socket, Data, Opts), - case inet_tcp:send(Socket, Data, Opts) of - {error, closed} -> - self() ! {tcp_closed, Socket}, - {error, closed}; - R -> - R - end). - -include("dist.hrl"). -include("dist_util.hrl"). @@ -52,8 +47,15 @@ %% ------------------------------------------------------------ select(Node) -> + gen_select(inet_tcp, Node). + +gen_select(Driver, Node) -> case split_node(atom_to_list(Node), $@, []) of - [_,_Host] -> true; + [_, Host] -> + case inet:getaddr(Host, Driver:family()) of + {ok,_} -> true; + _ -> false + end; _ -> false end. @@ -63,9 +65,12 @@ select(Node) -> %% ------------------------------------------------------------ listen(Name) -> - case do_listen([{active, false}, {packet,2}, {reuseaddr, true}]) of + gen_listen(inet_tcp, Name). + +gen_listen(Driver, Name) -> + case do_listen(Driver, [{active, false}, {packet,2}, {reuseaddr, true}]) of {ok, Socket} -> - TcpAddress = get_tcp_address(Socket), + TcpAddress = get_tcp_address(Driver, Socket), {_,Port} = TcpAddress#net_address.address, case erl_epmd:register_node(Name, Port) of {ok, Creation} -> @@ -77,7 +82,7 @@ listen(Name) -> Error end. -do_listen(Options) -> +do_listen(Driver, Options) -> {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of {ok,N} when is_integer(N) -> case application:get_env(kernel, @@ -90,14 +95,14 @@ do_listen(Options) -> _ -> {0,0} end, - do_listen(First, Last, listen_options([{backlog,128}|Options])). + do_listen(Driver, First, Last, listen_options([{backlog,128}|Options])). -do_listen(First,Last,_) when First > Last -> +do_listen(_Driver, First,Last,_) when First > Last -> {error,eaddrinuse}; -do_listen(First,Last,Options) -> - case inet_tcp:listen(First, Options) of +do_listen(Driver, First,Last,Options) -> + case Driver:listen(First, Options) of {error, eaddrinuse} -> - do_listen(First+1,Last,Options); + do_listen(Driver, First+1,Last,Options); Other -> Other end. @@ -124,23 +129,26 @@ listen_options(Opts0) -> %% ------------------------------------------------------------ accept(Listen) -> - spawn_opt(?MODULE, accept_loop, [self(), Listen], [link, {priority, max}]). + gen_accept(inet_tcp, Listen). -accept_loop(Kernel, Listen) -> - case inet_tcp:accept(Listen) of +gen_accept(Driver, Listen) -> + spawn_opt(?MODULE, accept_loop, [Driver, self(), Listen], [link, {priority, max}]). + +accept_loop(Driver, Kernel, Listen) -> + case Driver:accept(Listen) of {ok, Socket} -> - Kernel ! {accept,self(),Socket,inet,tcp}, - _ = controller(Kernel, Socket), - accept_loop(Kernel, Listen); + Kernel ! {accept,self(),Socket,Driver:family(),tcp}, + _ = controller(Driver, Kernel, Socket), + accept_loop(Driver, Kernel, Listen); Error -> exit(Error) end. -controller(Kernel, Socket) -> +controller(Driver, Kernel, Socket) -> receive {Kernel, controller, Pid} -> flush_controller(Pid, Socket), - inet_tcp:controlling_process(Socket, Pid), + Driver:controlling_process(Socket, Pid), flush_controller(Pid, Socket), Pid ! {self(), controller}; {Kernel, unsupported_protocol} -> @@ -165,15 +173,18 @@ flush_controller(Pid, Socket) -> %% ------------------------------------------------------------ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> + gen_accept_connection(inet_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime). + +gen_accept_connection(Driver, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> spawn_opt(?MODULE, do_accept, - [self(), AcceptPid, Socket, MyNode, Allowed, SetupTime], + [Driver, self(), AcceptPid, Socket, MyNode, Allowed, SetupTime], [link, {priority, max}]). -do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> +do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> receive {AcceptPid, controller} -> Timer = dist_util:start_timer(SetupTime), - case check_ip(Socket) of + case check_ip(Driver, Socket) of true -> HSData = #hs_data{ kernel_pid = Kernel, @@ -182,9 +193,8 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> timer = Timer, this_flags = 0, allowed = Allowed, - f_send = fun(S,D) -> inet_tcp:send(S,D) end, - f_recv = fun(S,N,T) -> inet_tcp:recv(S,N,T) - end, + f_send = fun Driver:send/2, + f_recv = fun Driver:recv/3, f_setopts_pre_nodeup = fun(S) -> inet:setopts(S, @@ -203,8 +213,8 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> f_getll = fun(S) -> inet:getll(S) end, - f_address = fun get_remote_id/2, - mf_tick = fun ?MODULE:tick/1, + f_address = fun(S, Node) -> get_remote_id(Driver, S, Node) end, + mf_tick = fun(S) -> tick(Driver, S) end, mf_getstat = fun ?MODULE:getstat/1 }, dist_util:handshake_other_started(HSData); @@ -235,13 +245,13 @@ nodelay() -> %% ------------------------------------------------------------ %% Get remote information about a Socket. %% ------------------------------------------------------------ -get_remote_id(Socket, Node) -> +get_remote_id(Driver, Socket, Node) -> case inet:peername(Socket) of {ok,Address} -> case split_node(atom_to_list(Node), $@, []) of [_,Host] -> #net_address{address=Address,host=Host, - protocol=tcp,family=inet}; + protocol=tcp,family=Driver:family()}; _ -> %% No '@' or more than one '@' in node name. ?shutdown(no_node) @@ -256,14 +266,18 @@ get_remote_id(Socket, Node) -> %% ------------------------------------------------------------ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> + gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime). + +gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) -> spawn_opt(?MODULE, do_setup, - [self(), Node, Type, MyNode, LongOrShortNames, SetupTime], + [Driver, self(), Node, Type, MyNode, LongOrShortNames, SetupTime], [link, {priority, max}]). -do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> +do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> ?trace("~p~n",[{inet_tcp_dist,self(),setup,Node}]), - [Name, Address] = splitnode(Node, LongOrShortNames), - case inet:getaddr(Address, inet) of + [Name, Address] = splitnode(Driver, Node, LongOrShortNames), + AddressFamily = Driver:family(), + case inet:getaddr(Address, AddressFamily) of {ok, Ip} -> Timer = dist_util:start_timer(SetupTime), case erl_epmd:port_please(Name, Ip) of @@ -272,7 +286,7 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> [Node,Version]), dist_util:reset_timer(Timer), case - inet_tcp:connect( + Driver:connect( Ip, TcpPort, connect_options([{active, false}, {packet, 2}])) of @@ -285,8 +299,8 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> timer = Timer, this_flags = 0, other_version = Version, - f_send = fun inet_tcp:send/2, - f_recv = fun inet_tcp:recv/3, + f_send = fun Driver:send/2, + f_recv = fun Driver:recv/3, f_setopts_pre_nodeup = fun(S) -> inet:setopts @@ -311,9 +325,9 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> address = {Ip,TcpPort}, host = Address, protocol = tcp, - family = inet} + family = AddressFamily} end, - mf_tick = fun ?MODULE:tick/1, + mf_tick = fun(S) -> tick(Driver, S) end, mf_getstat = fun ?MODULE:getstat/1, request_type = Type }, @@ -340,7 +354,7 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) -> connect_options(Opts) -> case application:get_env(kernel, inet_dist_connect_options) of {ok,ConnectOpts} -> - erlang:display({inet_dist_listen_options, ConnectOpts}), + erlang:display({inet_dist_connect_options, ConnectOpts}), ConnectOpts ++ Opts; _ -> Opts @@ -354,18 +368,23 @@ close(Socket) -> %% If Node is illegal terminate the connection setup!! -splitnode(Node, LongOrShortNames) -> +splitnode(Driver, Node, LongOrShortNames) -> case split_node(atom_to_list(Node), $@, []) of [Name|Tail] when Tail =/= [] -> Host = lists:append(Tail), case split_node(Host, $., []) of [_] when LongOrShortNames =:= longnames -> - error_msg("** System running to use " - "fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), - ?shutdown(Node); + case Driver:parse_address(Host) of + {ok, _} -> + [Name, Host]; + _ -> + error_msg("** System running to use " + "fully qualified " + "hostnames **~n" + "** Hostname ~s is illegal **~n", + [Host]), + ?shutdown(Node) + end; L when length(L) > 1, LongOrShortNames =:= shortnames -> error_msg("** System NOT running to use fully qualified " "hostnames **~n" @@ -391,26 +410,26 @@ split_node([], _, Ack) -> [lists:reverse(Ack)]. %% ------------------------------------------------------------ %% Fetch local information about a Socket. %% ------------------------------------------------------------ -get_tcp_address(Socket) -> +get_tcp_address(Driver, Socket) -> {ok, Address} = inet:sockname(Socket), {ok, Host} = inet:gethostname(), #net_address { address = Address, host = Host, protocol = tcp, - family = inet + family = Driver:family() }. %% ------------------------------------------------------------ %% Do only accept new connection attempts from nodes at our %% own LAN, if the check_ip environment parameter is true. %% ------------------------------------------------------------ -check_ip(Socket) -> +check_ip(Driver, Socket) -> case application:get_env(check_ip) of {ok, true} -> case get_ifs(Socket) of {ok, IFs, IP} -> - check_ip(IFs, IP); + check_ip(Driver, IFs, IP); _ -> ?shutdown(no_node) end; @@ -429,20 +448,14 @@ get_ifs(Socket) -> Error end. -check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) -> - case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of +check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) -> + case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of {M, M} -> true; - _ -> check_ip(IFs, PeerIP) + _ -> check_ip(Driver, IFs, PeerIP) end; -check_ip([], PeerIP) -> +check_ip(_Driver, [], PeerIP) -> {false, PeerIP}. -mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) -> - {M1 band IP1, - M2 band IP2, - M3 band IP3, - M4 band IP4}. - is_node_name(Node) when is_atom(Node) -> case split_node(atom_to_list(Node), $@, []) of [_, _Host] -> true; @@ -451,8 +464,14 @@ is_node_name(Node) when is_atom(Node) -> is_node_name(_Node) -> false. -tick(Sock) -> - ?to_port(Sock,[],[force]). +tick(Driver, Socket) -> + case Driver:send(Socket, [], [force]) of + {error, closed} -> + self() ! {tcp_closed, Socket}, + {error, closed}; + R -> + R + end. getstat(Socket) -> case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of -- cgit v1.2.3 From dd0baa002cf09286f5d80e046e8c8611f9e20d10 Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Fri, 29 May 2015 10:40:34 +0100 Subject: Honour dist_nodelay socket option in tls_dist proxy If a plaintext cluster has nodelay=1 then so should the tls cluster; significant performance issues have been seen when nodelay isn't set --- lib/ssl/src/ssl_tls_dist_proxy.erl | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index a22af6b960..c5e473f923 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -133,6 +133,7 @@ accept_loop(Proxy, erts = Type, Listen, Extra) -> Extra ! {accept,self(),Socket,inet,proxy}, receive {_Kernel, controller, Pid} -> + inet:setopts(Socket, [nodelay()]), ok = gen_tcp:controlling_process(Socket, Pid), flush_old_controller(Pid, Socket), Pid ! {self(), controller}; @@ -166,7 +167,7 @@ accept_loop(Proxy, world = Type, Listen, Extra) -> accept_loop(Proxy, Type, Listen, Extra). try_connect(Port) -> - case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}]) of + case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}, nodelay()]) of R = {ok, _S} -> R; {error, _R} -> @@ -176,7 +177,7 @@ try_connect(Port) -> setup_proxy(Ip, Port, Parent) -> process_flag(trap_exit, true), Opts = get_ssl_options(client), - case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}] ++ Opts) of + case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()] ++ Opts) of {ok, World} -> {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, {127,0,0,1}}, binary, {packet,?PPRE}]), {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL), @@ -192,25 +193,41 @@ setup_proxy(Ip, Port, Parent) -> Parent ! {self(), Err} end. + +%% we may not always want the nodelay behaviour +%% %% for performance reasons + +nodelay() -> + case application:get_env(kernel, dist_nodelay) of + undefined -> + {nodelay, true}; + {ok, true} -> + {nodelay, true}; + {ok, false} -> + {nodelay, false}; + _ -> + {nodelay, true} + end. + setup_connection(World, ErtsListen) -> process_flag(trap_exit, true), {ok, TcpAddress} = get_tcp_address(ErtsListen), {_Addr,Port} = TcpAddress#net_address.address, - {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}]), - ssl:setopts(World, [{active,true}, {packet,?PPRE}]), + {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()]), + ssl:setopts(World, [{active,true}, {packet,?PPRE}, nodelay()]), loop_conn_setup(World, Erts). loop_conn_setup(World, Erts) -> receive {ssl, World, Data = <<$a, _/binary>>} -> gen_tcp:send(Erts, Data), - ssl:setopts(World, [{packet,?PPOST}]), - inet:setopts(Erts, [{packet,?PPOST}]), + ssl:setopts(World, [{packet,?PPOST}, nodelay()]), + inet:setopts(Erts, [{packet,?PPOST}, nodelay()]), loop_conn(World, Erts); {tcp, Erts, Data = <<$a, _/binary>>} -> ssl:send(World, Data), - ssl:setopts(World, [{packet,?PPOST}]), - inet:setopts(Erts, [{packet,?PPOST}]), + ssl:setopts(World, [{packet,?PPOST}, nodelay()]), + inet:setopts(Erts, [{packet,?PPOST}, nodelay()]), loop_conn(World, Erts); {ssl, World, Data = <<_, _/binary>>} -> gen_tcp:send(Erts, Data), -- cgit v1.2.3 From 16212e0495c43e5cba11aeddd0adc9da520b3f45 Mon Sep 17 00:00:00 2001 From: Rory Byrne Date: Mon, 8 Jun 2015 23:23:58 +0100 Subject: Fix supervisor reporting error When a simple_one_for_one supervisor is shutting down, if one or more of its children fail to terminate within the 'shutdown' timeout, then the following reporting error will occur: * If there is only one child that fails to exit on time, then no supervisor report will be generated. * If more than one child fails to exit on time, then the reporting of 'nb_children' in the supervisor report will be 1 less than it should be. --- lib/stdlib/src/supervisor.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 1d7396adee..32718a7959 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -1079,7 +1079,7 @@ wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz, {timeout, TRef, kill} -> ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids), - wait_dynamic_children(Child, Pids, Sz-1, undefined, EStack) + wait_dynamic_children(Child, Pids, Sz, undefined, EStack) end. %%----------------------------------------------------------------- -- cgit v1.2.3 From 274311c9f8f2a056e57f9c89e83a4aa46a774c92 Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Sun, 14 Jun 2015 15:40:13 +0200 Subject: Eliminate dialyzer warnings for unmatched_returns While at it, do a minor cleanup using is_boolean/1 --- lib/eldap/src/eldap.erl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl index ae47c815c9..df87ddde08 100644 --- a/lib/eldap/src/eldap.erl +++ b/lib/eldap/src/eldap.erl @@ -242,7 +242,7 @@ modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) %%% Sanity checks ! -bool_p(Bool) when Bool==true;Bool==false -> Bool. +bool_p(Bool) when is_boolean(Bool) -> Bool. optional([]) -> asn1_NOVALUE; optional(Value) -> Value. @@ -1022,10 +1022,13 @@ log(_, _, _, _) -> %%% Misc. routines %%% -------------------------------------------------------------------- -send(To,Msg) -> To ! {self(),Msg}. +send(To,Msg) -> + To ! {self(), Msg}, + ok. + recv(From) -> receive - {From,Msg} -> Msg; + {From, Msg} -> Msg; {'EXIT', From, Reason} -> {error, {internal_error, Reason}} end. -- cgit v1.2.3 From a5c3feee7bfa77eb385334272505ed562c7ef0f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 18 Jun 2015 17:56:58 +0200 Subject: erts: Remove halfword specific tests --- lib/ssh/test/ssh_upgrade_SUITE.erl | 23 ++++++++++------------- lib/ssl/test/ssl_upgrade_SUITE.erl | 25 ++++++++++++------------- lib/stdlib/test/ets_SUITE.erl | 18 +----------------- 3 files changed, 23 insertions(+), 43 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl index c0645f3b01..eca8b3663d 100644 --- a/lib/ssh/test/ssh_upgrade_SUITE.erl +++ b/lib/ssh/test/ssh_upgrade_SUITE.erl @@ -46,20 +46,17 @@ all() -> init_per_suite(Config0) -> catch crypto:stop(), - try {crypto:start(), erlang:system_info({wordsize, internal}) == - erlang:system_info({wordsize, external})} of - {ok, true} -> - case ct_release_test:init(Config0) of - {skip, Reason} -> - {skip, Reason}; - Config -> - ssh:start(), - Config - end; - {ok, false} -> - {skip, "Test server will not handle halfwordemulator correctly. Skip as halfwordemulator is deprecated"} + try crypto:start() of + ok -> + case ct_release_test:init(Config0) of + {skip, Reason} -> + {skip, Reason}; + Config -> + ssh:start(), + Config + end catch _:_ -> - {skip, "Crypto did not start"} + {skip, "Crypto did not start"} end. end_per_suite(Config) -> diff --git a/lib/ssl/test/ssl_upgrade_SUITE.erl b/lib/ssl/test/ssl_upgrade_SUITE.erl index 17b0240fe8..fa9593b5dd 100644 --- a/lib/ssl/test/ssl_upgrade_SUITE.erl +++ b/lib/ssl/test/ssl_upgrade_SUITE.erl @@ -39,20 +39,19 @@ all() -> init_per_suite(Config0) -> catch crypto:stop(), - try {crypto:start(), erlang:system_info({wordsize, internal}) == erlang:system_info({wordsize, external})} of - {ok, true} -> - case ct_release_test:init(Config0) of - {skip, Reason} -> - {skip, Reason}; - Config -> - {ok, _} = make_certs:all(?config(data_dir, Config), - ?config(priv_dir, Config)), - ssl_test_lib:cert_options(Config) - end; - {ok, false} -> - {skip, "Test server will not handle halfwordemulator correctly. Skip as halfwordemulator is deprecated"} + try crypto:start() of + ok -> + case ct_release_test:init(Config0) of + {skip, Reason} -> + {skip, Reason}; + Config -> + Result = + {ok, _} = make_certs:all(?config(data_dir, Config), + ?config(priv_dir, Config)), + ssl_test_lib:cert_options(Config) + end catch _:_ -> - {skip, "Crypto did not start"} + {skip, "Crypto did not start"} end. end_per_suite(Config) -> diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index ae431d66d9..1b80f555d7 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -731,10 +731,6 @@ chk_normal_tab_struct_size() -> % ?line ok % end. --define(DB_TREE_STACK_NEED,50). % The static stack for a tree, in halfword pointers are two internal words - % so the stack gets twice as big --define(DB_HASH_SIZEOF_EXTSEG,260). % The segment size in words, in halfword this will be twice as large. - adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) -> %% Adjust for 64-bit, smp, and os: %% Table struct size may differ. @@ -748,19 +744,7 @@ adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) -> % end, TabDiff = ?TAB_STRUCT_SZ, - Mem1 = {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}, - - case {erlang:system_info({wordsize,internal}),erlang:system_info({wordsize,external})} of - %% Halfword, corrections for regular pointers occupying two internal words. - {4,8} -> - {A1,B1,C1,D1} = Mem1, - {A1+4*ets:info(T1, size)+?DB_TREE_STACK_NEED, - B1+3*ets:info(T2, size)+?DB_HASH_SIZEOF_EXTSEG, - C1+3*ets:info(T3, size)+?DB_HASH_SIZEOF_EXTSEG, - D1+3*ets:info(T4, size)+?DB_HASH_SIZEOF_EXTSEG}; - _ -> - Mem1 - end. + {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}. t_whitebox(doc) -> ["Diverse whitebox testes"]; -- cgit v1.2.3 From b71856c612f82a44400f85d8fd2eafcf446202c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Meadows-J=C3=B6nsson?= Date: Thu, 25 Jun 2015 11:29:54 +0200 Subject: Fix formatting of depth option --- lib/ssl/doc/src/ssl.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index f23b71e28b..52d68c1b4a 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -88,7 +88,8 @@

{verify, verify_type()}

| {verify_fun, {fun(), term()}}

-

| {fail_if_no_peer_cert, boolean()} {depth, integer()}

+

| {fail_if_no_peer_cert, boolean()}

+

| {depth, integer()}

| {cert, public_key:der_encoded()}

| {certfile, path()}

| {key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey' -- cgit v1.2.3 From 9356c4b37709b236c076f95fe26637fc332a3b3d Mon Sep 17 00:00:00 2001 From: Red Date: Sun, 28 Jun 2015 10:24:59 -0400 Subject: Updated documentation to match implementation Line number references are with respect to sources in public_key.erl Changes: - pkix_sign replaced public with private (L510) (Certificates are signed by private keys) - pki_asn1_type() added 'CertificateList' (L73) - pkix_sign_types added ecdsa (L404) - pkix_verify added ec_public_key() (L530) - pkix_is_issuer added 'CertificateList' (L569) --- lib/public_key/doc/src/public_key.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 394fe54428..209de2bdf7 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -108,8 +108,9 @@

| 'SubjectPublicKeyInfo'

| 'PrivateKeyInfo'

| 'CertificationRequest'

+

| 'CertificateList'

| 'ECPrivateKey'

-

| 'EcpkParameters'

+

| 'EcpkParameters'

pem_entry () = @@ -433,7 +434,7 @@ pkix_is_issuer(Cert, IssuerCert) -> boolean() Checks if IssuerCert issued Cert. - Cert = der_encoded() | #'OTPCertificate'{} + Cert = der_encoded() | #'OTPCertificate'{} | #'CertificateList'{} IssuerCert = der_encoded() | #'OTPCertificate'{} @@ -698,7 +699,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded() Signs certificate. - Key = rsa_public_key() | dsa_public_key() + Key = rsa_private_key() | dsa_private_key()

Signs an 'OTPTBSCertificate'. Returns the corresponding @@ -713,7 +714,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, AlgorithmId = oid() Signature OID from a certificate or a certificate revocation list. DigestType = rsa_digest_type() | dss_digest_type() - SignatureType = rsa | dsa + SignatureType = rsa | dsa | ecdsa

Translates signature algorithm OID to Erlang digest and signature types. @@ -726,7 +727,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, Verifies PKIX x.509 certificate signature. Cert = der_encoded() - Key = rsa_public_key() | dsa_public_key() + Key = rsa_public_key() | dsa_public_key() | ec_public_key()

Verifies PKIX x.509 certificate signature.

-- cgit v1.2.3 From f940d1cc510b9eb86a2562f190825b17a31acee2 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Wed, 24 Jun 2015 07:59:00 +0200 Subject: Remove erlang:now() and random usage in tests --- lib/mnesia/examples/bench/bench_generate.erl | 40 +++++++--------- lib/mnesia/examples/mnesia_tpcb.erl | 39 +++++---------- lib/mnesia/test/mnesia_atomicity_test.erl | 4 +- lib/mnesia/test/mnesia_config_test.erl | 4 +- lib/mnesia/test/mnesia_cost.erl | 10 ++-- lib/mnesia/test/mnesia_dbn_meters.erl | 55 ++++++++++----------- lib/mnesia/test/mnesia_evil_backup.erl | 2 +- lib/mnesia/test/mnesia_isolation_test.erl | 4 +- lib/mnesia/test/mnesia_test_lib.erl | 4 +- lib/mnesia/test/mnesia_tpcb.erl | 71 ++++++++++++++++++++-------- 10 files changed, 121 insertions(+), 112 deletions(-) (limited to 'lib') diff --git a/lib/mnesia/examples/bench/bench_generate.erl b/lib/mnesia/examples/bench/bench_generate.erl index 7a701812a7..e838f07fbb 100644 --- a/lib/mnesia/examples/bench/bench_generate.erl +++ b/lib/mnesia/examples/bench/bench_generate.erl @@ -153,9 +153,7 @@ generator_init(Monitor, C) -> process_flag(trap_exit, true), Tables = mnesia:system_info(tables), ok = mnesia:wait_for_tables(Tables, infinity), - {_Mega, Sec, Micro} = erlang:now(), - Uniq = lists:sum(binary_to_list(term_to_binary(make_ref()))), - random:seed(Uniq, Sec, Micro), + rand:seed(exsplus), Counters = reset_counters(C, C#config.statistics_detail), SessionTab = ets:new(bench_sessions, [public, {keypos, 1}]), generator_loop(Monitor, C, SessionTab, Counters). @@ -189,9 +187,9 @@ generator_loop(Monitor, C, SessionTab, Counters) -> after 0 -> {Name, {Nodes, Activity, Wlock}, Fun, CommitSessions} = gen_trans(C, SessionTab), - Before = erlang:now(), + Before = erlang:monotonic_time(), Res = call_worker(Nodes, Activity, Fun, Wlock, mnesia_frag), - After = erlang:now(), + After = erlang:monotonic_time(), Elapsed = elapsed(Before, After), post_eval(Monitor, C, Elapsed, Res, Name, CommitSessions, SessionTab, Counters) end. @@ -253,10 +251,8 @@ worker_loop(Parent) -> end. -elapsed({Before1, Before2, Before3}, {After1, After2, After3}) -> - After = After1 * 1000000000000 + After2 * 1000000 + After3, - Before = Before1 * 1000000000000 + Before2 * 1000000 + Before3, - After - Before. +elapsed(Before, After) -> + erlang:convert_time_unit(After-Before, native, micro_seconds). %% Lookup counters get_counters(_C, {table, Tab}) -> @@ -351,7 +347,7 @@ commit_session(Fun) when is_function(Fun, 0) -> %% Randlomly choose a transaction type according to benchmar spec gen_trans(C, SessionTab) when C#config.generator_profile == random -> - case random:uniform(100) of + case rand:uniform(100) of Rand when Rand > 0, Rand =< 25 -> gen_t1(C, SessionTab); Rand when Rand > 25, Rand =< 50 -> gen_t2(C, SessionTab); Rand when Rand > 50, Rand =< 70 -> gen_t3(C, SessionTab); @@ -369,7 +365,7 @@ gen_trans(C, SessionTab) -> end. gen_t1(C, _SessionTab) -> - SubscrId = random:uniform(C#config.n_subscribers) - 1, + SubscrId = rand:uniform(C#config.n_subscribers) - 1, SubscrKey = bench_trans:number_to_key(SubscrId, C), Location = 4711, ChangedBy = <<4711:(8*25)>>, @@ -381,7 +377,7 @@ gen_t1(C, _SessionTab) -> }. gen_t2(C, _SessionTab) -> - SubscrId = random:uniform(C#config.n_subscribers) - 1, + SubscrId = rand:uniform(C#config.n_subscribers) - 1, SubscrKey = bench_trans:number_to_key(SubscrId, C), {t2, nearest_node(SubscrId, sync_dirty, C), @@ -395,9 +391,9 @@ gen_t3(C, SessionTab) -> '$end_of_table' -> %% This generator does not have any session, %% try reading someone elses session details - SubscrId = random:uniform(C#config.n_subscribers) - 1, + SubscrId = rand:uniform(C#config.n_subscribers) - 1, SubscrKey = bench_trans:number_to_key(SubscrId, C), - ServerId = random:uniform(C#config.n_servers) - 1, + ServerId = rand:uniform(C#config.n_servers) - 1, ServerBit = 1 bsl ServerId, {t3, nearest_node(SubscrId, transaction, C), @@ -419,12 +415,12 @@ gen_t4(C, SessionTab) -> %% This generator may already have sessions, %% create a new session and hope that no other %% generator already has occupied it - SubscrId = random:uniform(C#config.n_subscribers) - 1, + SubscrId = rand:uniform(C#config.n_subscribers) - 1, SubscrKey = bench_trans:number_to_key(SubscrId, C), - ServerId = random:uniform(C#config.n_servers) - 1, + ServerId = rand:uniform(C#config.n_servers) - 1, ServerBit = 1 bsl ServerId, Details = <<4711:(8*2000)>>, - DoRollback = (random:uniform(100) =< 2), + DoRollback = (rand:uniform(100) =< 2), Insert = fun() -> ets:insert(SessionTab, {{SubscrId, SubscrKey, ServerId}, self()}) end, {t4, nearest_node(SubscrId, transaction, C), @@ -437,11 +433,11 @@ gen_t5(C, SessionTab) -> '$end_of_table' -> %% This generator does not have any session, %% try to delete someone elses session details - SubscrId = random:uniform(C#config.n_subscribers) - 1, + SubscrId = rand:uniform(C#config.n_subscribers) - 1, SubscrKey = bench_trans:number_to_key(SubscrId, C), - ServerId = random:uniform(C#config.n_servers) - 1, + ServerId = rand:uniform(C#config.n_servers) - 1, ServerBit = 1 bsl ServerId, - DoRollback = (random:uniform(100) =< 2), + DoRollback = (rand:uniform(100) =< 2), {t5, nearest_node(SubscrId, transaction, C), fun(Wlock) -> bench_trans:delete_session_from_server(Wlock, SubscrKey, ServerBit, ServerId, DoRollback) end, @@ -451,7 +447,7 @@ gen_t5(C, SessionTab) -> %% This generator do have at least one session, %% delete it. ServerBit = 1 bsl ServerId, - DoRollback = (random:uniform(100) =< 2), + DoRollback = (rand:uniform(100) =< 2), Delete = fun() -> ets:delete(SessionTab, {SubscrId, SubscrKey, ServerId}) end, {t5, nearest_node(SubscrId, transaction, C), @@ -461,7 +457,7 @@ gen_t5(C, SessionTab) -> end. gen_ping(C, _SessionTab) -> - SubscrId = random:uniform(C#config.n_subscribers) - 1, + SubscrId = rand:uniform(C#config.n_subscribers) - 1, {ping, nearest_node(SubscrId, transaction, C), fun(_Wlock) -> {do_commit, true, []} end, diff --git a/lib/mnesia/examples/mnesia_tpcb.erl b/lib/mnesia/examples/mnesia_tpcb.erl index fde6cf402e..c6eda1c448 100644 --- a/lib/mnesia/examples/mnesia_tpcb.erl +++ b/lib/mnesia/examples/mnesia_tpcb.erl @@ -164,7 +164,7 @@ -record(history, { history_id = {0, 0}, % {DriverId, DriverLocalHistoryid} - time_stamp = now(), % Time point during active transaction + time_stamp = erlang:system_time(), % Time point during active transaction branch_id = 0, % Branch associated with teller teller_id = 0, % Teller invlolved in transaction account_id = 0, % Account updated by transaction @@ -412,9 +412,8 @@ config(remote_frag2_test, ReplicaType) -> config(conflict_benchmark, ReplicaType) -> Remote = nodes(), Local = node(), - Nodes = [Local | Remote], - [{seed, {1326,448637,337711}}, - {db_nodes, Nodes}, + Nodes = [Local | Remote], + [{db_nodes, Nodes}, {driver_nodes, Nodes}, {replica_nodes, Nodes}, {n_drivers_per_node, 10}, @@ -758,7 +757,7 @@ reporter_init(Starter, RC) -> replica_type = Type }, Drivers = start_drivers(RC, TC), - Now = now_to_micros(erlang:now()), + Now = erlang:monotonic_time(), State = #reporter_state{driver_pids = Drivers, run_config = RC, starter_pid = Starter, @@ -896,7 +895,7 @@ add_time(Acc, New) -> -define(AVOID_DIV_ZERO(_What_), try (_What_) catch _:_ -> 0 end). show_report(State) -> - Now = now_to_micros(erlang:now()), + Now = erlang:timestamp(), Iters = State#reporter_state.n_iters, Cfg = State#reporter_state.run_config, Time = State#reporter_state.curr, @@ -924,14 +923,14 @@ show_report(State) -> case Cfg#run_config.send_bench_report of true -> ct_event:notify( - #event{name = benchmark_data, + #event{name = benchmark_data, data = [{suite,"mnesia_tpcb"}, {value,Tps}]}); _ -> ok end, - State#reporter_state{prev_tps = Tps, prev_micros = Now}. + State#reporter_state{prev_tps = Tps, prev_micros = Now}. signed_diff(Iters, Curr, Prev) -> case Iters > 1 of @@ -941,11 +940,6 @@ signed_diff(Iters, Curr, Prev) -> sign(N) when N > 0 -> {"+", N}; sign(N) -> {"", N}. - -now_to_micros({Mega, Secs, Micros}) -> - DT = calendar:now_to_datetime({Mega, Secs, 0}), - S = calendar:datetime_to_gregorian_seconds(DT), - (S * ?SECOND) + Micros. start_drivers(RC, TC) -> LastHistoryId = table_info(history, size), @@ -998,13 +992,11 @@ alloc_local_branches([], Specs, OrphanBranches) -> {Specs, OrphanBranches}. driver_init(DS, AllBranches) -> - case (DS#driver_state.run_config)#run_config.seed of - undefined -> - Seed = erlang:now(); - Seed -> - Seed + Seed = case (DS#driver_state.run_config)#run_config.seed of + undefined -> rand:seed(exsplus); + ExpSeed -> rand:seed(ExpSeed) end, - + DS2 = if DS#driver_state.n_local_branches =:= 0 -> @@ -1058,14 +1050,7 @@ calc_trans(DS) -> %% Generate teller_id, account_id and delta %% Time the TPC-B transaction time_trans(DS) -> - OldSeed = get(random_seed), % Avoid interference with Mnesia - put(random_seed, DS#driver_state.seed), - Random = random:uniform(), - NewSeed = get(random_seed), - case OldSeed of - undefined -> erase(random_seed); - _ -> put(random_seed, OldSeed) - end, + {Random, NewSeed} = rand:uniform_s(DS#driver_state.seed), TC = DS#driver_state.tab_config, RC = DS#driver_state.run_config, diff --git a/lib/mnesia/test/mnesia_atomicity_test.erl b/lib/mnesia/test/mnesia_atomicity_test.erl index 1d9d9c35bc..e3e0eaaf75 100644 --- a/lib/mnesia/test/mnesia_atomicity_test.erl +++ b/lib/mnesia/test/mnesia_atomicity_test.erl @@ -557,8 +557,8 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) -> ?verify_mnesia([N1], [N2]). mk_tab_name(Prefix) -> - {Mega, Sec, Micro} = erlang:now(), - list_to_atom(lists:concat([Prefix , Mega, '_', Sec, '_', Micro])). + Count = erlang:unique_integer([monotonic,positive]), + list_to_atom(lists:concat([Prefix , '_', Count])). lock_waiter_fun(Op, TabName, Val) -> case Op of diff --git a/lib/mnesia/test/mnesia_config_test.erl b/lib/mnesia/test/mnesia_config_test.erl index c8a6a000c6..089fbc06dc 100644 --- a/lib/mnesia/test/mnesia_config_test.erl +++ b/lib/mnesia/test/mnesia_config_test.erl @@ -1206,7 +1206,7 @@ dynamic_ext(Config) when is_list(Config) -> end, [Check(Test) || Test <- [{tab1, ram_copies},{tab2, disc_copies},{tab3, disc_only_copies}]], - T = now(), + T = erlang:unique_integer(), ?match(ok, mnesia:dirty_write({tab0, 42, T})), ?match(ok, mnesia:dirty_write({tab1, 42, T})), ?match(ok, mnesia:dirty_write({tab2, 42, T})), @@ -1284,7 +1284,7 @@ check_storage(Me, Orig, Other) -> mnesia_test_lib:kill_mnesia([Orig]), mnesia_test_lib:kill_mnesia(Other), - T = now(), + T = erlang:unique_integer(), ?match(ok, rpc:call(Me, mnesia, dirty_write, [{tab2, 42, T}])), ?match(stopped, rpc:call(Me, mnesia, stop, [])), ?match(ok, rpc:call(Me, mnesia, start, [])), diff --git a/lib/mnesia/test/mnesia_cost.erl b/lib/mnesia/test/mnesia_cost.erl index ff0108ced1..714dbaef27 100644 --- a/lib/mnesia/test/mnesia_cost.erl +++ b/lib/mnesia/test/mnesia_cost.erl @@ -108,11 +108,11 @@ run(What, OtherInfo, Ops, F) -> run(t, What, OtherInfo, Ops, F). run(How, What, OtherInfo, Ops, F) -> - T1 = erlang:now(), + T1 = erlang:monotonic_time(), statistics(runtime), do_times(How, ?TIMES, F), {_, RunTime} = statistics(runtime), - T2 = erlang:now(), + T2 = erlang:monotonic_time(), RealTime = subtr(T1, T2), report(How, What, OtherInfo, Ops, RunTime, RealTime). @@ -140,11 +140,7 @@ report(dirty, What, OtherInfo, Ops, RunTime, RealTime) -> subtr(Before, After) -> - E =(element(1,After)*1000000000000 - +element(2,After)*1000000+element(3,After)) - - (element(1,Before)*1000000000000 - +element(2,Before)*1000000+element(3,Before)), - E div 1000. + erlang:convert_time_unit(After-Before, native, milli_seconds). do_times(t, I, F) -> do_trans_times(I, F); diff --git a/lib/mnesia/test/mnesia_dbn_meters.erl b/lib/mnesia/test/mnesia_dbn_meters.erl index f97bd973fc..5c3ea08a1d 100644 --- a/lib/mnesia/test/mnesia_dbn_meters.erl +++ b/lib/mnesia/test/mnesia_dbn_meters.erl @@ -93,7 +93,7 @@ some_meters() -> report_meter(Meter) -> Times = 100, Micros = repeat_meter(Meter,{atomic,{0,ignore}},Times) div Times, - io:format("\t~-30w ~-10w micro seconds (mean of ~p repetitions)~n",[Meter,Micros,Times]). + io:format("\t~-30w ~-10w nano seconds (mean of ~p repetitions)~n",[Meter,Micros,Times]). repeat_meter(_Meter,{atomic,{Micros,_Result}},0) -> Micros; @@ -110,9 +110,9 @@ meter(create) -> Key = 1, mnesia:transaction(fun() -> mnesia:delete({simple,Key}) end), Fun = fun() -> - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), R = mnesia:write(#simple{key=Key}), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,R) end, mnesia:transaction(Fun); @@ -121,9 +121,9 @@ meter(open_safe_read) -> Key = 2, mnesia:transaction(fun() -> mnesia:write(#simple{key=Key}) end), Fun = fun() -> - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), R = mnesia:read({simple,Key}), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,R) end, mnesia:transaction(Fun); @@ -132,9 +132,9 @@ meter(open_dirty_read) -> Key = 21, mnesia:transaction(fun() -> mnesia:write(#simple{key=Key}) end), Fun = fun() -> - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), R = mnesia:dirty_read({simple,Key}), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,R) end, mnesia:transaction(Fun); @@ -144,9 +144,9 @@ meter(get_int) -> mnesia:transaction(fun() -> mnesia:write(#simple{key=Key}) end), Fun = fun() -> [Simple] = mnesia:read({simple,Key}), - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), Int = Simple#simple.val, - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,Int) end, mnesia:transaction(Fun); @@ -155,9 +155,9 @@ meter(open_update) -> Key = 3, mnesia:transaction(fun() -> mnesia:write(#simple{key=Key}) end), Fun = fun() -> - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), R = mnesia:wread({simple,Key}), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,R) end, mnesia:transaction(Fun); @@ -167,9 +167,9 @@ meter(put_int) -> mnesia:transaction(fun() -> mnesia:write(#simple{key=Key}) end), Fun = fun() -> [Simple] = mnesia:wread({simple,Key}), - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), R = Simple#simple{val=7}, - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,R) end, mnesia:transaction(Fun); @@ -179,10 +179,10 @@ meter(put_int_and_copy) -> mnesia:transaction(fun() -> mnesia:write(#simple{key=Key}) end), Fun = fun() -> [Simple] = mnesia:wread({simple,Key}), - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), Simple2 = Simple#simple{val=17}, R = mnesia:write(Simple2), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,R) end, mnesia:transaction(Fun); @@ -191,15 +191,15 @@ meter(dirty_put_int_and_copy) -> Key = 55, mnesia:dirty_write(#simple{key=Key}), [Simple] = mnesia:dirty_read({simple,Key}), - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), Simple2 = Simple#simple{val=17}, R = mnesia:dirty_write(Simple2), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), {atomic,elapsed_time(BeforeT,AfterT,R)}; meter(start_trans) -> - BeforeT = erlang:now(), - {atomic,AfterT} = mnesia:transaction(fun() -> erlang:now() end), + BeforeT = erlang:monotonic_time(), + {atomic,AfterT} = mnesia:transaction(fun() -> erlang:monotonic_time() end), {atomic,elapsed_time(BeforeT,AfterT,ok)}; meter(commit_one_update) -> @@ -209,19 +209,19 @@ meter(commit_one_update) -> [Simple] = mnesia:wread({simple,Key}), Simple2 = Simple#simple{val=27}, _R = mnesia:write(Simple2), - erlang:now() + erlang:monotonic_time() end, {atomic,BeforeT} = mnesia:transaction(Fun), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), {atomic,elapsed_time(BeforeT,AfterT,ok)}; meter(delete) -> Key = 7, mnesia:transaction(fun() -> mnesia:write(#simple{key=Key}) end), Fun = fun() -> - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), R = mnesia:delete({simple,Key}), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), elapsed_time(BeforeT,AfterT,R) end, mnesia:transaction(Fun); @@ -229,15 +229,12 @@ meter(delete) -> meter(dirty_delete) -> Key = 75, mnesia:dirty_write(#simple{key=Key}), - BeforeT = erlang:now(), + BeforeT = erlang:monotonic_time(), R = mnesia:dirty_delete({simple,Key}), - AfterT = erlang:now(), + AfterT = erlang:monotonic_time(), {atomic, elapsed_time(BeforeT,AfterT,R)}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Calculate the elapsed time elapsed_time(BeforeT,AfterT,Result) -> - {(element(1,AfterT)*1000000000000 - +element(2,AfterT)*1000000+element(3,AfterT)) - - (element(1,BeforeT)*1000000000000 - +element(2,BeforeT)*1000000+element(3,BeforeT)),Result}. + {erlang:convert_time_unit(AfterT-BeforeT, native, nano_seconds),Result}. diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl index 5392267f79..89f2861661 100644 --- a/lib/mnesia/test/mnesia_evil_backup.erl +++ b/lib/mnesia/test/mnesia_evil_backup.erl @@ -229,7 +229,7 @@ restore(Config, Op) -> [mnesia:dirty_write({Tab1, N, N+1}) || N <- lists:seq(1, 11)], [mnesia:dirty_write({Tab2, N, N+1}) || N <- lists:seq(1, 11)], [mnesia:dirty_write({Tab3, N, N+1}) || N <- lists:seq(1, 11)], - _Res11 = [{Tab1, N, N+1} || N <- lists:seq(1, 11)], + Res21 = [{Tab2, N, N+1} || N <- lists:seq(1, 11)], Res31 = [[{Tab3, N, N+1}, {Tab3, N, N+44}] || N <- lists:seq(1, 10)], diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl index 6abb1f7cdc..b66da6e390 100644 --- a/lib/mnesia/test/mnesia_isolation_test.erl +++ b/lib/mnesia/test/mnesia_isolation_test.erl @@ -1127,7 +1127,9 @@ update_shared(Tab, Me, Acc) -> 0 -> case mnesia:transaction(Update) of {atomic, {ok,Term,W2}} -> - io:format("~p:~p:(~p,~p) ~w@~w~n", [erlang:now(),node(),Me,Acc,Term,W2]), + io:format("~p:~p:(~p,~p) ~w@~w~n", + [erlang:unique_integer([monotonic,positive]), + node(),Me,Acc,Term,W2]), update_shared(Tab, Me, Acc+1); Else -> ?error("Trans failed on ~p with ~p~n" diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl index 035d6bde87..9d3b277e07 100644 --- a/lib/mnesia/test/mnesia_test_lib.erl +++ b/lib/mnesia/test/mnesia_test_lib.erl @@ -238,8 +238,8 @@ slave_start_link() -> slave_start_link(Node) -> [Local, Host] = node_to_name_and_host(Node), - {Mega, Sec, Micro} = erlang:now(), - List = [Local, "_", Mega, "_", Sec, "_", Micro], + Count = erlang:unique_integer([positive]), + List = [Local, "_", Count], Name = list_to_atom(lists:concat(List)), slave_start_link(list_to_atom(Host), Name). diff --git a/lib/mnesia/test/mnesia_tpcb.erl b/lib/mnesia/test/mnesia_tpcb.erl index 3f936591b0..c6eda1c448 100644 --- a/lib/mnesia/test/mnesia_tpcb.erl +++ b/lib/mnesia/test/mnesia_tpcb.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -100,9 +100,13 @@ replica_test/1, sticky_replica_test/1, remote_test/1, - remote_frag2_test/1 + remote_frag2_test/1, + + conflict_benchmark/1 ]). +-include_lib("common_test/include/ct_event.hrl"). + -define(SECOND, 1000000). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -160,7 +164,7 @@ -record(history, { history_id = {0, 0}, % {DriverId, DriverLocalHistoryid} - time_stamp = now(), % Time point during active transaction + time_stamp = erlang:system_time(), % Time point during active transaction branch_id = 0, % Branch associated with teller teller_id = 0, % Teller invlolved in transaction account_id = 0, % Account updated by transaction @@ -192,8 +196,10 @@ driver_nodes = [node()], n_drivers_per_node = 1, use_running_mnesia = false, + seed, stop_after = timer:minutes(15), % Minimum 15 min report_interval = timer:minutes(1), + send_bench_report = false, use_sticky_locks = false, spawn_near_branch = false, activity_type = transaction, @@ -398,8 +404,29 @@ config(remote_frag2_test, ReplicaType) -> {stop_after, timer:minutes(1)}, {report_interval, timer:seconds(10)}, {reuse_history_id, true} + ]; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Ten drivers per node, tables replicated to all nodes, single branch + +config(conflict_benchmark, ReplicaType) -> + Remote = nodes(), + Local = node(), + Nodes = [Local | Remote], + [{db_nodes, Nodes}, + {driver_nodes, Nodes}, + {replica_nodes, Nodes}, + {n_drivers_per_node, 10}, + {n_branches, 1}, + {n_accounts_per_branch, 10}, + {replica_type, ReplicaType}, + {stop_after, timer:minutes(1)}, + {report_interval, timer:seconds(10)}, + {send_bench_report, true}, + {reuse_history_id, true} ]. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start(What, ReplicaType) -> @@ -423,6 +450,9 @@ remote_test(ReplicaType) -> remote_frag2_test(ReplicaType) -> start(remote_frag2_test, ReplicaType). +conflict_benchmark(ReplicaType) -> + start(config(conflict_benchmark, ReplicaType)). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Args is a list of {Key, Val} tuples where Key is a field name %% in either the record tab_config or run_config. Unknown keys are ignored. @@ -727,7 +757,7 @@ reporter_init(Starter, RC) -> replica_type = Type }, Drivers = start_drivers(RC, TC), - Now = now_to_micros(erlang:now()), + Now = erlang:monotonic_time(), State = #reporter_state{driver_pids = Drivers, run_config = RC, starter_pid = Starter, @@ -865,8 +895,9 @@ add_time(Acc, New) -> -define(AVOID_DIV_ZERO(_What_), try (_What_) catch _:_ -> 0 end). show_report(State) -> - Now = now_to_micros(erlang:now()), + Now = erlang:timestamp(), Iters = State#reporter_state.n_iters, + Cfg = State#reporter_state.run_config, Time = State#reporter_state.curr, Max = Time#time.max_time, N = Time#time.n_trans, @@ -889,6 +920,16 @@ show_report(State) -> "duration of longest transaction was ~p milliseconds~n", [Tps, BruttoTps, Max div 1000]) end, + case Cfg#run_config.send_bench_report of + true -> + ct_event:notify( + #event{name = benchmark_data, + data = [{suite,"mnesia_tpcb"}, + {value,Tps}]}); + _ -> + ok + end, + State#reporter_state{prev_tps = Tps, prev_micros = Now}. signed_diff(Iters, Curr, Prev) -> @@ -899,11 +940,6 @@ signed_diff(Iters, Curr, Prev) -> sign(N) when N > 0 -> {"+", N}; sign(N) -> {"", N}. - -now_to_micros({Mega, Secs, Micros}) -> - DT = calendar:now_to_datetime({Mega, Secs, 0}), - S = calendar:datetime_to_gregorian_seconds(DT), - (S * ?SECOND) + Micros. start_drivers(RC, TC) -> LastHistoryId = table_info(history, size), @@ -956,7 +992,11 @@ alloc_local_branches([], Specs, OrphanBranches) -> {Specs, OrphanBranches}. driver_init(DS, AllBranches) -> - Seed = erlang:now(), + Seed = case (DS#driver_state.run_config)#run_config.seed of + undefined -> rand:seed(exsplus); + ExpSeed -> rand:seed(ExpSeed) + end, + DS2 = if DS#driver_state.n_local_branches =:= 0 -> @@ -1010,14 +1050,7 @@ calc_trans(DS) -> %% Generate teller_id, account_id and delta %% Time the TPC-B transaction time_trans(DS) -> - OldSeed = get(random_seed), % Avoid interference with Mnesia - put(random_seed, DS#driver_state.seed), - Random = random:uniform(), - NewSeed = get(random_seed), - case OldSeed of - undefined -> erase(random_seed); - _ -> put(random_seed, OldSeed) - end, + {Random, NewSeed} = rand:uniform_s(DS#driver_state.seed), TC = DS#driver_state.tab_config, RC = DS#driver_state.run_config, -- cgit v1.2.3 From 9aa30b9d0f0286cc8f6b7095a11194f89f0d5adb Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 30 Jun 2015 10:32:27 +0200 Subject: wx: Fix code generator I had changed the (generatade) code without updating the code generator in commit 38cb91a9. Fixed now, and also fixed a typo in the generated licence code. --- lib/wx/api_gen/gen_util.erl | 4 ++-- lib/wx/api_gen/wx_extra/wxEvtHandler.c_src | 2 +- lib/wx/api_gen/wx_gen_cpp.erl | 18 ++++++++--------- lib/wx/api_gen/wxapi.conf | 32 +++++++++++++++--------------- 4 files changed, 28 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/wx/api_gen/gen_util.erl b/lib/wx/api_gen/gen_util.erl index 6bdbb4ca96..ff245a6359 100644 --- a/lib/wx/api_gen/gen_util.erl +++ b/lib/wx/api_gen/gen_util.erl @@ -230,7 +230,7 @@ erl_copyright() -> w("%% Copyright Ericsson AB ~p-~p. All Rights Reserved.~n", [StartYear, CurrentYear]), w("%%~n",[]), - w("%% Licensed under the Apache License, Version 2.0 (the \"License\");,~n",[]), + w("%% Licensed under the Apache License, Version 2.0 (the \"License\");~n",[]), w("%% you may not use this file except in compliance with the License.~n",[]), w("%% You may obtain a copy of the License at~n",[]), w("%%~n",[]), @@ -251,7 +251,7 @@ c_copyright() -> w(" *~n",[]), w(" * Copyright Ericsson AB 2008-~p. All Rights Reserved.~n",[CurrentYear]), w(" *~n",[]), - w(" * Licensed under the Apache License, Version 2.0 (the \"License\");,~n",[]), + w(" * Licensed under the Apache License, Version 2.0 (the \"License\");~n",[]), w(" * you may not use this file except in compliance with the License.~n",[]), w(" * You may obtain a copy of the License at~n",[]), w(" *~n",[]), diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src index 5d20019d8f..5e02066309 100644 --- a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src +++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src @@ -11,7 +11,7 @@ case 100: { // wxEvtHandler::Connect int * class_nameLen = (int *) bp; bp += 4; if(*haveUserData) { - userData = new wxeErlTerm(Ecmd.bin[0]); + userData = new wxeErlTerm(&Ecmd.bin[0]); } int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen; diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index 3120d491b1..2ce6295078 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -206,8 +206,8 @@ gen_funcs(Defs) -> " rt.addAtom(\"ok\");~n" " break;~n" " }~n"), - w(" case WXE_BIN_INCR:~n driver_binary_inc_refc(Ecmd.bin[0]->bin);~n break;~n",[]), - w(" case WXE_BIN_DECR:~n driver_binary_dec_refc(Ecmd.bin[0]->bin);~n break;~n",[]), + w(" case WXE_BIN_INCR:~n driver_binary_inc_refc(Ecmd.bin[0].bin);~n break;~n",[]), + w(" case WXE_BIN_DECR:~n driver_binary_dec_refc(Ecmd.bin[0].bin);~n break;~n",[]), w(" case WXE_INIT_OPENGL:~n wxe_initOpenGL(&rt, bp);~n break;~n",[]), Res = [gen_class(Class) || Class <- Defs], @@ -631,10 +631,10 @@ decode_arg(N,#type{name=Type,base=binary,mod=Mod0},Arg,A0) -> Mod = mods([M || M <- Mod0]), case Arg of arg -> - w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p]->base;~n", + w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p].base;~n", [Mod,Type,N,Mod,Type, next_id(bin_count)]); opt -> - w(" ~s = (~s~s*) Ecmd.bin[~p]->base;~n", + w(" ~s = (~s~s*) Ecmd.bin[~p].base;~n", [N,Mod,Type,next_id(bin_count)]) end, A0; @@ -644,10 +644,10 @@ decode_arg(N,#type{base={term,"wxTreeItemData"},mod=Mod0},Arg,A0) -> BinCnt = next_id(bin_count), case Arg of arg -> - w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n", + w(" ~s~s * ~s = new ~s(Ecmd.bin[~p].size, Ecmd.bin[~p].base);~n", [Mod,Type,N,Type,BinCnt,BinCnt]); opt -> - w(" ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n", + w(" ~s = new ~s(Ecmd.bin[~p].size, Ecmd.bin[~p].base);~n", [N,Type,BinCnt,BinCnt]) end, A0; @@ -656,10 +656,10 @@ decode_arg(N,#type{name=Type,base={term,_},mod=Mod0},Arg,A0) -> BinCnt = next_id(bin_count), case Arg of arg -> - w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]);~n", + w(" ~s~s * ~s = new ~s(&Ecmd.bin[~p]);~n", [Mod,Type,N,Type,BinCnt]); opt -> - w(" ~s = new ~s(Ecmd.bin[~p]);~n", + w(" ~s = new ~s(&Ecmd.bin[~p]);~n", [N,Type,BinCnt]) end, A0; @@ -832,7 +832,7 @@ call_arg(#param{where=c, alt={length,Alt}}) when is_list(Alt) -> "*" ++ Alt ++ "Len"; call_arg(#param{where=c, alt={size,Id}}) when is_integer(Id) -> %% It's a binary - "Ecmd.bin["++ integer_to_list(Id) ++ "]->size"; + "Ecmd.bin["++ integer_to_list(Id) ++ "].size"; call_arg(#param{name=N,def=Def,type=#type{by_val=true,single=true,base=Base}}) when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool -> case Def of diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index 09877f0f5a..a243f21852 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -556,14 +556,14 @@ {"alpha",[in,{base,binary}]}, {{4,pre_hook}, [{c, "if(!static_data) {" - "data = (unsigned char *) malloc(Ecmd.bin[0]->size);" - "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]}, + "data = (unsigned char *) malloc(Ecmd.bin[0].size);" + "memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]}, {{5,pre_hook}, [{c, "if(!static_data) {" - " data = (unsigned char *) malloc(Ecmd.bin[0]->size);" - " alpha = (unsigned char *) malloc(Ecmd.bin[1]->size);" - " memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);" - " memcpy(alpha,Ecmd.bin[1]->base,Ecmd.bin[1]->size);}"}]} + " data = (unsigned char *) malloc(Ecmd.bin[0].size);" + " alpha = (unsigned char *) malloc(Ecmd.bin[1].size);" + " memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);" + " memcpy(alpha,Ecmd.bin[1].base,Ecmd.bin[1].size);}"}]} ]}, '~wxImage',%'AddHandler', 'Blur','BlurHorizontal','BlurVertical', @@ -575,14 +575,14 @@ {"alpha",[in,{base,binary}]}, {{4,pre_hook}, [{c, "if(!static_data) {" - "data = (unsigned char *) malloc(Ecmd.bin[0]->size);" - "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]}, + "data = (unsigned char *) malloc(Ecmd.bin[0].size);" + "memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]}, {{5,pre_hook}, [{c, "if(!static_data) {" - " data = (unsigned char *) malloc(Ecmd.bin[0]->size);" - " alpha = (unsigned char *) malloc(Ecmd.bin[1]->size);" - " memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);" - " memcpy(alpha,Ecmd.bin[1]->base,Ecmd.bin[1]->size);}"}]} + " data = (unsigned char *) malloc(Ecmd.bin[0].size);" + " alpha = (unsigned char *) malloc(Ecmd.bin[1].size);" + " memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);" + " memcpy(alpha,Ecmd.bin[1].base,Ecmd.bin[1].size);}"}]} ]}, 'Destroy','FindFirstUnusedColour', % 'FindHandler', 'GetImageExtWildcard', @@ -608,14 +608,14 @@ {'SetAlpha', [{{2,"alpha"},[in,{base,binary}, {def, none}]}, {{2,pre_hook}, [{c, "if(!static_data) {" - "alpha = (unsigned char *) malloc(Ecmd.bin[0]->size);" - "memcpy(alpha,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]} + "alpha = (unsigned char *) malloc(Ecmd.bin[0].size);" + "memcpy(alpha,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]} ]}, {'SetData', [{"data",[in,{base,binary}]}, {pre_hook, [{c, "if(!static_data) {" - "data = (unsigned char *) malloc(Ecmd.bin[0]->size);" - "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]} + "data = (unsigned char *) malloc(Ecmd.bin[0].size);" + "memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]} ]}, 'SetMask','SetMaskColour','SetMaskFromImage','SetOption', 'SetPalette', -- cgit v1.2.3 From 46285b9f6f9cbe102e22aaf6157e436797404f00 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 30 Jun 2015 10:39:09 +0200 Subject: wx: Add mouse_capture_lost event Needed to avoid asserts when capturing mouse on Windows. --- lib/wx/api_gen/wxapi.conf | 3 ++ lib/wx/c_src/gen/wxe_events.cpp | 8 ++++ lib/wx/include/wx.hrl | 8 +++- lib/wx/src/gen/wxMouseCaptureLostEvent.erl | 65 ++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 lib/wx/src/gen/wxMouseCaptureLostEvent.erl (limited to 'lib') diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index a243f21852..b8241816b2 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -1925,3 +1925,6 @@ {class, wxPopupTransientWindow, wxPopupWindow, [{ifdef, wxUSE_POPUPWIN}], ['wxPopupTransientWindow', '~wxPopupTransientWindow', 'Popup', 'Dismiss']}. + +{class, wxMouseCaptureLostEvent, wxEvent, + [{event,[wxEVT_MOUSE_CAPTURE_LOST]}],[]}. diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp index 88a147cf90..f6a5868b48 100644 --- a/lib/wx/c_src/gen/wxe_events.cpp +++ b/lib/wx/c_src/gen/wxe_events.cpp @@ -302,6 +302,7 @@ void initEventTable() {wxEVT_ACTIVATE, 231, "activate"}, {wxEVT_ACTIVATE_APP, 231, "activate_app"}, {wxEVT_HIBERNATE, 231, "hibernate"}, + {wxEVT_MOUSE_CAPTURE_LOST, 234, "mouse_capture_lost"}, {-1, 0, } }; for(int i=0; event_types[i].ev_type != -1; i++) { @@ -869,6 +870,13 @@ case 231: {// wxActivateEvent rt.addBool(ev->GetActive()); rt.addTupleCount(3); break; +} +case 234: {// wxMouseCaptureLostEvent + evClass = (char*)"wxMouseCaptureLostEvent"; + rt.addAtom((char*)"wxMouseCaptureLost"); + rt.addAtom(Etype->eName); + rt.addTupleCount(2); + break; } } diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl index 6705e34cb9..c2a5831415 100644 --- a/lib/wx/include/wx.hrl +++ b/lib/wx/include/wx.hrl @@ -133,6 +133,10 @@ -type wxSetCursorEventType() :: set_cursor. -type wxSetCursor() :: #wxSetCursor{}. %% Callback event: {@link wxSetCursorEvent} +-record(wxMouseCaptureLost, {type :: wxMouseCaptureLostEventType()}). %% Callback event: {@link wxMouseCaptureLostEvent} +-type wxMouseCaptureLostEventType() :: mouse_capture_lost. +-type wxMouseCaptureLost() :: #wxMouseCaptureLost{}. %% Callback event: {@link wxMouseCaptureLostEvent} + -record(wxFontPicker,{type :: wxFontPickerEventType(), %% Callback event: {@link wxFontPickerEvent} font :: wxFont:wxFont()}). -type wxFontPickerEventType() :: command_fontpicker_changed. @@ -344,8 +348,8 @@ -type wxTreeEventType() :: command_tree_begin_drag | command_tree_begin_rdrag | command_tree_begin_label_edit | command_tree_end_label_edit | command_tree_delete_item | command_tree_get_info | command_tree_set_info | command_tree_item_expanded | command_tree_item_expanding | command_tree_item_collapsed | command_tree_item_collapsing | command_tree_sel_changed | command_tree_sel_changing | command_tree_key_down | command_tree_item_activated | command_tree_item_right_click | command_tree_item_middle_click | command_tree_end_drag | command_tree_state_image_click | command_tree_item_gettooltip | command_tree_item_menu. -type wxTree() :: #wxTree{}. %% Callback event: {@link wxTreeEvent} --type event() :: wxActivate() | wxAuiManager() | wxAuiNotebook() | wxCalendar() | wxChildFocus() | wxClipboardText() | wxClose() | wxColourPicker() | wxCommand() | wxContextMenu() | wxDate() | wxDisplayChanged() | wxErase() | wxFileDirPicker() | wxFocus() | wxFontPicker() | wxGrid() | wxHelp() | wxHtmlLink() | wxIconize() | wxIdle() | wxInitDialog() | wxJoystick() | wxKey() | wxList() | wxMaximize() | wxMenu() | wxMouse() | wxMouseCaptureChanged() | wxMove() | wxNavigationKey() | wxNotebook() | wxPaint() | wxPaletteChanged() | wxQueryNewPalette() | wxSash() | wxScroll() | wxScrollWin() | wxSetCursor() | wxShow() | wxSize() | wxSpin() | wxSplitter() | wxStyledText() | wxSysColourChanged() | wxTaskBarIcon() | wxTree() | wxUpdateUI() | wxWindowCreate() | wxWindowDestroy(). --type wxEventType() :: wxActivateEventType() | wxAuiManagerEventType() | wxAuiNotebookEventType() | wxCalendarEventType() | wxChildFocusEventType() | wxClipboardTextEventType() | wxCloseEventType() | wxColourPickerEventType() | wxCommandEventType() | wxContextMenuEventType() | wxDateEventType() | wxDisplayChangedEventType() | wxEraseEventType() | wxFileDirPickerEventType() | wxFocusEventType() | wxFontPickerEventType() | wxGridEventType() | wxHelpEventType() | wxHtmlLinkEventType() | wxIconizeEventType() | wxIdleEventType() | wxInitDialogEventType() | wxJoystickEventType() | wxKeyEventType() | wxListEventType() | wxMaximizeEventType() | wxMenuEventType() | wxMouseCaptureChangedEventType() | wxMouseEventType() | wxMoveEventType() | wxNavigationKeyEventType() | wxNotebookEventType() | wxPaintEventType() | wxPaletteChangedEventType() | wxQueryNewPaletteEventType() | wxSashEventType() | wxScrollEventType() | wxScrollWinEventType() | wxSetCursorEventType() | wxShowEventType() | wxSizeEventType() | wxSpinEventType() | wxSplitterEventType() | wxStyledTextEventType() | wxSysColourChangedEventType() | wxTaskBarIconEventType() | wxTreeEventType() | wxUpdateUIEventType() | wxWindowCreateEventType() | wxWindowDestroyEventType(). +-type event() :: wxActivate() | wxAuiManager() | wxAuiNotebook() | wxCalendar() | wxChildFocus() | wxClipboardText() | wxClose() | wxColourPicker() | wxCommand() | wxContextMenu() | wxDate() | wxDisplayChanged() | wxErase() | wxFileDirPicker() | wxFocus() | wxFontPicker() | wxGrid() | wxHelp() | wxHtmlLink() | wxIconize() | wxIdle() | wxInitDialog() | wxJoystick() | wxKey() | wxList() | wxMaximize() | wxMenu() | wxMouse() | wxMouseCaptureChanged() | wxMouseCaptureLost() | wxMove() | wxNavigationKey() | wxNotebook() | wxPaint() | wxPaletteChanged() | wxQueryNewPalette() | wxSash() | wxScroll() | wxScrollWin() | wxSetCursor() | wxShow() | wxSize() | wxSpin() | wxSplitter() | wxStyledText() | wxSysColourChanged() | wxTaskBarIcon() | wxTree() | wxUpdateUI() | wxWindowCreate() | wxWindowDestroy(). +-type wxEventType() :: wxActivateEventType() | wxAuiManagerEventType() | wxAuiNotebookEventType() | wxCalendarEventType() | wxChildFocusEventType() | wxClipboardTextEventType() | wxCloseEventType() | wxColourPickerEventType() | wxCommandEventType() | wxContextMenuEventType() | wxDateEventType() | wxDisplayChangedEventType() | wxEraseEventType() | wxFileDirPickerEventType() | wxFocusEventType() | wxFontPickerEventType() | wxGridEventType() | wxHelpEventType() | wxHtmlLinkEventType() | wxIconizeEventType() | wxIdleEventType() | wxInitDialogEventType() | wxJoystickEventType() | wxKeyEventType() | wxListEventType() | wxMaximizeEventType() | wxMenuEventType() | wxMouseCaptureChangedEventType() | wxMouseCaptureLostEventType() | wxMouseEventType() | wxMoveEventType() | wxNavigationKeyEventType() | wxNotebookEventType() | wxPaintEventType() | wxPaletteChangedEventType() | wxQueryNewPaletteEventType() | wxSashEventType() | wxScrollEventType() | wxScrollWinEventType() | wxSetCursorEventType() | wxShowEventType() | wxSizeEventType() | wxSpinEventType() | wxSplitterEventType() | wxStyledTextEventType() | wxSysColourChangedEventType() | wxTaskBarIconEventType() | wxTreeEventType() | wxUpdateUIEventType() | wxWindowCreateEventType() | wxWindowDestroyEventType(). %% Hardcoded Records -record(wxMouseState, {x :: integer(), y :: integer(), diff --git a/lib/wx/src/gen/wxMouseCaptureLostEvent.erl b/lib/wx/src/gen/wxMouseCaptureLostEvent.erl new file mode 100644 index 0000000000..a7e68a2d2f --- /dev/null +++ b/lib/wx/src/gen/wxMouseCaptureLostEvent.erl @@ -0,0 +1,65 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: wxMouseCaptureLostEvent. +%%
Use {@link wxEvtHandler:connect/3.} with EventType:
+%%
mouse_capture_lost
+%% See also the message variant {@link wxEvtHandler:wxMouseCaptureLost(). #wxMouseCaptureLost{}} event record type. +%% +%%

This class is derived (and can use functions) from: +%%
{@link wxEvent} +%%

+%% @type wxMouseCaptureLostEvent(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxMouseCaptureLostEvent). +-include("wxe.hrl"). +-export([]). + +%% inherited exports +-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1, + resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]). + +-export_type([wxMouseCaptureLostEvent/0]). +%% @hidden +parent_class(wxEvent) -> true; +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxMouseCaptureLostEvent() :: wx:wx_object(). + %% From wxEvent +%% @hidden +stopPropagation(This) -> wxEvent:stopPropagation(This). +%% @hidden +skip(This, Options) -> wxEvent:skip(This, Options). +%% @hidden +skip(This) -> wxEvent:skip(This). +%% @hidden +shouldPropagate(This) -> wxEvent:shouldPropagate(This). +%% @hidden +resumePropagation(This,PropagationLevel) -> wxEvent:resumePropagation(This,PropagationLevel). +%% @hidden +isCommandEvent(This) -> wxEvent:isCommandEvent(This). +%% @hidden +getTimestamp(This) -> wxEvent:getTimestamp(This). +%% @hidden +getSkipped(This) -> wxEvent:getSkipped(This). +%% @hidden +getId(This) -> wxEvent:getId(This). -- cgit v1.2.3 From 4246d988b53947c7a7f0ce4943a83af38d129435 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 30 Jun 2015 12:53:02 +0200 Subject: wx: Send wxWdigets assert to error logger Instead of popping up an annoying msgbox --- lib/wx/c_src/wxe_impl.cpp | 19 +++++++++++++++++++ lib/wx/c_src/wxe_impl.h | 5 +++++ lib/wx/test/wx_class_SUITE.erl | 6 +++++- 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index 6236fb708e..e6ed236962 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -181,6 +181,25 @@ void WxeApp::dummy_close(wxEvent& Ev) { // windows open, and this will kill the erlang, override default handling } +void WxeApp::OnAssertFailure(const wxChar *file, int line, const wxChar *cfunc, + const wxChar *cond, const wxChar *cmsgUser) { + wxString msg; + wxString func(cfunc); + wxString msgUser(cmsgUser); + + msg.Printf(wxT("wxWidgets Assert failure: %s(%d): \"%s\""), + file, line, cond); + if ( !func.empty() ) { + msg << wxT(" in ") << func << wxT("()"); + } + // and the message itself + if ( !msgUser.empty() ) { + msg << wxT(" : ") << msgUser; + } + + send_msg("error", &msg); +} + // Called by wx thread void WxeApp::idle(wxIdleEvent& event) { event.Skip(true); diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h index d8241d11a4..d6d3095a0f 100644 --- a/lib/wx/c_src/wxe_impl.h +++ b/lib/wx/c_src/wxe_impl.h @@ -57,9 +57,14 @@ class WxeApp : public wxApp { public: virtual bool OnInit(); + + virtual void OnAssertFailure(const wxChar *file, int line, const wxChar *func, + const wxChar *cond, const wxChar *msg); + #ifdef _MACOSX virtual void MacOpenFile(const wxString &filename); #endif + void shutdown(wxeMetaCommand& event); int dispatch(wxeFifo *, int, int); diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index fd6023a820..ebae32aeb8 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -386,13 +386,17 @@ listCtrlSort(Config) -> io:format("Sorted ~p ~n",[Time]), Item = wxListItem:new(), + + %% Force an assert on (and debug compiled) which 3.0 is by default + wxListItem:setId(Item, 200), + io:format("Got ~p ~n", [wxListCtrl:getItem(LC, Item)]), + wxListItem:setMask(Item, ?wxLIST_MASK_TEXT), _List = wx:map(fun(Int) -> wxListItem:setId(Item, Int), ?m(true, wxListCtrl:getItem(LC, Item)), io:format("~p: ~s~n",[Int, wxListItem:getText(Item)]) end, lists:seq(0,10)), - wxListItem:destroy(Item), wx_test_lib:wx_destroy(Frame,Config). -- cgit v1.2.3 From 1be39649f2996c20f4afd6772c7f6fa27c859416 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 22 Jun 2015 20:03:49 +0200 Subject: ssh: delete ssh_unicode_SUITE The tests now have supersets in ssh_basic_SUITE and ssh_sftp_SUITE. --- lib/ssh/test/ssh_unicode_SUITE.erl | 589 --------------------- lib/ssh/test/ssh_unicode_SUITE_data/sftp.txt | 1 - .../sftp\347\221\236\347\202\271.txt" | 1 - .../test/ssh_unicode_SUITE_data/ssh_host_dsa_key | 13 - .../ssh_unicode_SUITE_data/ssh_host_dsa_key.pub | 11 - 5 files changed, 615 deletions(-) delete mode 100644 lib/ssh/test/ssh_unicode_SUITE.erl delete mode 100644 lib/ssh/test/ssh_unicode_SUITE_data/sftp.txt delete mode 100644 "lib/ssh/test/ssh_unicode_SUITE_data/sftp\347\221\236\347\202\271.txt" delete mode 100644 lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key delete mode 100644 lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key.pub (limited to 'lib') diff --git a/lib/ssh/test/ssh_unicode_SUITE.erl b/lib/ssh/test/ssh_unicode_SUITE.erl deleted file mode 100644 index f0b97554b3..0000000000 --- a/lib/ssh/test/ssh_unicode_SUITE.erl +++ /dev/null @@ -1,589 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2014. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% gerl +fnu -%% ct:run_test([{suite,"ssh_unicode_SUITE"}, {logdir,"LOG"}]). - --module(ssh_unicode_SUITE). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include_lib("common_test/include/ct.hrl"). --include_lib("kernel/include/file.hrl"). - -% Default timetrap timeout --define(default_timeout, ?t:minutes(1)). - --define(USER, "åke高兴"). --define(PASSWD, "ärlig日本じん"). --define('sftp.txt', "sftp瑞点.txt"). --define('test.txt', "testハンス.txt"). --define('link_test.txt', "link_test語.txt"). - --define(bindata, unicode:characters_to_binary("foobar å 一二三四いちにさんち") ). - --define(NEWLINE, <<"\r\n">>). - -%%-------------------------------------------------------------------- -%% Common Test interface functions ----------------------------------- -%%-------------------------------------------------------------------- - -%% suite() -> -%% [{ct_hooks,[ts_install_cth]}]. - -all() -> - [{group, sftp}, - {group, shell} - ]. - - -init_per_suite(Config) -> - catch crypto:stop(), - case {file:native_name_encoding(), (catch crypto:start())} of - {utf8, ok} -> - ssh:start(), - Config; - {utf8, _} -> - {skip,"Could not start crypto!"}; - _ -> - {skip,"Not unicode filename enabled emulator"} - end. - -end_per_suite(Config) -> - ssh:stop(), - crypto:stop(), - Config. - -%%-------------------------------------------------------------------- -groups() -> - [{shell, [], [shell_no_unicode, shell_unicode_string]}, - {sftp, [], [open_close_file, open_close_dir, read_file, read_dir, - write_file, rename_file, mk_rm_dir, remove_file, links, - retrieve_attributes, set_attributes, async_read, async_read_bin, - async_write - %% , position, pos_read, pos_write - ]}]. - -init_per_group(Group, Config) when Group==sftp - ; Group==shell -> - PrivDir = ?config(priv_dir, Config), - SysDir = ?config(data_dir, Config), - Sftpd = - ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, PrivDir}, - {user_passwords, [{?USER, ?PASSWD}]}]), - [{group,Group}, {sftpd, Sftpd} | Config]; - -init_per_group(Group, Config) -> - [{group,Group} | Config]. - - -end_per_group(erlang_server, Config) -> - Config; -end_per_group(_, Config) -> - Config. - -%%-------------------------------------------------------------------- -init_per_testcase(_Case, Config) -> - prep(Config), - TmpConfig0 = lists:keydelete(watchdog, 1, Config), - TmpConfig = lists:keydelete(sftp, 1, TmpConfig0), - Dog = ct:timetrap(?default_timeout), - - case ?config(group, Config) of - sftp -> - {_Pid, Host, Port} = ?config(sftpd, Config), - {ok, ChannelPid, Connection} = - ssh_sftp:start_channel(Host, Port, - [{user, ?USER}, - {password, ?PASSWD}, - {user_interaction, false}, - {silently_accept_hosts, true}]), - Sftp = {ChannelPid, Connection}, - [{sftp, Sftp}, {watchdog, Dog} | TmpConfig]; - shell -> - UserDir = ?config(priv_dir, Config), - process_flag(trap_exit, true), - {_Pid, _Host, Port} = ?config(sftpd, Config), - ct:sleep(500), - IO = ssh_test_lib:start_io_server(), - Shell = ssh_test_lib:start_shell(Port, IO, UserDir, - [{silently_accept_hosts, true}, - {user,?USER},{password,?PASSWD}]), -%%ct:pal("IO=~p, Shell=~p, self()=~p",[IO,Shell,self()]), - wait_for_erlang_first_line([{io,IO}, {shell,Shell} | Config]) - end. - - -wait_for_erlang_first_line(Config) -> - receive - {'EXIT', _, _} -> - {fail,no_ssh_connection}; - <<"Eshell ",_/binary>> = ErlShellStart -> -%% ct:pal("Erlang shell start: ~p~n", [ErlShellStart]), - Config; - Other -> - ct:pal("Unexpected answer from ssh server: ~p",[Other]), - {fail,unexpected_answer} - after 10000 -> - ct:pal("No answer from ssh-server"), - {fail,timeout} - end. - - - -end_per_testcase(rename_file, Config) -> - PrivDir = ?config(priv_dir, Config), - NewFileName = filename:join(PrivDir, ?'test.txt'), - file:delete(NewFileName), - end_per_testcase(Config); -end_per_testcase(_TC, Config) -> - end_per_testcase(Config). - -end_per_testcase(Config) -> - catch exit(?config(shell,Config), kill), - case ?config(sftp, Config) of - {Sftp, Connection} -> - ssh_sftp:stop_channel(Sftp), - ssh:close(Connection); - _ -> - ok - end. - -%%-------------------------------------------------------------------- -%% Test Cases -------------------------------------------------------- - --define(chk_expected(Received,Expected), - (fun(R_,E_) when R_==E_ -> ok; - (R_,E_) -> ct:pal("Expected: ~p~nReceived: ~p~n", [E_,R_]), - E_ = R_ - end)(Received,Expected)). - --define(receive_chk(Ref,Expected), - (fun(E__) -> - receive - {async_reply, Ref, Received} when Received==E__ -> - ?chk_expected(Received, E__); - {async_reply, Ref, Received} when Received=/=E__ -> - ct:pal("Expected: ~p~nReceived: ~p~n", [E__,Received]), - E__ = Received; - Msg -> - ct:pal("Expected (Ref=~p): ~p", [Ref,E__]), - ct:fail(Msg) - end - end)(Expected)). - -%%-------------------------------------------------------------------- - - -open_close_file() -> - [{doc, "Test API functions open/3 and close/2"}]. -open_close_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - {Sftp, _} = ?config(sftp, Config), - - lists:foreach( - fun(Mode) -> - ct:log("Mode: ~p",[Mode]), - %% list_dir(PrivDir), - ok = open_close_file(Sftp, FileName, Mode) - end, - [ - [read], - [write], - [write, creat], - [write, trunc], - [append], - [read, binary] - ]). - -open_close_file(Server, File, Mode) -> - {ok, Handle} = ssh_sftp:open(Server, File, Mode), - ok = ssh_sftp:close(Server, Handle). - -%%-------------------------------------------------------------------- -open_close_dir() -> - [{doc, "Test API functions opendir/2 and close/2"}]. -open_close_dir(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - {Sftp, _} = ?config(sftp, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - - {ok, Handle} = ssh_sftp:opendir(Sftp, PrivDir), - ok = ssh_sftp:close(Sftp, Handle), - {error, _} = ssh_sftp:opendir(Sftp, FileName). - -%%-------------------------------------------------------------------- -read_file() -> - [{doc, "Test API funtion read_file/2"}]. -read_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - {Sftp, _} = ?config(sftp, Config), - ?chk_expected(ssh_sftp:read_file(Sftp,FileName), file:read_file(FileName)). - -%%-------------------------------------------------------------------- -read_dir() -> - [{doc,"Test API function list_dir/2"}]. -read_dir(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - {Sftp, _} = ?config(sftp, Config), - {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), - ct:pal("sftp list dir: ~ts~n", [Files]). - -%%-------------------------------------------------------------------- -write_file() -> - [{doc, "Test API function write_file/2"}]. -write_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - {Sftp, _} = ?config(sftp, Config), - ok = ssh_sftp:write_file(Sftp, FileName, [?bindata]), - ?chk_expected(file:read_file(FileName), {ok,?bindata}). - -%%-------------------------------------------------------------------- -remove_file() -> - [{doc,"Test API function delete/2"}]. -remove_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - {Sftp, _} = ?config(sftp, Config), - - {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), - true = lists:member(filename:basename(FileName), Files), - ok = ssh_sftp:delete(Sftp, FileName), - {ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir), - false = lists:member(filename:basename(FileName), NewFiles), - {error, _} = ssh_sftp:delete(Sftp, FileName). -%%-------------------------------------------------------------------- -rename_file() -> - [{doc, "Test API function rename_file/2"}]. -rename_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - NewFileName = filename:join(PrivDir, ?'test.txt'), - - {Sftp, _} = ?config(sftp, Config), - {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), - ct:pal("FileName: ~ts~nFiles: ~ts~n", [FileName, [[$\n,$ ,F]||F<-Files] ]), - true = lists:member(filename:basename(FileName), Files), - false = lists:member(filename:basename(NewFileName), Files), - ok = ssh_sftp:rename(Sftp, FileName, NewFileName), - {ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir), - ct:pal("FileName: ~ts, Files: ~ts~n", [FileName, [[$\n,F]||F<-NewFiles] ]), - - false = lists:member(filename:basename(FileName), NewFiles), - true = lists:member(filename:basename(NewFileName), NewFiles). - -%%-------------------------------------------------------------------- -mk_rm_dir() -> - [{doc,"Test API functions make_dir/2, del_dir/2"}]. -mk_rm_dir(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - {Sftp, _} = ?config(sftp, Config), - - DirName = filename:join(PrivDir, "test"), - ok = ssh_sftp:make_dir(Sftp, DirName), - ok = ssh_sftp:del_dir(Sftp, DirName), - NewDirName = filename:join(PrivDir, "foo/bar"), - {error, _} = ssh_sftp:make_dir(Sftp, NewDirName), - {error, _} = ssh_sftp:del_dir(Sftp, PrivDir). - -%%-------------------------------------------------------------------- -links() -> - [{doc,"Tests API function make_symlink/3"}]. -links(Config) when is_list(Config) -> - case os:type() of - {win32, _} -> - {skip, "Links are not fully supported by windows"}; - _ -> - {Sftp, _} = ?config(sftp, Config), - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - LinkFileName = filename:join(PrivDir, ?'link_test.txt'), - - ok = ssh_sftp:make_symlink(Sftp, LinkFileName, FileName), - {ok, FileName} = ssh_sftp:read_link(Sftp, LinkFileName) - end. - -%%-------------------------------------------------------------------- -retrieve_attributes() -> - [{doc, "Test API function read_file_info/3"}]. -retrieve_attributes(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - - {Sftp, _} = ?config(sftp, Config), - {ok, FileInfo} = ssh_sftp:read_file_info(Sftp, FileName), - {ok, NewFileInfo} = file:read_file_info(FileName), - - %% TODO comparison. There are some differences now is that ok? - ct:pal("SFTP: ~p~nFILE: ~p~n", [FileInfo, NewFileInfo]). - -%%-------------------------------------------------------------------- -set_attributes() -> - [{doc,"Test API function write_file_info/3"}]. -set_attributes(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'test.txt'), - - {Sftp, _} = ?config(sftp, Config), - {ok,Fd} = file:open(FileName, write), - io:put_chars(Fd,"foo"), - ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#400}), - {error, eacces} = file:write_file(FileName, "hello again"), - ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#600}), - ok = file:write_file(FileName, "hello again"). - -%%-------------------------------------------------------------------- - -async_read() -> - [{doc,"Test API aread/3"}]. -async_read(Config) when is_list(Config) -> - do_async_read(Config, false). - -async_read_bin() -> - [{doc,"Test API aread/3"}]. -async_read_bin(Config) when is_list(Config) -> - do_async_read(Config, true). - -do_async_read(Config, BinaryFlag) -> - {Sftp, _} = ?config(sftp, Config), - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'sftp.txt'), - {ok,ExpDataBin} = file:read_file(FileName), - ExpData = case BinaryFlag of - true -> ExpDataBin; - false -> binary_to_list(ExpDataBin) - end, - {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read|case BinaryFlag of - true -> [binary]; - false -> [] - end]), - {async, Ref} = ssh_sftp:aread(Sftp, Handle, 20), - ?receive_chk(Ref, {ok,ExpData}). - -%%-------------------------------------------------------------------- -async_write() -> - [{doc,"Test API awrite/3"}]. -async_write(Config) when is_list(Config) -> - {Sftp, _} = ?config(sftp, Config), - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'test.txt'), - {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]), - Expected = ?bindata, - {async, Ref} = ssh_sftp:awrite(Sftp, Handle, Expected), - - receive - {async_reply, Ref, ok} -> - {ok, Data} = file:read_file(FileName), - ?chk_expected(Data, Expected); - Msg -> - ct:fail(Msg) - end. - -%%-------------------------------------------------------------------- - -position() -> - [{doc, "Test API functions position/3"}]. -position(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'test.txt'), - {Sftp, _} = ?config(sftp, Config), - - Data = list_to_binary("1234567890"), - ssh_sftp:write_file(Sftp, FileName, [Data]), - {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]), - - {ok, 3} = ssh_sftp:position(Sftp, Handle, {bof, 3}), - {ok, "4"} = ssh_sftp:read(Sftp, Handle, 1), - - {ok, 10} = ssh_sftp:position(Sftp, Handle, eof), - eof = ssh_sftp:read(Sftp, Handle, 1), - - {ok, 6} = ssh_sftp:position(Sftp, Handle, {bof, 6}), - {ok, "7"} = ssh_sftp:read(Sftp, Handle, 1), - - {ok, 9} = ssh_sftp:position(Sftp, Handle, {cur, 2}), - {ok, "0"} = ssh_sftp:read(Sftp, Handle, 1), - - {ok, 0} = ssh_sftp:position(Sftp, Handle, bof), - {ok, "1"} = ssh_sftp:read(Sftp, Handle, 1), - - {ok, 1} = ssh_sftp:position(Sftp, Handle, cur), - {ok, "2"} = ssh_sftp:read(Sftp, Handle, 1). - -%%-------------------------------------------------------------------- -pos_read() -> - [{doc,"Test API functions pread/3 and apread/3"}]. -pos_read(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'test.txt'), - {Sftp, _} = ?config(sftp, Config), - Data = ?bindata, - ssh_sftp:write_file(Sftp, FileName, [Data]), - - {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]), - {async, Ref} = ssh_sftp:apread(Sftp, Handle, {bof,5}, 4), - - ?receive_chk(Ref, {ok,binary_part(Data,5,4)}), - ?chk_expected(ssh_sftp:pread(Sftp,Handle,{bof,4},4), {ok,binary_part(Data,4,4)}). - - -%%-------------------------------------------------------------------- -pos_write() -> - [{doc,"Test API functions pwrite/4 and apwrite/4"}]. -pos_write(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, ?'test.txt'), - {Sftp, _} = ?config(sftp, Config), - - {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]), - - Data = unicode:characters_to_list("再见"), - ssh_sftp:write_file(Sftp, FileName, [Data]), - - NewData = unicode:characters_to_list(" さようなら"), - {async, Ref} = ssh_sftp:apwrite(Sftp, Handle, {bof, 2}, NewData), - ?receive_chk(Ref, ok), - - ok = ssh_sftp:pwrite(Sftp, Handle, eof, unicode:characters_to_list(" adjö ")), - - ?chk_expected(ssh_sftp:read_file(Sftp,FileName), - {ok,unicode:characters_to_binary("再见 さようなら adjö ")}). - -%%-------------------------------------------------------------------- -sftp_nonexistent_subsystem() -> - [{doc, "Try to execute sftp subsystem on a server that does not support it"}]. -sftp_nonexistent_subsystem(Config) when is_list(Config) -> - {_,Host, Port} = ?config(sftpd, Config), - {error,"server failed to start sftp subsystem"} = - ssh_sftp:start_channel(Host, Port, - [{user_interaction, false}, - {user, ?USER}, - {password, ?PASSWD}, - {silently_accept_hosts, true}]). - -%%-------------------------------------------------------------------- -shell_no_unicode(Config) -> - do_shell(?config(io,Config), - [new_prompt, - {type,"io:format(\"hej ~p~n\",[42])."}, - {expect,"hej 42"} - ]). - -%%-------------------------------------------------------------------- -shell_unicode_string(Config) -> - do_shell(?config(io,Config), - [new_prompt, - {type,"io:format(\"こにちわ~ts~n\",[\"四二\"])."}, - {expect,"こにちわ四二"}, - {expect,"ok"} - ]). - -%%-------------------------------------------------------------------- -%% Internal functions ------------------------------------------------ -%%-------------------------------------------------------------------- -prep(Config) -> - PrivDir = ?config(priv_dir, Config), - TestFile = filename:join(PrivDir, ?'sftp.txt'), - TestFile1 = filename:join(PrivDir, ?'test.txt'), - TestLink = filename:join(PrivDir, ?'link_test.txt'), - - file:delete(TestFile), - file:delete(TestFile1), - file:delete(TestLink), - - %% Initial config - DataDir = ?config(data_dir, Config), - FileName = filename:join(DataDir, ?'sftp.txt'), - {ok,_BytesCopied} = file:copy(FileName, TestFile), - Mode = 8#00400 bor 8#00200 bor 8#00040, % read & write owner, read group - {ok, FileInfo} = file:read_file_info(TestFile), - ok = file:write_file_info(TestFile, - FileInfo#file_info{mode = Mode}). - - -%% list_dir(Dir) -> -%% ct:pal("prep/1: ls(~p):~n~p~n~ts",[Dir, file:list_dir(Dir), -%% begin -%% {ok,DL} = file:list_dir(Dir), -%% [[$\n|FN] || FN <- DL] -%% end]). - - -%%-------------------------------------------------------------------- -do_shell(IO, List) -> do_shell(IO, 0, List). - -do_shell(IO, N, [new_prompt|More]) -> - do_shell(IO, N+1, More); - -do_shell(IO, N, Ops=[{Order,Arg}|More]) -> - receive - X = <<"\r\n">> -> -%% ct:pal("Skip newline ~p",[X]), - do_shell(IO, N, Ops); - - < ">> when (P1-$0)==N -> - do_shell_prompt(IO, N, Order, Arg, More); - - < ">> when (P1-$0)*10 + (P2-$0) == N -> - do_shell_prompt(IO, N, Order, Arg, More); - - Err when element(1,Err)==error -> - ct:fail("do_shell error: ~p~n",[Err]); - - RecBin when Order==expect ; Order==expect_echo -> -%% ct:pal("received ~p",[RecBin]), - RecStr = string:strip(unicode:characters_to_list(RecBin)), - ExpStr = string:strip(Arg), - case lists:prefix(ExpStr, RecStr) of - true when Order==expect -> - ct:pal("Matched ~ts",[RecStr]), - do_shell(IO, N, More); - true when Order==expect_echo -> - ct:pal("Matched echo ~ts",[RecStr]), - do_shell(IO, N, More); - false -> - ct:fail("*** Expected ~p, but got ~p",[string:strip(ExpStr),RecStr]) - end - after 10000 -> - case Order of - expect -> ct:fail("timeout, expected ~p",[string:strip(Arg)]); - type -> ct:fail("timeout, no prompt") - end - end; - -do_shell(_, _, []) -> - ok. - - -do_shell_prompt(IO, N, type, Str, More) -> -%% ct:pal("Matched prompt ~p to trigger sending of next line to server",[N]), - IO ! {input, self(), Str++"\r\n"}, - ct:pal("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]), - do_shell(IO, N, [{expect_echo,Str}|More]); % expect echo of the sent line -do_shell_prompt(IO, N, Op, Str, More) -> -%% ct:pal("Matched prompt ~p",[N]), - do_shell(IO, N, [{Op,Str}|More]). - -%%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_unicode_SUITE_data/sftp.txt b/lib/ssh/test/ssh_unicode_SUITE_data/sftp.txt deleted file mode 100644 index 3eaaddca21..0000000000 --- a/lib/ssh/test/ssh_unicode_SUITE_data/sftp.txt +++ /dev/null @@ -1 +0,0 @@ -åäöÅÄÖ瑞語 diff --git "a/lib/ssh/test/ssh_unicode_SUITE_data/sftp\347\221\236\347\202\271.txt" "b/lib/ssh/test/ssh_unicode_SUITE_data/sftp\347\221\236\347\202\271.txt" deleted file mode 100644 index 3eaaddca21..0000000000 --- "a/lib/ssh/test/ssh_unicode_SUITE_data/sftp\347\221\236\347\202\271.txt" +++ /dev/null @@ -1 +0,0 @@ -åäöÅÄÖ瑞語 diff --git a/lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key deleted file mode 100644 index 51ab6fbd88..0000000000 --- a/lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK -wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q -diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA -l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X -skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF -Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP -ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah -/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U -ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W -Lv62jKcdskxNyz2NQoBx ------END DSA PRIVATE KEY----- - diff --git a/lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key.pub deleted file mode 100644 index 4dbb1305b0..0000000000 --- a/lib/ssh/test/ssh_unicode_SUITE_data/ssh_host_dsa_key.pub +++ /dev/null @@ -1,11 +0,0 @@ ----- BEGIN SSH2 PUBLIC KEY ---- -AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j -YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 -KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU -aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI -fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT -MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh -DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 -wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 -/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== ----- END SSH2 PUBLIC KEY ---- -- cgit v1.2.3 From ab5fa21f07203af27d5c685c9698de5149eae8d0 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 22 Jun 2015 19:52:33 +0200 Subject: ssh: new unicode tests --- lib/ssh/test/ssh_basic_SUITE.erl | 137 +- lib/ssh/test/ssh_relay.erl | 2 +- lib/ssh/test/ssh_sftp_SUITE.erl | 301 +- .../F\344\270\200.txt" | 1 + .../big.txt" | 16384 +++++++++++++++++++ .../d1/f1" | 1 + .../d1/f2" | 1 + .../f2.txt" | 1 + 8 files changed, 16724 insertions(+), 104 deletions(-) create mode 100644 "lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/F\344\270\200.txt" create mode 100644 "lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/big.txt" create mode 100644 "lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f1" create mode 100644 "lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f2" create mode 100644 "lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f2.txt" (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 2b3fadbbf4..9ff3eb8d0b 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -99,7 +99,9 @@ groups() -> basic_tests() -> [send, close, peername_sockname, - exec, exec_compressed, shell, cli, known_hosts, + exec, exec_compressed, + shell, shell_no_unicode, shell_unicode_string, + cli, known_hosts, idle_time, openssh_zlib_basic_test, misc_ssh_options, inet_option]. @@ -215,6 +217,25 @@ end_per_group(internal_error, Config) -> end_per_group(_, Config) -> Config. %%-------------------------------------------------------------------- +init_per_testcase(TC, Config) when TC==shell_no_unicode ; + TC==shell_unicode_string -> + PrivDir = ?config(priv_dir, Config), + UserDir = ?config(priv_dir, Config), + SysDir = ?config(data_dir, Config), + ssh:start(), + Sftpd = {_Pid, _Host, Port} = + ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, PrivDir}, + {user_passwords, [{"foo", "bar"}]}]), + ct:sleep(500), + IO = ssh_test_lib:start_io_server(), + Shell = ssh_test_lib:start_shell(Port, IO, UserDir, + [{silently_accept_hosts, true}, + {user,"foo"},{password,"bar"}]), + ct:pal("IO=~p, Shell=~p, self()=~p",[IO,Shell,self()]), + ct:pal("file:native_name_encoding() = ~p,~nio:getopts() = ~p", + [file:native_name_encoding(),io:getopts()]), + wait_for_erlang_first_line([{io,IO}, {shell,Shell}, {sftpd, Sftpd} | Config]); init_per_testcase(_TestCase, Config) -> ssh:start(), Config. @@ -224,6 +245,15 @@ end_per_testcase(TestCase, Config) when TestCase == server_password_option; UserDir = filename:join(?config(priv_dir, Config), nopubkey), ssh_test_lib:del_dirs(UserDir), end_per_testcase(Config); +end_per_testcase(TC, Config) when TC==shell_no_unicode ; + TC==shell_unicode_string -> + case ?config(sftpd, Config) of + {Pid, _, _} -> + ssh:stop_daemon(Pid), + ssh:stop(); + _ -> + ssh:stop() + end; end_per_testcase(_TestCase, Config) -> end_per_testcase(Config). end_per_testcase(_Config) -> @@ -1597,7 +1627,23 @@ one_shell_op(IO, TimeOut) -> end. %%-------------------------------------------------------------------- +shell_no_unicode(Config) -> + new_do_shell(?config(io,Config), + [new_prompt, + {type,"io:format(\"hej ~p~n\",[42])."}, + {expect,"hej 42"} + ]). + +%%-------------------------------------------------------------------- +shell_unicode_string(Config) -> + new_do_shell(?config(io,Config), + [new_prompt, + {type,"io:format(\"こにちわ~ts~n\",[\"四二\"])."}, + {expect,"こにちわ四二"}, + {expect,"ok"} + ]). +%%-------------------------------------------------------------------- openssh_zlib_basic_test() -> [{doc, "Test basic connection with openssh_zlib"}]. openssh_zlib_basic_test(Config) -> @@ -1855,6 +1901,95 @@ do_shell(IO, Shell) -> %% end. +%%-------------------------------------------------------------------- +wait_for_erlang_first_line(Config) -> + receive + {'EXIT', _, _} -> + {fail,no_ssh_connection}; + <<"Eshell ",_/binary>> = _ErlShellStart -> + ct:pal("Erlang shell start: ~p~n", [_ErlShellStart]), + Config; + Other -> + ct:pal("Unexpected answer from ssh server: ~p",[Other]), + {fail,unexpected_answer} + after 10000 -> + ct:pal("No answer from ssh-server"), + {fail,timeout} + end. + + + +new_do_shell(IO, List) -> new_do_shell(IO, 0, List). + +new_do_shell(IO, N, [new_prompt|More]) -> + new_do_shell(IO, N+1, More); + +new_do_shell(IO, N, Ops=[{Order,Arg}|More]) -> + Pfx = prompt_prefix(), + PfxSize = size(Pfx), + receive + _X = <<"\r\n">> -> + ct:pal("Skip newline ~p",[_X]), + new_do_shell(IO, N, Ops); + + < ">> when (P1-$0)==N -> + new_do_shell_prompt(IO, N, Order, Arg, More); + + < ">> when (P1-$0)*10 + (P2-$0) == N -> + new_do_shell_prompt(IO, N, Order, Arg, More); + + < ">> when (P1-$0)*100 + (P2-$0)*10 + (P3-$0) == N -> + new_do_shell_prompt(IO, N, Order, Arg, More); + + Err when element(1,Err)==error -> + ct:fail("new_do_shell error: ~p~n",[Err]); + + RecBin when Order==expect ; Order==expect_echo -> + ct:pal("received ~p",[RecBin]), + RecStr = string:strip(unicode:characters_to_list(RecBin)), + ExpStr = string:strip(Arg), + case lists:prefix(ExpStr, RecStr) of + true when Order==expect -> + ct:pal("Matched ~ts",[RecStr]), + new_do_shell(IO, N, More); + true when Order==expect_echo -> + ct:pal("Matched echo ~ts",[RecStr]), + new_do_shell(IO, N, More); + false -> + ct:fail("*** Expected ~p, but got ~p",[string:strip(ExpStr),RecStr]) + end + after 30000 -> + ct:log("Meassage queue of ~p:~n~p", + [self(), erlang:process_info(self(), messages)]), + case Order of + expect -> ct:fail("timeout, expected ~p",[string:strip(Arg)]); + type -> ct:fail("timeout, no prompt") + end + end; + +new_do_shell(_, _, []) -> + ok. + +prompt_prefix() -> + case node() of + nonode@nohost -> <<>>; + Node -> list_to_binary( + lists:concat(["(",Node,")"])) + end. + + +new_do_shell_prompt(IO, N, type, Str, More) -> + ct:pal("Matched prompt ~p to trigger sending of next line to server",[N]), + IO ! {input, self(), Str++"\r\n"}, + ct:pal("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]), + new_do_shell(IO, N, [{expect_echo,Str}|More]); % expect echo of the sent line +new_do_shell_prompt(IO, N, Op, Str, More) -> + ct:pal("Matched prompt ~p",[N]), + new_do_shell(IO, N, [{Op,Str}|More]). + +%%-------------------------------------------------------------------- + + std_daemon(Config, ExtraOpts) -> SystemDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), diff --git a/lib/ssh/test/ssh_relay.erl b/lib/ssh/test/ssh_relay.erl index a4f2bad2e2..28000fbb97 100644 --- a/lib/ssh/test/ssh_relay.erl +++ b/lib/ssh/test/ssh_relay.erl @@ -117,7 +117,7 @@ stop(Srv) -> %% {stop, Reason} %% @end %%-------------------------------------------------------------------- -init([ListenAddr, ListenPort, PeerAddr, PeerPort | Options]) -> +init([ListenAddr, ListenPort, PeerAddr, PeerPort | _Options]) -> IfAddr = case ListenAddr of {0,0,0,0} -> []; diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index c19ede296f..6c631e6f6e 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -30,11 +30,6 @@ % Default timetrap timeout -define(default_timeout, ?t:minutes(1)). --define(USER, "Alladin"). --define(PASSWD, "Sesame"). - --define(tar_file_name, "sftp_tar_test.tar"). - %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- @@ -43,9 +38,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [{group, erlang_server}, - {group, openssh_server}, - sftp_nonexistent_subsystem + [{group, not_unicode}, + {group, unicode} ]. @@ -53,6 +47,8 @@ init_per_suite(Config) -> catch crypto:stop(), case (catch crypto:start()) of ok -> + ct:pal("file:native_name_encoding() = ~p,~nio:getopts() = ~p", + [file:native_name_encoding(),io:getopts()]), ssh:start(), Config; _ -> @@ -66,18 +62,19 @@ end_per_suite(Config) -> %%-------------------------------------------------------------------- groups() -> - [{erlang_server, [], [open_close_file, open_close_dir, read_file, read_dir, - write_file, write_big_file, sftp_read_big_file, - rename_file, mk_rm_dir, remove_file, links, - retrieve_attributes, set_attributes, async_read, - async_write, position, pos_read, pos_write, version_option, + [{not_unicode, [], [{group,erlang_server}, + {group,openssh_server}, + sftp_nonexistent_subsystem]}, + + {unicode, [], [{group,erlang_server}, + {group,openssh_server}, + sftp_nonexistent_subsystem]}, + + {erlang_server, [], [{group,write_read_tests}, + version_option, {group,remote_tar}]}, - {openssh_server, [], [open_close_file, open_close_dir, read_file, read_dir, - write_file, write_big_file, sftp_read_big_file, - rename_file, mk_rm_dir, remove_file, links, - retrieve_attributes, set_attributes, async_read, - async_write, position, pos_read, pos_write, + {openssh_server, [], [{group,write_read_tests}, {group,remote_tar}]}, {remote_tar, [], [create_empty_tar, files_to_tar, big_file_to_tar, files_chunked_to_tar, @@ -85,21 +82,74 @@ groups() -> simple_crypto_tar_small, simple_crypto_tar_big, read_tar, read_null_crypto_tar, read_crypto_tar, aes_cbc256_crypto_tar, aes_ctr_stream_crypto_tar - ]} + ]}, + + {write_read_tests, [], [open_close_file, open_close_dir, read_file, read_dir, + write_file, write_file_iolist, write_big_file, sftp_read_big_file, + rename_file, mk_rm_dir, remove_file, links, + retrieve_attributes, set_attributes, async_read, + async_write, position, pos_read, pos_write + ]} ]. - +init_per_group(not_unicode, Config) -> + ct:comment("Begin ~p",[grps(Config)]), + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + [{user, "Alladin"}, + {passwd, "Sesame"}, + {data, <<"Hello world!">>}, + {filename, filename:join(PrivDir, "sftp.txt")}, + {testfile, filename:join(PrivDir, "test.txt")}, + {linktest, filename:join(PrivDir, "link_test.txt")}, + {tar_filename, filename:join(PrivDir, "sftp_tar_test.tar")}, + {tar_F1_txt, "f1.txt"}, + {datadir_tar, filename:join(DataDir,"sftp_tar_test_data")} + | Config]; + +init_per_group(unicode, Config) -> + case file:native_name_encoding() of + utf8 -> + ct:comment("Begin ~p",[grps(Config)]), + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + [{user, "åke高兴"}, + {passwd, "ärlig日本じん"}, + {data, <<"foobar å 一二三四いちにさんち">>}, + {filename, filename:join(PrivDir, "sftp瑞点.txt")}, + {testfile, filename:join(PrivDir, "testハンス.txt")}, + {linktest, filename:join(PrivDir, "link_test語.txt")}, + {tar_filename, filename:join(PrivDir, "sftp_tar_test一二三.tar")}, + {tar_F1_txt, "F一.txt"}, + {datadir_tar, filename:join(DataDir,"sftp_tar_test_data_高兴")} + | lists:foldl(fun(K,Cf) -> lists:keydelete(K,1,Cf) end, + Config, + [user, passwd, data, + filename, testfile, linktest, + tar_filename, tar_F1_txt, datadir_tar + ] + ) + ]; + + _ -> + {skip, "Not unicode file encoding"} + end; + init_per_group(erlang_server, Config) -> + ct:comment("Begin ~p",[grps(Config)]), PrivDir = ?config(priv_dir, Config), SysDir = ?config(data_dir, Config), + User = ?config(user, Config), + Passwd = ?config(passwd, Config), Sftpd = {_, HostX, PortX} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, PrivDir}, {user_passwords, - [{?USER, ?PASSWD}]}]), + [{User, Passwd}]}]), [{peer, {fmt_host(HostX),PortX}}, {group, erlang_server}, {sftpd, Sftpd} | Config]; init_per_group(openssh_server, Config) -> + ct:comment("Begin ~p",[grps(Config)]), Host = ssh_test_lib:hostname(), case (catch ssh_sftp:start_channel(Host, [{user_interaction, false}, @@ -113,14 +163,17 @@ init_per_group(openssh_server, Config) -> end; init_per_group(remote_tar, Config) -> + ct:comment("Begin ~p",[grps(Config)]), {Host,Port} = ?config(peer, Config), ct:log("Server (~p) at ~p:~p",[?config(group,Config),Host,Port]), + User = ?config(user, Config), + Passwd = ?config(passwd, Config), {ok, Connection} = case ?config(group, Config) of erlang_server -> ssh:connect(Host, Port, - [{user, ?USER}, - {password, ?PASSWD}, + [{user, User}, + {password, Passwd}, {user_interaction, false}, {silently_accept_hosts, true}]); openssh_server -> @@ -129,11 +182,24 @@ init_per_group(remote_tar, Config) -> {silently_accept_hosts, true}]) end, [{remote_tar, true}, - {connection, Connection} | Config]. + {connection, Connection} | Config]; + +init_per_group(write_read_tests, Config) -> + ct:comment("Begin ~p",[grps(Config)]), + Config. + +grps(Config) -> + proplists:get_all_values( + name, + lists:flatten([proplists:get_value(tc_group_properties,Config,[]), + proplists:get_value(tc_group_path,Config,[])])). + end_per_group(erlang_server, Config) -> + ct:comment("End ~p",[grps(Config)]), Config; end_per_group(_, Config) -> + ct:comment("End ~p",[grps(Config)]), Config. %%-------------------------------------------------------------------- @@ -141,11 +207,13 @@ end_per_group(_, Config) -> init_per_testcase(sftp_nonexistent_subsystem, Config) -> PrivDir = ?config(priv_dir, Config), SysDir = ?config(data_dir, Config), + User = ?config(user, Config), + Passwd = ?config(passwd, Config), Sftpd = ssh_test_lib:daemon([{system_dir, SysDir}, {user_dir, PrivDir}, {subsystems, []}, {user_passwords, - [{?USER, ?PASSWD}]} + [{User, Passwd}]} ]), [{sftpd, Sftpd} | Config]; @@ -155,11 +223,13 @@ init_per_testcase(version_option, Config) -> TmpConfig = lists:keydelete(sftp, 1, TmpConfig0), Dog = ct:timetrap(?default_timeout), {_,Host, Port} = ?config(sftpd, Config), + User = ?config(user, Config), + Passwd = ?config(passwd, Config), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, Port, [{sftp_vsn, 3}, - {user, ?USER}, - {password, ?PASSWD}, + {user, User}, + {password, Passwd}, {user_interaction, false}, {silently_accept_hosts, true}]), Sftp = {ChannelPid, Connection}, @@ -170,6 +240,8 @@ init_per_testcase(Case, Config0) -> Config1 = lists:keydelete(watchdog, 1, Config0), Config2 = lists:keydelete(sftp, 1, Config1), Dog = ct:timetrap(?default_timeout), + User = ?config(user, Config0), + Passwd = ?config(passwd, Config0), Config = case ?config(group,Config2) of @@ -177,8 +249,8 @@ init_per_testcase(Case, Config0) -> {_,Host, Port} = ?config(sftpd, Config2), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, Port, - [{user, ?USER}, - {password, ?PASSWD}, + [{user, User}, + {password, Passwd}, {user_interaction, false}, {silently_accept_hosts, true}]), Sftp = {ChannelPid, Connection}, @@ -208,8 +280,7 @@ init_per_testcase(Case, Config0) -> end_per_testcase(sftp_nonexistent_subsystem, Config) -> Config; end_per_testcase(rename_file, Config) -> - PrivDir = ?config(priv_dir, Config), - NewFileName = filename:join(PrivDir, "test.txt"), + NewFileName = ?config(testfile, Config), file:delete(NewFileName), end_per_testcase(Config); end_per_testcase(_, Config) -> @@ -227,8 +298,7 @@ end_per_testcase(Config) -> open_close_file() -> [{doc, "Test API functions open/3 and close/2"}]. open_close_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), @@ -249,7 +319,7 @@ open_close_dir() -> open_close_dir(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), {Sftp, _} = ?config(sftp, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {ok, Handle} = ssh_sftp:opendir(Sftp, PrivDir), ok = ssh_sftp:close(Sftp, Handle), @@ -259,8 +329,7 @@ open_close_dir(Config) when is_list(Config) -> read_file() -> [{doc, "Test API funtion read_file/2"}]. read_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), {ok, Data} = ssh_sftp:read_file(Sftp, FileName), {ok, Data} = ssh_sftp:read_file(Sftp, FileName), @@ -279,20 +348,39 @@ read_dir(Config) when is_list(Config) -> write_file() -> [{doc, "Test API function write_file/2"}]. write_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), Data = list_to_binary("Hej hopp!"), ssh_sftp:write_file(Sftp, FileName, [Data]), {ok, Data} = file:read_file(FileName). +%%-------------------------------------------------------------------- +write_file_iolist() -> + [{doc, "Test API function write_file/2 with iolists"}]. +write_file_iolist(Config) when is_list(Config) -> + FileName = ?config(filename, Config), + {Sftp, _} = ?config(sftp, Config), + + Data = list_to_binary("Hej hopp!"), + lists:foreach( + fun(D) -> + ssh_sftp:write_file(Sftp, FileName, [D]), + Expected = if is_binary(D) -> D; + is_list(D) -> list_to_binary(D) + end, + {ok, Expected} = file:read_file(FileName) + end, + [Data, [Data,Data], [[Data],[Data]], [[[Data]],[[[[Data]],Data]]], + [[[[Data]],Data],binary_to_list(Data)], + [[[[Data]],Data],[[binary_to_list(Data)],[[binary_to_list(Data)]]]] + ]). + %%-------------------------------------------------------------------- write_big_file() -> [{doc, "Test API function write_file/2 with big data"}]. write_big_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), Data = list_to_binary(lists:duplicate(750000,"a")), @@ -303,8 +391,7 @@ write_big_file(Config) when is_list(Config) -> sftp_read_big_file() -> [{doc, "Test API function read_file/2 with big data"}]. sftp_read_big_file(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), Data = list_to_binary(lists:duplicate(750000,"a")), @@ -317,7 +404,7 @@ remove_file() -> [{doc,"Test API function delete/2"}]. remove_file(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), @@ -331,8 +418,8 @@ rename_file() -> [{doc, "Test API function rename_file/2"}]. rename_file(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), - NewFileName = filename:join(PrivDir, "test.txt"), + FileName = ?config(filename, Config), + NewFileName = ?config(testfile, Config), {Sftp, _} = ?config(sftp, Config), {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), @@ -369,9 +456,8 @@ links(Config) when is_list(Config) -> {skip, "Links are not fully supported by windows"}; _ -> {Sftp, _} = ?config(sftp, Config), - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), - LinkFileName = filename:join(PrivDir, "link_test.txt"), + FileName = ?config(filename, Config), + LinkFileName = ?config(linktest, Config), ok = ssh_sftp:make_symlink(Sftp, LinkFileName, FileName), {ok, FileName} = ssh_sftp:read_link(Sftp, LinkFileName) @@ -381,8 +467,7 @@ links(Config) when is_list(Config) -> retrieve_attributes() -> [{doc, "Test API function read_file_info/3"}]. retrieve_attributes(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {Sftp, _} = ?config(sftp, Config), {ok, FileInfo} = ssh_sftp:read_file_info(Sftp, FileName), @@ -395,8 +480,7 @@ retrieve_attributes(Config) when is_list(Config) -> set_attributes() -> [{doc,"Test API function write_file_info/3"}]. set_attributes(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "test.txt"), + FileName = ?config(testfile, Config), {Sftp, _} = ?config(sftp, Config), {ok,Fd} = file:open(FileName, write), @@ -412,9 +496,8 @@ async_read() -> [{doc,"Test API aread/3"}]. async_read(Config) when is_list(Config) -> {Sftp, _} = ?config(sftp, Config), - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "sftp.txt"), + FileName = ?config(filename, Config), {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]), {async, Ref} = ssh_sftp:aread(Sftp, Handle, 20), @@ -430,8 +513,7 @@ async_write() -> [{doc,"Test API awrite/3"}]. async_write(Config) when is_list(Config) -> {Sftp, _} = ?config(sftp, Config), - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "test.txt"), + FileName = ?config(testfile, Config), {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]), Data = list_to_binary("foobar"), {async, Ref} = ssh_sftp:awrite(Sftp, Handle, Data), @@ -448,8 +530,7 @@ async_write(Config) when is_list(Config) -> position() -> [{doc, "Test API functions position/3"}]. position(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "test.txt"), + FileName = ?config(testfile, Config), {Sftp, _} = ?config(sftp, Config), Data = list_to_binary("1234567890"), @@ -478,8 +559,7 @@ position(Config) when is_list(Config) -> pos_read() -> [{doc,"Test API functions pread/3 and apread/3"}]. pos_read(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "test.txt"), + FileName = ?config(testfile, Config), {Sftp, _} = ?config(sftp, Config), Data = list_to_binary("Hej hopp!"), ssh_sftp:write_file(Sftp, FileName, [Data]), @@ -504,8 +584,7 @@ pos_read(Config) when is_list(Config) -> pos_write() -> [{doc,"Test API functions pwrite/4 and apwrite/4"}]. pos_write(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "test.txt"), + FileName = ?config(testfile, Config), {Sftp, _} = ?config(sftp, Config), {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]), @@ -532,10 +611,13 @@ sftp_nonexistent_subsystem() -> [{doc, "Try to execute sftp subsystem on a server that does not support it"}]. sftp_nonexistent_subsystem(Config) when is_list(Config) -> {_,Host, Port} = ?config(sftpd, Config), + User = ?config(user, Config), + Passwd = ?config(passwd, Config), {error,"server failed to start sftp subsystem"} = ssh_sftp:start_channel(Host, Port, [{user_interaction, false}, - {user, ?USER}, {password, ?PASSWD}, + {user, User}, + {password, Passwd}, {silently_accept_hosts, true}]). %%-------------------------------------------------------------------- @@ -547,25 +629,29 @@ version_option(Config) when is_list(Config) -> %%-------------------------------------------------------------------- create_empty_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), erl_tar:close(Handle), {ChPid,_} = ?config(sftp,Config), {ok, #file_info{type=regular}} = - ssh_sftp:read_file_info(ChPid,fnp(?tar_file_name,Config)). + ssh_sftp:read_file_info(ChPid, TarFileName). %%-------------------------------------------------------------------- files_to_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write]), - ok = erl_tar:add(Handle, fn("f1.txt",Config), "f1.txt", [verbose]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), + F1 = ?config(tar_F1_txt, Config), + ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose]), ok = erl_tar:add(Handle, fn("f2.txt",Config), "f2.txt", [verbose]), ok = erl_tar:close(Handle), - chk_tar(["f1.txt", "f2.txt"], Config). + chk_tar([F1, "f2.txt"], Config). %%-------------------------------------------------------------------- big_file_to_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), ok = erl_tar:add(Handle, fn("big.txt",Config), "big.txt", [verbose]), ok = erl_tar:close(Handle), chk_tar(["big.txt"], Config). @@ -574,15 +660,18 @@ big_file_to_tar(Config) -> %%-------------------------------------------------------------------- files_chunked_to_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write]), - ok = erl_tar:add(Handle, fn("f1.txt",Config), "f1.txt", [verbose,{chunks,2}]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), + F1 = ?config(tar_F1_txt, Config), + ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]), ok = erl_tar:close(Handle), - chk_tar(["f1.txt"], Config). + chk_tar([F1], Config). %%-------------------------------------------------------------------- directory_to_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), ok = erl_tar:add(Handle, fn("d1",Config), "d1", [verbose]), ok = erl_tar:close(Handle), chk_tar(["d1"], Config). @@ -590,7 +679,8 @@ directory_to_tar(Config) -> %%-------------------------------------------------------------------- binaries_to_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), Bin = <<"A binary">>, ok = erl_tar:add(Handle, Bin, "b1", [verbose]), ok = erl_tar:close(Handle), @@ -603,13 +693,15 @@ null_crypto_tar(Config) -> Cenc = fun(Bin,CState) -> {ok,Bin,CState,_SendSize=5} end, Cend = fun(Bin,_CState) -> {ok,Bin} end, C = {Cinit,Cenc,Cend}, - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write,{crypto,C}]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,C}]), Bin = <<"A binary">>, + F1 = ?config(tar_F1_txt, Config), ok = erl_tar:add(Handle, Bin, "b1", [verbose]), - ok = erl_tar:add(Handle, fn("f1.txt",Config), "f1.txt", [verbose,{chunks,2}]), + ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]), ok = erl_tar:add(Handle, fn("big.txt",Config), "big.txt", [verbose,{chunks,15000}]), ok = erl_tar:close(Handle), - chk_tar([{"b1",Bin}, "f1.txt", "big.txt"], Config). + chk_tar([{"b1",Bin}, F1, "big.txt"], Config). %%-------------------------------------------------------------------- simple_crypto_tar_small(Config) -> @@ -619,12 +711,14 @@ simple_crypto_tar_small(Config) -> Cdec = fun(Bin,CState) -> {ok,unstuff(Bin),CState,_Size=4} end, Cend = fun(Bin,_CState) -> {ok,stuff(Bin)} end, C = {Cinit,Cenc,Cend}, - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write,{crypto,C}]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,C}]), Bin = <<"A binary">>, + F1 = ?config(tar_F1_txt, Config), ok = erl_tar:add(Handle, Bin, "b1", [verbose]), - ok = erl_tar:add(Handle, fn("f1.txt",Config), "f1.txt", [verbose,{chunks,2}]), + ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]), ok = erl_tar:close(Handle), - chk_tar([{"b1",Bin}, "f1.txt"], Config, [{crypto,{Cinit,Cdec}}]). + chk_tar([{"b1",Bin}, F1], Config, [{crypto,{Cinit,Cdec}}]). %%-------------------------------------------------------------------- simple_crypto_tar_big(Config) -> @@ -634,13 +728,15 @@ simple_crypto_tar_big(Config) -> Cdec = fun(Bin,CState) -> {ok,unstuff(Bin),CState,_SendSize=4} end, Cend = fun(Bin,_CState) -> {ok,stuff(Bin)} end, C = {Cinit,Cenc,Cend}, - {ok,Handle} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write,{crypto,C}]), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,C}]), Bin = <<"A binary">>, + F1 = ?config(tar_F1_txt, Config), ok = erl_tar:add(Handle, Bin, "b1", [verbose]), - ok = erl_tar:add(Handle, fn("f1.txt",Config), "f1.txt", [verbose,{chunks,2}]), + ok = erl_tar:add(Handle, fn(F1,Config), F1, [verbose,{chunks,2}]), ok = erl_tar:add(Handle, fn("big.txt",Config), "big.txt", [verbose,{chunks,15000}]), ok = erl_tar:close(Handle), - chk_tar([{"b1",Bin}, "f1.txt", "big.txt"], Config, [{crypto,{Cinit,Cdec}}]). + chk_tar([{"b1",Bin}, F1, "big.txt"], Config, [{crypto,{Cinit,Cdec}}]). stuff(Bin) -> << <> || <> <= Bin >>. @@ -653,7 +749,8 @@ read_tar(Config) -> [{"b1",<<"A binary">>}, {"b2",list_to_binary(lists:duplicate(750000,"a"))} ]), - {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write]), + TarFileName = ?config(tar_filename, Config), + {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), [ok = erl_tar:add(HandleWrite, Bin, Name, [verbose]) || {Name,Bin} <- NameBins], ok = erl_tar:close(HandleWrite), @@ -675,7 +772,8 @@ read_null_crypto_tar(Config) -> Cw = {Cinitw,Cenc,Cendw}, Cr = {Cinitr,Cdec}, - {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write,{crypto,Cw}]), + TarFileName = ?config(tar_filename, Config), + {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]), [ok = erl_tar:add(HandleWrite, Bin, Name, [verbose]) || {Name,Bin} <- NameBins], ok = erl_tar:close(HandleWrite), @@ -698,7 +796,8 @@ read_crypto_tar(Config) -> Cw = {Cinitw,Cenc,Cendw}, Cr = {Cinitr,Cdec}, - {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write,{crypto,Cw}]), + TarFileName = ?config(tar_filename, Config), + {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]), [ok = erl_tar:add(HandleWrite, Bin, Name, [verbose]) || {Name,Bin} <- NameBins], ok = erl_tar:close(HandleWrite), @@ -737,7 +836,8 @@ aes_cbc256_crypto_tar(Config) -> end, Cw = {Cinitw,Cenc,Cendw}, - {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write,{crypto,Cw}]), + TarFileName = ?config(tar_filename, Config), + {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]), [ok = erl_tar:add(HandleWrite, Bin, Name, [verbose]) || {Name,Bin} <- NameBins], ok = erl_tar:close(HandleWrite), @@ -779,7 +879,8 @@ aes_ctr_stream_crypto_tar(Config) -> end, Cw = {Cinitw,Cenc,Cendw}, - {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, fnp(?tar_file_name,Config), [write,{crypto,Cw}]), + TarFileName = ?config(tar_filename, Config), + {ok,HandleWrite} = ssh_sftp:open_tar(ChPid2, TarFileName, [write,{crypto,Cw}]), [ok = erl_tar:add(HandleWrite, Bin, Name, [verbose]) || {Name,Bin} <- NameBins], ok = erl_tar:close(HandleWrite), @@ -790,18 +891,18 @@ aes_ctr_stream_crypto_tar(Config) -> %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- prep(Config) -> - PrivDir = ?config(priv_dir, Config), - TestFile = filename:join(PrivDir, "sftp.txt"), - TestFile1 = filename:join(PrivDir, "test.txt"), - TestLink = filename:join(PrivDir, "link_test.txt"), + DataDir = ?config(data_dir, Config), + TestFile = ?config(filename, Config), + TestFile1 = ?config(testfile, Config), + TestLink = ?config(linktest, Config), + TarFileName = ?config(tar_filename, Config), file:delete(TestFile), file:delete(TestFile1), file:delete(TestLink), - file:delete(fnp(?tar_file_name,Config)), + file:delete(TarFileName), %% Initial config - DataDir = ?config(data_dir, Config), FileName = filename:join(DataDir, "sftp.txt"), file:copy(FileName, TestFile), Mode = 8#00400 bor 8#00200 bor 8#00040, % read & write owner, read group @@ -815,7 +916,8 @@ chk_tar(Items, Config) -> chk_tar(Items, Config, []). chk_tar(Items, Config, Opts) -> - chk_tar(Items, fnp(?tar_file_name,Config), Config, Opts). + TarFileName = ?config(tar_filename, Config), + chk_tar(Items, TarFileName, Config, Opts). chk_tar(Items, TarFileName, Config, Opts) when is_list(Opts) -> tar_size(TarFileName, Config), @@ -888,13 +990,8 @@ read_item_contents(ItemName, FileName) -> end. fn(Name, Config) -> - Dir = ?config(data_dir, Config), - filename:join([Dir,"sftp_tar_test_data",Name]). - -fnp(Name, Config) -> - Dir = ?config(priv_dir, Config), - filename:join([Dir,Name]). - + Dir = ?config(datadir_tar, Config), + filename:join(Dir,Name). fmt_host({A,B,C,D}) -> lists:concat([A,".",B,".",C,".",D]); fmt_host(S) -> S. diff --git "a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/F\344\270\200.txt" "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/F\344\270\200.txt" new file mode 100644 index 0000000000..e6076a05b5 --- /dev/null +++ "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/F\344\270\200.txt" @@ -0,0 +1 @@ +你好 diff --git "a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/big.txt" "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/big.txt" new file mode 100644 index 0000000000..f597b69d4c --- /dev/null +++ "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/big.txt" @@ -0,0 +1,16384 @@ +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. +All work and no play makes Jack a dull boy. diff --git "a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f1" "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f1" new file mode 100644 index 0000000000..1bafa9761e --- /dev/null +++ "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f1" @@ -0,0 +1 @@ +And hi from the subdirectory too! diff --git "a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f2" "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f2" new file mode 100644 index 0000000000..8566adaeef --- /dev/null +++ "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/d1/f2" @@ -0,0 +1 @@ +one more file diff --git "a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f2.txt" "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f2.txt" new file mode 100644 index 0000000000..d18c6b11fc --- /dev/null +++ "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f2.txt" @@ -0,0 +1 @@ +How are you? -- cgit v1.2.3 From 747e32d7e5cfcd580da0a57e94cf9fda7adfb6e3 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 22 Jun 2015 19:53:03 +0200 Subject: ssh: correct sftp unicode and iolist bug Ssh_sftp.erl handled incorrectly unicode data in ssh_ftp:write_file. There was also problems with some deeper iolists. --- lib/ssh/src/ssh_sftp.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl index 9fe2d56759..dbacf730cc 100644 --- a/lib/ssh/src/ssh_sftp.erl +++ b/lib/ssh/src/ssh_sftp.erl @@ -439,7 +439,7 @@ write_file(Pid, Name, List) -> write_file(Pid, Name, List, ?FILEOP_TIMEOUT). write_file(Pid, Name, List, FileOpTimeout) when is_list(List) -> - write_file(Pid, Name, unicode:characters_to_binary(List), FileOpTimeout); + write_file(Pid, Name, list_to_binary(List), FileOpTimeout); write_file(Pid, Name, Bin, FileOpTimeout) -> case open(Pid, Name, [write, binary], FileOpTimeout) of {ok, Handle} -> @@ -611,8 +611,7 @@ do_handle_call({pread,Async,Handle,At,Length}, From, State) -> fun({ok,Data}, State2) -> case get_mode(Handle, State2) of binary -> {{ok,Data}, State2}; - text -> - {{ok,unicode:characters_to_list(Data)}, State2} + text -> {{ok,binary_to_list(Data)}, State2} end; (Rep, State2) -> {Rep, State2} -- cgit v1.2.3 From 9134d6bdbff1afdc5cf5a390597498feea23c1fa Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Wed, 1 Jul 2015 15:55:12 +0200 Subject: wx: Make wxLANGUAGE_ variable So they work on both wxWidgets-2.8 and 3.0 --- lib/wx/api_gen/wx_gen.erl | 10 +- lib/wx/api_gen/wxapi.conf | 3 +- lib/wx/c_src/gen/wxe_init.cpp | 468 ++++++++++++++++++++++++++++++++++++++++- lib/wx/include/wx.hrl | 466 ++++++++++++++++++++-------------------- lib/wx/test/wx_class_SUITE.erl | 30 ++- 5 files changed, 736 insertions(+), 241 deletions(-) (limited to 'lib') diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl index 212574ede3..114b3e561e 100644 --- a/lib/wx/api_gen/wx_gen.erl +++ b/lib/wx/api_gen/wx_gen.erl @@ -1196,7 +1196,7 @@ translate_constants(Enums, NotConsts0, Skip0) -> create_consts([{{enum, Name},Enum = #enum{vals=Vals}}|R], Skip, NotConsts, Acc0) -> CC = fun(What, Acc) -> - create_const(What, Skip, NotConsts, Acc) + create_const(What, Name, Skip, NotConsts, Acc) end, Acc = case Vals of undefined -> @@ -1210,17 +1210,17 @@ create_consts([{{enum, Name},Enum = #enum{vals=Vals}}|R], Skip, NotConsts, Acc0) create_consts(R, Skip, NotConsts, Acc); create_consts([],_,_,Acc) -> Acc. -create_const({Name, Val}, Skip, NotConsts, Acc) -> +create_const({Name, Val}, EnumName, Skip, NotConsts, Acc) -> case gb_sets:is_member(Name, Skip) of true -> Acc; false -> - case gb_sets:is_member(Name, NotConsts) of + case gb_sets:is_member(Name, NotConsts) orelse + gb_sets:is_member(EnumName, NotConsts) + of true -> [#const{name=Name,val=next_id(const),is_const=false}|Acc]; false -> [#const{name=Name,val=Val,is_const=true}|Acc] -%% false -> -%% [#const{name=Name,val=Val}|Acc] end end. diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index b8241816b2..0d1fef6272 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -36,7 +36,8 @@ wxSL_LABELS, wxCURSOR_DEFAULT, wxCURSOR_ARROWWAIT, - wxCURSOR_MAX + wxCURSOR_MAX, + wxLanguage ]}. {gvars, diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp index fd729accc9..1e432e34ce 100644 --- a/lib/wx/c_src/gen/wxe_init.cpp +++ b/lib/wx/c_src/gen/wxe_init.cpp @@ -57,6 +57,472 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) { rt.addTupleCount(2); rt.addAtom("wxMOD_CMD"); rt.addInt(wxMOD_CMD); rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ABKHAZIAN"); rt.addInt(wxLANGUAGE_ABKHAZIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_AFAR"); rt.addInt(wxLANGUAGE_AFAR); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_AFRIKAANS"); rt.addInt(wxLANGUAGE_AFRIKAANS); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ALBANIAN"); rt.addInt(wxLANGUAGE_ALBANIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_AMHARIC"); rt.addInt(wxLANGUAGE_AMHARIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC"); rt.addInt(wxLANGUAGE_ARABIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_ALGERIA"); rt.addInt(wxLANGUAGE_ARABIC_ALGERIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_BAHRAIN"); rt.addInt(wxLANGUAGE_ARABIC_BAHRAIN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_EGYPT"); rt.addInt(wxLANGUAGE_ARABIC_EGYPT); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_IRAQ"); rt.addInt(wxLANGUAGE_ARABIC_IRAQ); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_JORDAN"); rt.addInt(wxLANGUAGE_ARABIC_JORDAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_KUWAIT"); rt.addInt(wxLANGUAGE_ARABIC_KUWAIT); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_LEBANON"); rt.addInt(wxLANGUAGE_ARABIC_LEBANON); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_LIBYA"); rt.addInt(wxLANGUAGE_ARABIC_LIBYA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_MOROCCO"); rt.addInt(wxLANGUAGE_ARABIC_MOROCCO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_OMAN"); rt.addInt(wxLANGUAGE_ARABIC_OMAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_QATAR"); rt.addInt(wxLANGUAGE_ARABIC_QATAR); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_SAUDI_ARABIA"); rt.addInt(wxLANGUAGE_ARABIC_SAUDI_ARABIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_SUDAN"); rt.addInt(wxLANGUAGE_ARABIC_SUDAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_SYRIA"); rt.addInt(wxLANGUAGE_ARABIC_SYRIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_TUNISIA"); rt.addInt(wxLANGUAGE_ARABIC_TUNISIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_UAE"); rt.addInt(wxLANGUAGE_ARABIC_UAE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARABIC_YEMEN"); rt.addInt(wxLANGUAGE_ARABIC_YEMEN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ARMENIAN"); rt.addInt(wxLANGUAGE_ARMENIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ASSAMESE"); rt.addInt(wxLANGUAGE_ASSAMESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_AYMARA"); rt.addInt(wxLANGUAGE_AYMARA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_AZERI"); rt.addInt(wxLANGUAGE_AZERI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_AZERI_CYRILLIC"); rt.addInt(wxLANGUAGE_AZERI_CYRILLIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_AZERI_LATIN"); rt.addInt(wxLANGUAGE_AZERI_LATIN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BASHKIR"); rt.addInt(wxLANGUAGE_BASHKIR); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BASQUE"); rt.addInt(wxLANGUAGE_BASQUE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BELARUSIAN"); rt.addInt(wxLANGUAGE_BELARUSIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BENGALI"); rt.addInt(wxLANGUAGE_BENGALI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BHUTANI"); rt.addInt(wxLANGUAGE_BHUTANI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BIHARI"); rt.addInt(wxLANGUAGE_BIHARI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BISLAMA"); rt.addInt(wxLANGUAGE_BISLAMA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BRETON"); rt.addInt(wxLANGUAGE_BRETON); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BULGARIAN"); rt.addInt(wxLANGUAGE_BULGARIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_BURMESE"); rt.addInt(wxLANGUAGE_BURMESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CAMBODIAN"); rt.addInt(wxLANGUAGE_CAMBODIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CATALAN"); rt.addInt(wxLANGUAGE_CATALAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CHINESE"); rt.addInt(wxLANGUAGE_CHINESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CHINESE_HONGKONG"); rt.addInt(wxLANGUAGE_CHINESE_HONGKONG); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CHINESE_MACAU"); rt.addInt(wxLANGUAGE_CHINESE_MACAU); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CHINESE_SIMPLIFIED"); rt.addInt(wxLANGUAGE_CHINESE_SIMPLIFIED); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CHINESE_SINGAPORE"); rt.addInt(wxLANGUAGE_CHINESE_SINGAPORE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CHINESE_TAIWAN"); rt.addInt(wxLANGUAGE_CHINESE_TAIWAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CHINESE_TRADITIONAL"); rt.addInt(wxLANGUAGE_CHINESE_TRADITIONAL); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CORSICAN"); rt.addInt(wxLANGUAGE_CORSICAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CROATIAN"); rt.addInt(wxLANGUAGE_CROATIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_CZECH"); rt.addInt(wxLANGUAGE_CZECH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_DANISH"); rt.addInt(wxLANGUAGE_DANISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_DEFAULT"); rt.addInt(wxLANGUAGE_DEFAULT); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_DUTCH"); rt.addInt(wxLANGUAGE_DUTCH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_DUTCH_BELGIAN"); rt.addInt(wxLANGUAGE_DUTCH_BELGIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH"); rt.addInt(wxLANGUAGE_ENGLISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_AUSTRALIA"); rt.addInt(wxLANGUAGE_ENGLISH_AUSTRALIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_BELIZE"); rt.addInt(wxLANGUAGE_ENGLISH_BELIZE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_BOTSWANA"); rt.addInt(wxLANGUAGE_ENGLISH_BOTSWANA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_CANADA"); rt.addInt(wxLANGUAGE_ENGLISH_CANADA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_CARIBBEAN"); rt.addInt(wxLANGUAGE_ENGLISH_CARIBBEAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_DENMARK"); rt.addInt(wxLANGUAGE_ENGLISH_DENMARK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_EIRE"); rt.addInt(wxLANGUAGE_ENGLISH_EIRE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_JAMAICA"); rt.addInt(wxLANGUAGE_ENGLISH_JAMAICA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_NEW_ZEALAND"); rt.addInt(wxLANGUAGE_ENGLISH_NEW_ZEALAND); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_PHILIPPINES"); rt.addInt(wxLANGUAGE_ENGLISH_PHILIPPINES); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_SOUTH_AFRICA"); rt.addInt(wxLANGUAGE_ENGLISH_SOUTH_AFRICA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_TRINIDAD"); rt.addInt(wxLANGUAGE_ENGLISH_TRINIDAD); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_UK"); rt.addInt(wxLANGUAGE_ENGLISH_UK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_US"); rt.addInt(wxLANGUAGE_ENGLISH_US); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ENGLISH_ZIMBABWE"); rt.addInt(wxLANGUAGE_ENGLISH_ZIMBABWE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ESPERANTO"); rt.addInt(wxLANGUAGE_ESPERANTO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ESTONIAN"); rt.addInt(wxLANGUAGE_ESTONIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FAEROESE"); rt.addInt(wxLANGUAGE_FAEROESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FARSI"); rt.addInt(wxLANGUAGE_FARSI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FIJI"); rt.addInt(wxLANGUAGE_FIJI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FINNISH"); rt.addInt(wxLANGUAGE_FINNISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FRENCH"); rt.addInt(wxLANGUAGE_FRENCH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FRENCH_BELGIAN"); rt.addInt(wxLANGUAGE_FRENCH_BELGIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FRENCH_CANADIAN"); rt.addInt(wxLANGUAGE_FRENCH_CANADIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FRENCH_LUXEMBOURG"); rt.addInt(wxLANGUAGE_FRENCH_LUXEMBOURG); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FRENCH_MONACO"); rt.addInt(wxLANGUAGE_FRENCH_MONACO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FRENCH_SWISS"); rt.addInt(wxLANGUAGE_FRENCH_SWISS); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_FRISIAN"); rt.addInt(wxLANGUAGE_FRISIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GALICIAN"); rt.addInt(wxLANGUAGE_GALICIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GEORGIAN"); rt.addInt(wxLANGUAGE_GEORGIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GERMAN"); rt.addInt(wxLANGUAGE_GERMAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GERMAN_AUSTRIAN"); rt.addInt(wxLANGUAGE_GERMAN_AUSTRIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GERMAN_BELGIUM"); rt.addInt(wxLANGUAGE_GERMAN_BELGIUM); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GERMAN_LIECHTENSTEIN"); rt.addInt(wxLANGUAGE_GERMAN_LIECHTENSTEIN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GERMAN_LUXEMBOURG"); rt.addInt(wxLANGUAGE_GERMAN_LUXEMBOURG); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GERMAN_SWISS"); rt.addInt(wxLANGUAGE_GERMAN_SWISS); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GREEK"); rt.addInt(wxLANGUAGE_GREEK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GREENLANDIC"); rt.addInt(wxLANGUAGE_GREENLANDIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GUARANI"); rt.addInt(wxLANGUAGE_GUARANI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_GUJARATI"); rt.addInt(wxLANGUAGE_GUJARATI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_HAUSA"); rt.addInt(wxLANGUAGE_HAUSA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_HEBREW"); rt.addInt(wxLANGUAGE_HEBREW); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_HINDI"); rt.addInt(wxLANGUAGE_HINDI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_HUNGARIAN"); rt.addInt(wxLANGUAGE_HUNGARIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ICELANDIC"); rt.addInt(wxLANGUAGE_ICELANDIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_INDONESIAN"); rt.addInt(wxLANGUAGE_INDONESIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_INTERLINGUA"); rt.addInt(wxLANGUAGE_INTERLINGUA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_INTERLINGUE"); rt.addInt(wxLANGUAGE_INTERLINGUE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_INUKTITUT"); rt.addInt(wxLANGUAGE_INUKTITUT); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_INUPIAK"); rt.addInt(wxLANGUAGE_INUPIAK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_IRISH"); rt.addInt(wxLANGUAGE_IRISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ITALIAN"); rt.addInt(wxLANGUAGE_ITALIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ITALIAN_SWISS"); rt.addInt(wxLANGUAGE_ITALIAN_SWISS); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_JAPANESE"); rt.addInt(wxLANGUAGE_JAPANESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_JAVANESE"); rt.addInt(wxLANGUAGE_JAVANESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KANNADA"); rt.addInt(wxLANGUAGE_KANNADA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KASHMIRI"); rt.addInt(wxLANGUAGE_KASHMIRI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KASHMIRI_INDIA"); rt.addInt(wxLANGUAGE_KASHMIRI_INDIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KAZAKH"); rt.addInt(wxLANGUAGE_KAZAKH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KERNEWEK"); rt.addInt(wxLANGUAGE_KERNEWEK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KINYARWANDA"); rt.addInt(wxLANGUAGE_KINYARWANDA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KIRGHIZ"); rt.addInt(wxLANGUAGE_KIRGHIZ); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KIRUNDI"); rt.addInt(wxLANGUAGE_KIRUNDI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KONKANI"); rt.addInt(wxLANGUAGE_KONKANI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KOREAN"); rt.addInt(wxLANGUAGE_KOREAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_KURDISH"); rt.addInt(wxLANGUAGE_KURDISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_LAOTHIAN"); rt.addInt(wxLANGUAGE_LAOTHIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_LATIN"); rt.addInt(wxLANGUAGE_LATIN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_LATVIAN"); rt.addInt(wxLANGUAGE_LATVIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_LINGALA"); rt.addInt(wxLANGUAGE_LINGALA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_LITHUANIAN"); rt.addInt(wxLANGUAGE_LITHUANIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MACEDONIAN"); rt.addInt(wxLANGUAGE_MACEDONIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MALAGASY"); rt.addInt(wxLANGUAGE_MALAGASY); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MALAY"); rt.addInt(wxLANGUAGE_MALAY); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MALAYALAM"); rt.addInt(wxLANGUAGE_MALAYALAM); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM"); rt.addInt(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MALAY_MALAYSIA"); rt.addInt(wxLANGUAGE_MALAY_MALAYSIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MALTESE"); rt.addInt(wxLANGUAGE_MALTESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MANIPURI"); rt.addInt(wxLANGUAGE_MANIPURI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MAORI"); rt.addInt(wxLANGUAGE_MAORI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MARATHI"); rt.addInt(wxLANGUAGE_MARATHI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MOLDAVIAN"); rt.addInt(wxLANGUAGE_MOLDAVIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_MONGOLIAN"); rt.addInt(wxLANGUAGE_MONGOLIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_NAURU"); rt.addInt(wxLANGUAGE_NAURU); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_NEPALI"); rt.addInt(wxLANGUAGE_NEPALI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_NEPALI_INDIA"); rt.addInt(wxLANGUAGE_NEPALI_INDIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_NORWEGIAN_BOKMAL"); rt.addInt(wxLANGUAGE_NORWEGIAN_BOKMAL); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_NORWEGIAN_NYNORSK"); rt.addInt(wxLANGUAGE_NORWEGIAN_NYNORSK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_OCCITAN"); rt.addInt(wxLANGUAGE_OCCITAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ORIYA"); rt.addInt(wxLANGUAGE_ORIYA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_OROMO"); rt.addInt(wxLANGUAGE_OROMO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_PASHTO"); rt.addInt(wxLANGUAGE_PASHTO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_POLISH"); rt.addInt(wxLANGUAGE_POLISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_PORTUGUESE"); rt.addInt(wxLANGUAGE_PORTUGUESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_PORTUGUESE_BRAZILIAN"); rt.addInt(wxLANGUAGE_PORTUGUESE_BRAZILIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_PUNJABI"); rt.addInt(wxLANGUAGE_PUNJABI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_QUECHUA"); rt.addInt(wxLANGUAGE_QUECHUA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_RHAETO_ROMANCE"); rt.addInt(wxLANGUAGE_RHAETO_ROMANCE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ROMANIAN"); rt.addInt(wxLANGUAGE_ROMANIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_RUSSIAN"); rt.addInt(wxLANGUAGE_RUSSIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_RUSSIAN_UKRAINE"); rt.addInt(wxLANGUAGE_RUSSIAN_UKRAINE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SAMI"); rt.addInt(wxLANGUAGE_SAMI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SAMOAN"); rt.addInt(wxLANGUAGE_SAMOAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SANGHO"); rt.addInt(wxLANGUAGE_SANGHO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SANSKRIT"); rt.addInt(wxLANGUAGE_SANSKRIT); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SCOTS_GAELIC"); rt.addInt(wxLANGUAGE_SCOTS_GAELIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SERBIAN"); rt.addInt(wxLANGUAGE_SERBIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SERBIAN_CYRILLIC"); rt.addInt(wxLANGUAGE_SERBIAN_CYRILLIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SERBIAN_LATIN"); rt.addInt(wxLANGUAGE_SERBIAN_LATIN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SERBO_CROATIAN"); rt.addInt(wxLANGUAGE_SERBO_CROATIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SESOTHO"); rt.addInt(wxLANGUAGE_SESOTHO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SETSWANA"); rt.addInt(wxLANGUAGE_SETSWANA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SHONA"); rt.addInt(wxLANGUAGE_SHONA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SINDHI"); rt.addInt(wxLANGUAGE_SINDHI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SINHALESE"); rt.addInt(wxLANGUAGE_SINHALESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SISWATI"); rt.addInt(wxLANGUAGE_SISWATI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SLOVAK"); rt.addInt(wxLANGUAGE_SLOVAK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SLOVENIAN"); rt.addInt(wxLANGUAGE_SLOVENIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SOMALI"); rt.addInt(wxLANGUAGE_SOMALI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH"); rt.addInt(wxLANGUAGE_SPANISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_ARGENTINA"); rt.addInt(wxLANGUAGE_SPANISH_ARGENTINA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_BOLIVIA"); rt.addInt(wxLANGUAGE_SPANISH_BOLIVIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_CHILE"); rt.addInt(wxLANGUAGE_SPANISH_CHILE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_COLOMBIA"); rt.addInt(wxLANGUAGE_SPANISH_COLOMBIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_COSTA_RICA"); rt.addInt(wxLANGUAGE_SPANISH_COSTA_RICA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC"); rt.addInt(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_ECUADOR"); rt.addInt(wxLANGUAGE_SPANISH_ECUADOR); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_EL_SALVADOR"); rt.addInt(wxLANGUAGE_SPANISH_EL_SALVADOR); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_GUATEMALA"); rt.addInt(wxLANGUAGE_SPANISH_GUATEMALA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_HONDURAS"); rt.addInt(wxLANGUAGE_SPANISH_HONDURAS); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_MEXICAN"); rt.addInt(wxLANGUAGE_SPANISH_MEXICAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_MODERN"); rt.addInt(wxLANGUAGE_SPANISH_MODERN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_NICARAGUA"); rt.addInt(wxLANGUAGE_SPANISH_NICARAGUA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_PANAMA"); rt.addInt(wxLANGUAGE_SPANISH_PANAMA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_PARAGUAY"); rt.addInt(wxLANGUAGE_SPANISH_PARAGUAY); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_PERU"); rt.addInt(wxLANGUAGE_SPANISH_PERU); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_PUERTO_RICO"); rt.addInt(wxLANGUAGE_SPANISH_PUERTO_RICO); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_URUGUAY"); rt.addInt(wxLANGUAGE_SPANISH_URUGUAY); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_US"); rt.addInt(wxLANGUAGE_SPANISH_US); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SPANISH_VENEZUELA"); rt.addInt(wxLANGUAGE_SPANISH_VENEZUELA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SUNDANESE"); rt.addInt(wxLANGUAGE_SUNDANESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SWAHILI"); rt.addInt(wxLANGUAGE_SWAHILI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SWEDISH"); rt.addInt(wxLANGUAGE_SWEDISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_SWEDISH_FINLAND"); rt.addInt(wxLANGUAGE_SWEDISH_FINLAND); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TAGALOG"); rt.addInt(wxLANGUAGE_TAGALOG); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TAJIK"); rt.addInt(wxLANGUAGE_TAJIK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TAMIL"); rt.addInt(wxLANGUAGE_TAMIL); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TATAR"); rt.addInt(wxLANGUAGE_TATAR); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TELUGU"); rt.addInt(wxLANGUAGE_TELUGU); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_THAI"); rt.addInt(wxLANGUAGE_THAI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TIBETAN"); rt.addInt(wxLANGUAGE_TIBETAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TIGRINYA"); rt.addInt(wxLANGUAGE_TIGRINYA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TONGA"); rt.addInt(wxLANGUAGE_TONGA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TSONGA"); rt.addInt(wxLANGUAGE_TSONGA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TURKISH"); rt.addInt(wxLANGUAGE_TURKISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TURKMEN"); rt.addInt(wxLANGUAGE_TURKMEN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_TWI"); rt.addInt(wxLANGUAGE_TWI); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_UIGHUR"); rt.addInt(wxLANGUAGE_UIGHUR); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_UKRAINIAN"); rt.addInt(wxLANGUAGE_UKRAINIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_UNKNOWN"); rt.addInt(wxLANGUAGE_UNKNOWN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_URDU"); rt.addInt(wxLANGUAGE_URDU); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_URDU_INDIA"); rt.addInt(wxLANGUAGE_URDU_INDIA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_URDU_PAKISTAN"); rt.addInt(wxLANGUAGE_URDU_PAKISTAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_USER_DEFINED"); rt.addInt(wxLANGUAGE_USER_DEFINED); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_UZBEK"); rt.addInt(wxLANGUAGE_UZBEK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_UZBEK_CYRILLIC"); rt.addInt(wxLANGUAGE_UZBEK_CYRILLIC); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_UZBEK_LATIN"); rt.addInt(wxLANGUAGE_UZBEK_LATIN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_VALENCIAN"); rt.addInt(wxLANGUAGE_VALENCIAN); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_VIETNAMESE"); rt.addInt(wxLANGUAGE_VIETNAMESE); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_VOLAPUK"); rt.addInt(wxLANGUAGE_VOLAPUK); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_WELSH"); rt.addInt(wxLANGUAGE_WELSH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_WOLOF"); rt.addInt(wxLANGUAGE_WOLOF); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_XHOSA"); rt.addInt(wxLANGUAGE_XHOSA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_YIDDISH"); rt.addInt(wxLANGUAGE_YIDDISH); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_YORUBA"); rt.addInt(wxLANGUAGE_YORUBA); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ZHUANG"); rt.addInt(wxLANGUAGE_ZHUANG); + rt.addTupleCount(2); + rt.addAtom("wxLANGUAGE_ZULU"); rt.addInt(wxLANGUAGE_ZULU); + rt.addTupleCount(2); rt.addAtom("wxCURSOR_ARROWWAIT"); rt.addInt(wxCURSOR_ARROWWAIT); rt.addTupleCount(2); rt.addAtom("wxCURSOR_DEFAULT"); rt.addInt(wxCURSOR_DEFAULT); @@ -145,7 +611,7 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) { rt.addTupleCount(2); rt.addAtom("wxWHITE_PEN"); rt.addRef(getRef((void *)wxWHITE_PEN,memenv),"wxPen"); rt.addTupleCount(2); - rt.endList(60); + rt.endList(293); rt.addTupleCount(2); rt.send(); } diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl index c2a5831415..69ca13aca1 100644 --- a/lib/wx/include/wx.hrl +++ b/lib/wx/include/wx.hrl @@ -2013,239 +2013,239 @@ -define(wxIMAGELIST_DRAW_TRANSPARENT, 2). -define(wxIMAGELIST_DRAW_NORMAL, 1). % From "intl.h": wxLanguage --define(wxLANGUAGE_DEFAULT, 0). --define(wxLANGUAGE_UNKNOWN, 1). --define(wxLANGUAGE_ABKHAZIAN, 2). --define(wxLANGUAGE_AFAR, 3). --define(wxLANGUAGE_AFRIKAANS, 4). --define(wxLANGUAGE_ALBANIAN, 5). --define(wxLANGUAGE_AMHARIC, 6). --define(wxLANGUAGE_ARABIC, 7). --define(wxLANGUAGE_ARABIC_ALGERIA, 8). --define(wxLANGUAGE_ARABIC_BAHRAIN, 9). --define(wxLANGUAGE_ARABIC_EGYPT, 10). --define(wxLANGUAGE_ARABIC_IRAQ, 11). --define(wxLANGUAGE_ARABIC_JORDAN, 12). --define(wxLANGUAGE_ARABIC_KUWAIT, 13). --define(wxLANGUAGE_ARABIC_LEBANON, 14). --define(wxLANGUAGE_ARABIC_LIBYA, 15). --define(wxLANGUAGE_ARABIC_MOROCCO, 16). --define(wxLANGUAGE_ARABIC_OMAN, 17). --define(wxLANGUAGE_ARABIC_QATAR, 18). --define(wxLANGUAGE_ARABIC_SAUDI_ARABIA, 19). --define(wxLANGUAGE_ARABIC_SUDAN, 20). --define(wxLANGUAGE_ARABIC_SYRIA, 21). --define(wxLANGUAGE_ARABIC_TUNISIA, 22). --define(wxLANGUAGE_ARABIC_UAE, 23). --define(wxLANGUAGE_ARABIC_YEMEN, 24). --define(wxLANGUAGE_ARMENIAN, 25). --define(wxLANGUAGE_ASSAMESE, 26). --define(wxLANGUAGE_AYMARA, 27). --define(wxLANGUAGE_AZERI, 28). --define(wxLANGUAGE_AZERI_CYRILLIC, 29). --define(wxLANGUAGE_AZERI_LATIN, 30). --define(wxLANGUAGE_BASHKIR, 31). --define(wxLANGUAGE_BASQUE, 32). --define(wxLANGUAGE_BELARUSIAN, 33). --define(wxLANGUAGE_BENGALI, 34). --define(wxLANGUAGE_BHUTANI, 35). --define(wxLANGUAGE_BIHARI, 36). --define(wxLANGUAGE_BISLAMA, 37). --define(wxLANGUAGE_BRETON, 38). --define(wxLANGUAGE_BULGARIAN, 39). --define(wxLANGUAGE_BURMESE, 40). --define(wxLANGUAGE_CAMBODIAN, 41). --define(wxLANGUAGE_CATALAN, 42). --define(wxLANGUAGE_CHINESE, 43). --define(wxLANGUAGE_CHINESE_SIMPLIFIED, 44). --define(wxLANGUAGE_CHINESE_TRADITIONAL, 45). --define(wxLANGUAGE_CHINESE_HONGKONG, 46). --define(wxLANGUAGE_CHINESE_MACAU, 47). --define(wxLANGUAGE_CHINESE_SINGAPORE, 48). --define(wxLANGUAGE_CHINESE_TAIWAN, 49). --define(wxLANGUAGE_CORSICAN, 50). --define(wxLANGUAGE_CROATIAN, 51). --define(wxLANGUAGE_CZECH, 52). --define(wxLANGUAGE_DANISH, 53). --define(wxLANGUAGE_DUTCH, 54). --define(wxLANGUAGE_DUTCH_BELGIAN, 55). --define(wxLANGUAGE_ENGLISH, 56). --define(wxLANGUAGE_ENGLISH_UK, 57). --define(wxLANGUAGE_ENGLISH_US, 58). --define(wxLANGUAGE_ENGLISH_AUSTRALIA, 59). --define(wxLANGUAGE_ENGLISH_BELIZE, 60). --define(wxLANGUAGE_ENGLISH_BOTSWANA, 61). --define(wxLANGUAGE_ENGLISH_CANADA, 62). --define(wxLANGUAGE_ENGLISH_CARIBBEAN, 63). --define(wxLANGUAGE_ENGLISH_DENMARK, 64). --define(wxLANGUAGE_ENGLISH_EIRE, 65). --define(wxLANGUAGE_ENGLISH_JAMAICA, 66). --define(wxLANGUAGE_ENGLISH_NEW_ZEALAND, 67). --define(wxLANGUAGE_ENGLISH_PHILIPPINES, 68). --define(wxLANGUAGE_ENGLISH_SOUTH_AFRICA, 69). --define(wxLANGUAGE_ENGLISH_TRINIDAD, 70). --define(wxLANGUAGE_ENGLISH_ZIMBABWE, 71). --define(wxLANGUAGE_ESPERANTO, 72). --define(wxLANGUAGE_ESTONIAN, 73). --define(wxLANGUAGE_FAEROESE, 74). --define(wxLANGUAGE_FARSI, 75). --define(wxLANGUAGE_FIJI, 76). --define(wxLANGUAGE_FINNISH, 77). --define(wxLANGUAGE_FRENCH, 78). --define(wxLANGUAGE_FRENCH_BELGIAN, 79). --define(wxLANGUAGE_FRENCH_CANADIAN, 80). --define(wxLANGUAGE_FRENCH_LUXEMBOURG, 81). --define(wxLANGUAGE_FRENCH_MONACO, 82). --define(wxLANGUAGE_FRENCH_SWISS, 83). --define(wxLANGUAGE_FRISIAN, 84). --define(wxLANGUAGE_GALICIAN, 85). --define(wxLANGUAGE_GEORGIAN, 86). --define(wxLANGUAGE_GERMAN, 87). --define(wxLANGUAGE_GERMAN_AUSTRIAN, 88). --define(wxLANGUAGE_GERMAN_BELGIUM, 89). --define(wxLANGUAGE_GERMAN_LIECHTENSTEIN, 90). --define(wxLANGUAGE_GERMAN_LUXEMBOURG, 91). --define(wxLANGUAGE_GERMAN_SWISS, 92). --define(wxLANGUAGE_GREEK, 93). --define(wxLANGUAGE_GREENLANDIC, 94). --define(wxLANGUAGE_GUARANI, 95). --define(wxLANGUAGE_GUJARATI, 96). --define(wxLANGUAGE_HAUSA, 97). --define(wxLANGUAGE_HEBREW, 98). --define(wxLANGUAGE_HINDI, 99). --define(wxLANGUAGE_HUNGARIAN, 100). --define(wxLANGUAGE_ICELANDIC, 101). --define(wxLANGUAGE_INDONESIAN, 102). --define(wxLANGUAGE_INTERLINGUA, 103). --define(wxLANGUAGE_INTERLINGUE, 104). --define(wxLANGUAGE_INUKTITUT, 105). --define(wxLANGUAGE_INUPIAK, 106). --define(wxLANGUAGE_IRISH, 107). --define(wxLANGUAGE_ITALIAN, 108). --define(wxLANGUAGE_ITALIAN_SWISS, 109). --define(wxLANGUAGE_JAPANESE, 110). --define(wxLANGUAGE_JAVANESE, 111). --define(wxLANGUAGE_KANNADA, 112). --define(wxLANGUAGE_KASHMIRI, 113). --define(wxLANGUAGE_KASHMIRI_INDIA, 114). --define(wxLANGUAGE_KAZAKH, 115). --define(wxLANGUAGE_KERNEWEK, 116). --define(wxLANGUAGE_KINYARWANDA, 117). --define(wxLANGUAGE_KIRGHIZ, 118). --define(wxLANGUAGE_KIRUNDI, 119). --define(wxLANGUAGE_KONKANI, 120). --define(wxLANGUAGE_KOREAN, 121). --define(wxLANGUAGE_KURDISH, 122). --define(wxLANGUAGE_LAOTHIAN, 123). --define(wxLANGUAGE_LATIN, 124). --define(wxLANGUAGE_LATVIAN, 125). --define(wxLANGUAGE_LINGALA, 126). --define(wxLANGUAGE_LITHUANIAN, 127). --define(wxLANGUAGE_MACEDONIAN, 128). --define(wxLANGUAGE_MALAGASY, 129). --define(wxLANGUAGE_MALAY, 130). --define(wxLANGUAGE_MALAYALAM, 131). --define(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM, 132). --define(wxLANGUAGE_MALAY_MALAYSIA, 133). --define(wxLANGUAGE_MALTESE, 134). --define(wxLANGUAGE_MANIPURI, 135). --define(wxLANGUAGE_MAORI, 136). --define(wxLANGUAGE_MARATHI, 137). --define(wxLANGUAGE_MOLDAVIAN, 138). --define(wxLANGUAGE_MONGOLIAN, 139). --define(wxLANGUAGE_NAURU, 140). --define(wxLANGUAGE_NEPALI, 141). --define(wxLANGUAGE_NEPALI_INDIA, 142). --define(wxLANGUAGE_NORWEGIAN_BOKMAL, 143). --define(wxLANGUAGE_NORWEGIAN_NYNORSK, 144). --define(wxLANGUAGE_OCCITAN, 145). --define(wxLANGUAGE_ORIYA, 146). --define(wxLANGUAGE_OROMO, 147). --define(wxLANGUAGE_PASHTO, 148). --define(wxLANGUAGE_POLISH, 149). --define(wxLANGUAGE_PORTUGUESE, 150). --define(wxLANGUAGE_PORTUGUESE_BRAZILIAN, 151). --define(wxLANGUAGE_PUNJABI, 152). --define(wxLANGUAGE_QUECHUA, 153). --define(wxLANGUAGE_RHAETO_ROMANCE, 154). --define(wxLANGUAGE_ROMANIAN, 155). --define(wxLANGUAGE_RUSSIAN, 156). --define(wxLANGUAGE_RUSSIAN_UKRAINE, 157). --define(wxLANGUAGE_SAMOAN, 158). --define(wxLANGUAGE_SANGHO, 159). --define(wxLANGUAGE_SANSKRIT, 160). --define(wxLANGUAGE_SCOTS_GAELIC, 161). --define(wxLANGUAGE_SERBIAN, 162). --define(wxLANGUAGE_SERBIAN_CYRILLIC, 163). --define(wxLANGUAGE_SERBIAN_LATIN, 164). --define(wxLANGUAGE_SERBO_CROATIAN, 165). --define(wxLANGUAGE_SESOTHO, 166). --define(wxLANGUAGE_SETSWANA, 167). --define(wxLANGUAGE_SHONA, 168). --define(wxLANGUAGE_SINDHI, 169). --define(wxLANGUAGE_SINHALESE, 170). --define(wxLANGUAGE_SISWATI, 171). --define(wxLANGUAGE_SLOVAK, 172). --define(wxLANGUAGE_SLOVENIAN, 173). --define(wxLANGUAGE_SOMALI, 174). --define(wxLANGUAGE_SPANISH, 175). --define(wxLANGUAGE_SPANISH_ARGENTINA, 176). --define(wxLANGUAGE_SPANISH_BOLIVIA, 177). --define(wxLANGUAGE_SPANISH_CHILE, 178). --define(wxLANGUAGE_SPANISH_COLOMBIA, 179). --define(wxLANGUAGE_SPANISH_COSTA_RICA, 180). --define(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC, 181). --define(wxLANGUAGE_SPANISH_ECUADOR, 182). --define(wxLANGUAGE_SPANISH_EL_SALVADOR, 183). --define(wxLANGUAGE_SPANISH_GUATEMALA, 184). --define(wxLANGUAGE_SPANISH_HONDURAS, 185). --define(wxLANGUAGE_SPANISH_MEXICAN, 186). --define(wxLANGUAGE_SPANISH_MODERN, 187). --define(wxLANGUAGE_SPANISH_NICARAGUA, 188). --define(wxLANGUAGE_SPANISH_PANAMA, 189). --define(wxLANGUAGE_SPANISH_PARAGUAY, 190). --define(wxLANGUAGE_SPANISH_PERU, 191). --define(wxLANGUAGE_SPANISH_PUERTO_RICO, 192). --define(wxLANGUAGE_SPANISH_URUGUAY, 193). --define(wxLANGUAGE_SPANISH_US, 194). --define(wxLANGUAGE_SPANISH_VENEZUELA, 195). --define(wxLANGUAGE_SUNDANESE, 196). --define(wxLANGUAGE_SWAHILI, 197). --define(wxLANGUAGE_SWEDISH, 198). --define(wxLANGUAGE_SWEDISH_FINLAND, 199). --define(wxLANGUAGE_TAGALOG, 200). --define(wxLANGUAGE_TAJIK, 201). --define(wxLANGUAGE_TAMIL, 202). --define(wxLANGUAGE_TATAR, 203). --define(wxLANGUAGE_TELUGU, 204). --define(wxLANGUAGE_THAI, 205). --define(wxLANGUAGE_TIBETAN, 206). --define(wxLANGUAGE_TIGRINYA, 207). --define(wxLANGUAGE_TONGA, 208). --define(wxLANGUAGE_TSONGA, 209). --define(wxLANGUAGE_TURKISH, 210). --define(wxLANGUAGE_TURKMEN, 211). --define(wxLANGUAGE_TWI, 212). --define(wxLANGUAGE_UIGHUR, 213). --define(wxLANGUAGE_UKRAINIAN, 214). --define(wxLANGUAGE_URDU, 215). --define(wxLANGUAGE_URDU_INDIA, 216). --define(wxLANGUAGE_URDU_PAKISTAN, 217). --define(wxLANGUAGE_UZBEK, 218). --define(wxLANGUAGE_UZBEK_CYRILLIC, 219). --define(wxLANGUAGE_UZBEK_LATIN, 220). --define(wxLANGUAGE_VIETNAMESE, 221). --define(wxLANGUAGE_VOLAPUK, 222). --define(wxLANGUAGE_WELSH, 223). --define(wxLANGUAGE_WOLOF, 224). --define(wxLANGUAGE_XHOSA, 225). --define(wxLANGUAGE_YIDDISH, 226). --define(wxLANGUAGE_YORUBA, 227). --define(wxLANGUAGE_ZHUANG, 228). --define(wxLANGUAGE_ZULU, 229). --define(wxLANGUAGE_USER_DEFINED, 230). --define(wxLANGUAGE_VALENCIAN, 536870911). --define(wxLANGUAGE_SAMI, 536870912). +-define(wxLANGUAGE_DEFAULT, wxe_util:get_const(wxLANGUAGE_DEFAULT)). +-define(wxLANGUAGE_UNKNOWN, wxe_util:get_const(wxLANGUAGE_UNKNOWN)). +-define(wxLANGUAGE_ABKHAZIAN, wxe_util:get_const(wxLANGUAGE_ABKHAZIAN)). +-define(wxLANGUAGE_AFAR, wxe_util:get_const(wxLANGUAGE_AFAR)). +-define(wxLANGUAGE_AFRIKAANS, wxe_util:get_const(wxLANGUAGE_AFRIKAANS)). +-define(wxLANGUAGE_ALBANIAN, wxe_util:get_const(wxLANGUAGE_ALBANIAN)). +-define(wxLANGUAGE_AMHARIC, wxe_util:get_const(wxLANGUAGE_AMHARIC)). +-define(wxLANGUAGE_ARABIC, wxe_util:get_const(wxLANGUAGE_ARABIC)). +-define(wxLANGUAGE_ARABIC_ALGERIA, wxe_util:get_const(wxLANGUAGE_ARABIC_ALGERIA)). +-define(wxLANGUAGE_ARABIC_BAHRAIN, wxe_util:get_const(wxLANGUAGE_ARABIC_BAHRAIN)). +-define(wxLANGUAGE_ARABIC_EGYPT, wxe_util:get_const(wxLANGUAGE_ARABIC_EGYPT)). +-define(wxLANGUAGE_ARABIC_IRAQ, wxe_util:get_const(wxLANGUAGE_ARABIC_IRAQ)). +-define(wxLANGUAGE_ARABIC_JORDAN, wxe_util:get_const(wxLANGUAGE_ARABIC_JORDAN)). +-define(wxLANGUAGE_ARABIC_KUWAIT, wxe_util:get_const(wxLANGUAGE_ARABIC_KUWAIT)). +-define(wxLANGUAGE_ARABIC_LEBANON, wxe_util:get_const(wxLANGUAGE_ARABIC_LEBANON)). +-define(wxLANGUAGE_ARABIC_LIBYA, wxe_util:get_const(wxLANGUAGE_ARABIC_LIBYA)). +-define(wxLANGUAGE_ARABIC_MOROCCO, wxe_util:get_const(wxLANGUAGE_ARABIC_MOROCCO)). +-define(wxLANGUAGE_ARABIC_OMAN, wxe_util:get_const(wxLANGUAGE_ARABIC_OMAN)). +-define(wxLANGUAGE_ARABIC_QATAR, wxe_util:get_const(wxLANGUAGE_ARABIC_QATAR)). +-define(wxLANGUAGE_ARABIC_SAUDI_ARABIA, wxe_util:get_const(wxLANGUAGE_ARABIC_SAUDI_ARABIA)). +-define(wxLANGUAGE_ARABIC_SUDAN, wxe_util:get_const(wxLANGUAGE_ARABIC_SUDAN)). +-define(wxLANGUAGE_ARABIC_SYRIA, wxe_util:get_const(wxLANGUAGE_ARABIC_SYRIA)). +-define(wxLANGUAGE_ARABIC_TUNISIA, wxe_util:get_const(wxLANGUAGE_ARABIC_TUNISIA)). +-define(wxLANGUAGE_ARABIC_UAE, wxe_util:get_const(wxLANGUAGE_ARABIC_UAE)). +-define(wxLANGUAGE_ARABIC_YEMEN, wxe_util:get_const(wxLANGUAGE_ARABIC_YEMEN)). +-define(wxLANGUAGE_ARMENIAN, wxe_util:get_const(wxLANGUAGE_ARMENIAN)). +-define(wxLANGUAGE_ASSAMESE, wxe_util:get_const(wxLANGUAGE_ASSAMESE)). +-define(wxLANGUAGE_AYMARA, wxe_util:get_const(wxLANGUAGE_AYMARA)). +-define(wxLANGUAGE_AZERI, wxe_util:get_const(wxLANGUAGE_AZERI)). +-define(wxLANGUAGE_AZERI_CYRILLIC, wxe_util:get_const(wxLANGUAGE_AZERI_CYRILLIC)). +-define(wxLANGUAGE_AZERI_LATIN, wxe_util:get_const(wxLANGUAGE_AZERI_LATIN)). +-define(wxLANGUAGE_BASHKIR, wxe_util:get_const(wxLANGUAGE_BASHKIR)). +-define(wxLANGUAGE_BASQUE, wxe_util:get_const(wxLANGUAGE_BASQUE)). +-define(wxLANGUAGE_BELARUSIAN, wxe_util:get_const(wxLANGUAGE_BELARUSIAN)). +-define(wxLANGUAGE_BENGALI, wxe_util:get_const(wxLANGUAGE_BENGALI)). +-define(wxLANGUAGE_BHUTANI, wxe_util:get_const(wxLANGUAGE_BHUTANI)). +-define(wxLANGUAGE_BIHARI, wxe_util:get_const(wxLANGUAGE_BIHARI)). +-define(wxLANGUAGE_BISLAMA, wxe_util:get_const(wxLANGUAGE_BISLAMA)). +-define(wxLANGUAGE_BRETON, wxe_util:get_const(wxLANGUAGE_BRETON)). +-define(wxLANGUAGE_BULGARIAN, wxe_util:get_const(wxLANGUAGE_BULGARIAN)). +-define(wxLANGUAGE_BURMESE, wxe_util:get_const(wxLANGUAGE_BURMESE)). +-define(wxLANGUAGE_CAMBODIAN, wxe_util:get_const(wxLANGUAGE_CAMBODIAN)). +-define(wxLANGUAGE_CATALAN, wxe_util:get_const(wxLANGUAGE_CATALAN)). +-define(wxLANGUAGE_CHINESE, wxe_util:get_const(wxLANGUAGE_CHINESE)). +-define(wxLANGUAGE_CHINESE_SIMPLIFIED, wxe_util:get_const(wxLANGUAGE_CHINESE_SIMPLIFIED)). +-define(wxLANGUAGE_CHINESE_TRADITIONAL, wxe_util:get_const(wxLANGUAGE_CHINESE_TRADITIONAL)). +-define(wxLANGUAGE_CHINESE_HONGKONG, wxe_util:get_const(wxLANGUAGE_CHINESE_HONGKONG)). +-define(wxLANGUAGE_CHINESE_MACAU, wxe_util:get_const(wxLANGUAGE_CHINESE_MACAU)). +-define(wxLANGUAGE_CHINESE_SINGAPORE, wxe_util:get_const(wxLANGUAGE_CHINESE_SINGAPORE)). +-define(wxLANGUAGE_CHINESE_TAIWAN, wxe_util:get_const(wxLANGUAGE_CHINESE_TAIWAN)). +-define(wxLANGUAGE_CORSICAN, wxe_util:get_const(wxLANGUAGE_CORSICAN)). +-define(wxLANGUAGE_CROATIAN, wxe_util:get_const(wxLANGUAGE_CROATIAN)). +-define(wxLANGUAGE_CZECH, wxe_util:get_const(wxLANGUAGE_CZECH)). +-define(wxLANGUAGE_DANISH, wxe_util:get_const(wxLANGUAGE_DANISH)). +-define(wxLANGUAGE_DUTCH, wxe_util:get_const(wxLANGUAGE_DUTCH)). +-define(wxLANGUAGE_DUTCH_BELGIAN, wxe_util:get_const(wxLANGUAGE_DUTCH_BELGIAN)). +-define(wxLANGUAGE_ENGLISH, wxe_util:get_const(wxLANGUAGE_ENGLISH)). +-define(wxLANGUAGE_ENGLISH_UK, wxe_util:get_const(wxLANGUAGE_ENGLISH_UK)). +-define(wxLANGUAGE_ENGLISH_US, wxe_util:get_const(wxLANGUAGE_ENGLISH_US)). +-define(wxLANGUAGE_ENGLISH_AUSTRALIA, wxe_util:get_const(wxLANGUAGE_ENGLISH_AUSTRALIA)). +-define(wxLANGUAGE_ENGLISH_BELIZE, wxe_util:get_const(wxLANGUAGE_ENGLISH_BELIZE)). +-define(wxLANGUAGE_ENGLISH_BOTSWANA, wxe_util:get_const(wxLANGUAGE_ENGLISH_BOTSWANA)). +-define(wxLANGUAGE_ENGLISH_CANADA, wxe_util:get_const(wxLANGUAGE_ENGLISH_CANADA)). +-define(wxLANGUAGE_ENGLISH_CARIBBEAN, wxe_util:get_const(wxLANGUAGE_ENGLISH_CARIBBEAN)). +-define(wxLANGUAGE_ENGLISH_DENMARK, wxe_util:get_const(wxLANGUAGE_ENGLISH_DENMARK)). +-define(wxLANGUAGE_ENGLISH_EIRE, wxe_util:get_const(wxLANGUAGE_ENGLISH_EIRE)). +-define(wxLANGUAGE_ENGLISH_JAMAICA, wxe_util:get_const(wxLANGUAGE_ENGLISH_JAMAICA)). +-define(wxLANGUAGE_ENGLISH_NEW_ZEALAND, wxe_util:get_const(wxLANGUAGE_ENGLISH_NEW_ZEALAND)). +-define(wxLANGUAGE_ENGLISH_PHILIPPINES, wxe_util:get_const(wxLANGUAGE_ENGLISH_PHILIPPINES)). +-define(wxLANGUAGE_ENGLISH_SOUTH_AFRICA, wxe_util:get_const(wxLANGUAGE_ENGLISH_SOUTH_AFRICA)). +-define(wxLANGUAGE_ENGLISH_TRINIDAD, wxe_util:get_const(wxLANGUAGE_ENGLISH_TRINIDAD)). +-define(wxLANGUAGE_ENGLISH_ZIMBABWE, wxe_util:get_const(wxLANGUAGE_ENGLISH_ZIMBABWE)). +-define(wxLANGUAGE_ESPERANTO, wxe_util:get_const(wxLANGUAGE_ESPERANTO)). +-define(wxLANGUAGE_ESTONIAN, wxe_util:get_const(wxLANGUAGE_ESTONIAN)). +-define(wxLANGUAGE_FAEROESE, wxe_util:get_const(wxLANGUAGE_FAEROESE)). +-define(wxLANGUAGE_FARSI, wxe_util:get_const(wxLANGUAGE_FARSI)). +-define(wxLANGUAGE_FIJI, wxe_util:get_const(wxLANGUAGE_FIJI)). +-define(wxLANGUAGE_FINNISH, wxe_util:get_const(wxLANGUAGE_FINNISH)). +-define(wxLANGUAGE_FRENCH, wxe_util:get_const(wxLANGUAGE_FRENCH)). +-define(wxLANGUAGE_FRENCH_BELGIAN, wxe_util:get_const(wxLANGUAGE_FRENCH_BELGIAN)). +-define(wxLANGUAGE_FRENCH_CANADIAN, wxe_util:get_const(wxLANGUAGE_FRENCH_CANADIAN)). +-define(wxLANGUAGE_FRENCH_LUXEMBOURG, wxe_util:get_const(wxLANGUAGE_FRENCH_LUXEMBOURG)). +-define(wxLANGUAGE_FRENCH_MONACO, wxe_util:get_const(wxLANGUAGE_FRENCH_MONACO)). +-define(wxLANGUAGE_FRENCH_SWISS, wxe_util:get_const(wxLANGUAGE_FRENCH_SWISS)). +-define(wxLANGUAGE_FRISIAN, wxe_util:get_const(wxLANGUAGE_FRISIAN)). +-define(wxLANGUAGE_GALICIAN, wxe_util:get_const(wxLANGUAGE_GALICIAN)). +-define(wxLANGUAGE_GEORGIAN, wxe_util:get_const(wxLANGUAGE_GEORGIAN)). +-define(wxLANGUAGE_GERMAN, wxe_util:get_const(wxLANGUAGE_GERMAN)). +-define(wxLANGUAGE_GERMAN_AUSTRIAN, wxe_util:get_const(wxLANGUAGE_GERMAN_AUSTRIAN)). +-define(wxLANGUAGE_GERMAN_BELGIUM, wxe_util:get_const(wxLANGUAGE_GERMAN_BELGIUM)). +-define(wxLANGUAGE_GERMAN_LIECHTENSTEIN, wxe_util:get_const(wxLANGUAGE_GERMAN_LIECHTENSTEIN)). +-define(wxLANGUAGE_GERMAN_LUXEMBOURG, wxe_util:get_const(wxLANGUAGE_GERMAN_LUXEMBOURG)). +-define(wxLANGUAGE_GERMAN_SWISS, wxe_util:get_const(wxLANGUAGE_GERMAN_SWISS)). +-define(wxLANGUAGE_GREEK, wxe_util:get_const(wxLANGUAGE_GREEK)). +-define(wxLANGUAGE_GREENLANDIC, wxe_util:get_const(wxLANGUAGE_GREENLANDIC)). +-define(wxLANGUAGE_GUARANI, wxe_util:get_const(wxLANGUAGE_GUARANI)). +-define(wxLANGUAGE_GUJARATI, wxe_util:get_const(wxLANGUAGE_GUJARATI)). +-define(wxLANGUAGE_HAUSA, wxe_util:get_const(wxLANGUAGE_HAUSA)). +-define(wxLANGUAGE_HEBREW, wxe_util:get_const(wxLANGUAGE_HEBREW)). +-define(wxLANGUAGE_HINDI, wxe_util:get_const(wxLANGUAGE_HINDI)). +-define(wxLANGUAGE_HUNGARIAN, wxe_util:get_const(wxLANGUAGE_HUNGARIAN)). +-define(wxLANGUAGE_ICELANDIC, wxe_util:get_const(wxLANGUAGE_ICELANDIC)). +-define(wxLANGUAGE_INDONESIAN, wxe_util:get_const(wxLANGUAGE_INDONESIAN)). +-define(wxLANGUAGE_INTERLINGUA, wxe_util:get_const(wxLANGUAGE_INTERLINGUA)). +-define(wxLANGUAGE_INTERLINGUE, wxe_util:get_const(wxLANGUAGE_INTERLINGUE)). +-define(wxLANGUAGE_INUKTITUT, wxe_util:get_const(wxLANGUAGE_INUKTITUT)). +-define(wxLANGUAGE_INUPIAK, wxe_util:get_const(wxLANGUAGE_INUPIAK)). +-define(wxLANGUAGE_IRISH, wxe_util:get_const(wxLANGUAGE_IRISH)). +-define(wxLANGUAGE_ITALIAN, wxe_util:get_const(wxLANGUAGE_ITALIAN)). +-define(wxLANGUAGE_ITALIAN_SWISS, wxe_util:get_const(wxLANGUAGE_ITALIAN_SWISS)). +-define(wxLANGUAGE_JAPANESE, wxe_util:get_const(wxLANGUAGE_JAPANESE)). +-define(wxLANGUAGE_JAVANESE, wxe_util:get_const(wxLANGUAGE_JAVANESE)). +-define(wxLANGUAGE_KANNADA, wxe_util:get_const(wxLANGUAGE_KANNADA)). +-define(wxLANGUAGE_KASHMIRI, wxe_util:get_const(wxLANGUAGE_KASHMIRI)). +-define(wxLANGUAGE_KASHMIRI_INDIA, wxe_util:get_const(wxLANGUAGE_KASHMIRI_INDIA)). +-define(wxLANGUAGE_KAZAKH, wxe_util:get_const(wxLANGUAGE_KAZAKH)). +-define(wxLANGUAGE_KERNEWEK, wxe_util:get_const(wxLANGUAGE_KERNEWEK)). +-define(wxLANGUAGE_KINYARWANDA, wxe_util:get_const(wxLANGUAGE_KINYARWANDA)). +-define(wxLANGUAGE_KIRGHIZ, wxe_util:get_const(wxLANGUAGE_KIRGHIZ)). +-define(wxLANGUAGE_KIRUNDI, wxe_util:get_const(wxLANGUAGE_KIRUNDI)). +-define(wxLANGUAGE_KONKANI, wxe_util:get_const(wxLANGUAGE_KONKANI)). +-define(wxLANGUAGE_KOREAN, wxe_util:get_const(wxLANGUAGE_KOREAN)). +-define(wxLANGUAGE_KURDISH, wxe_util:get_const(wxLANGUAGE_KURDISH)). +-define(wxLANGUAGE_LAOTHIAN, wxe_util:get_const(wxLANGUAGE_LAOTHIAN)). +-define(wxLANGUAGE_LATIN, wxe_util:get_const(wxLANGUAGE_LATIN)). +-define(wxLANGUAGE_LATVIAN, wxe_util:get_const(wxLANGUAGE_LATVIAN)). +-define(wxLANGUAGE_LINGALA, wxe_util:get_const(wxLANGUAGE_LINGALA)). +-define(wxLANGUAGE_LITHUANIAN, wxe_util:get_const(wxLANGUAGE_LITHUANIAN)). +-define(wxLANGUAGE_MACEDONIAN, wxe_util:get_const(wxLANGUAGE_MACEDONIAN)). +-define(wxLANGUAGE_MALAGASY, wxe_util:get_const(wxLANGUAGE_MALAGASY)). +-define(wxLANGUAGE_MALAY, wxe_util:get_const(wxLANGUAGE_MALAY)). +-define(wxLANGUAGE_MALAYALAM, wxe_util:get_const(wxLANGUAGE_MALAYALAM)). +-define(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM, wxe_util:get_const(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM)). +-define(wxLANGUAGE_MALAY_MALAYSIA, wxe_util:get_const(wxLANGUAGE_MALAY_MALAYSIA)). +-define(wxLANGUAGE_MALTESE, wxe_util:get_const(wxLANGUAGE_MALTESE)). +-define(wxLANGUAGE_MANIPURI, wxe_util:get_const(wxLANGUAGE_MANIPURI)). +-define(wxLANGUAGE_MAORI, wxe_util:get_const(wxLANGUAGE_MAORI)). +-define(wxLANGUAGE_MARATHI, wxe_util:get_const(wxLANGUAGE_MARATHI)). +-define(wxLANGUAGE_MOLDAVIAN, wxe_util:get_const(wxLANGUAGE_MOLDAVIAN)). +-define(wxLANGUAGE_MONGOLIAN, wxe_util:get_const(wxLANGUAGE_MONGOLIAN)). +-define(wxLANGUAGE_NAURU, wxe_util:get_const(wxLANGUAGE_NAURU)). +-define(wxLANGUAGE_NEPALI, wxe_util:get_const(wxLANGUAGE_NEPALI)). +-define(wxLANGUAGE_NEPALI_INDIA, wxe_util:get_const(wxLANGUAGE_NEPALI_INDIA)). +-define(wxLANGUAGE_NORWEGIAN_BOKMAL, wxe_util:get_const(wxLANGUAGE_NORWEGIAN_BOKMAL)). +-define(wxLANGUAGE_NORWEGIAN_NYNORSK, wxe_util:get_const(wxLANGUAGE_NORWEGIAN_NYNORSK)). +-define(wxLANGUAGE_OCCITAN, wxe_util:get_const(wxLANGUAGE_OCCITAN)). +-define(wxLANGUAGE_ORIYA, wxe_util:get_const(wxLANGUAGE_ORIYA)). +-define(wxLANGUAGE_OROMO, wxe_util:get_const(wxLANGUAGE_OROMO)). +-define(wxLANGUAGE_PASHTO, wxe_util:get_const(wxLANGUAGE_PASHTO)). +-define(wxLANGUAGE_POLISH, wxe_util:get_const(wxLANGUAGE_POLISH)). +-define(wxLANGUAGE_PORTUGUESE, wxe_util:get_const(wxLANGUAGE_PORTUGUESE)). +-define(wxLANGUAGE_PORTUGUESE_BRAZILIAN, wxe_util:get_const(wxLANGUAGE_PORTUGUESE_BRAZILIAN)). +-define(wxLANGUAGE_PUNJABI, wxe_util:get_const(wxLANGUAGE_PUNJABI)). +-define(wxLANGUAGE_QUECHUA, wxe_util:get_const(wxLANGUAGE_QUECHUA)). +-define(wxLANGUAGE_RHAETO_ROMANCE, wxe_util:get_const(wxLANGUAGE_RHAETO_ROMANCE)). +-define(wxLANGUAGE_ROMANIAN, wxe_util:get_const(wxLANGUAGE_ROMANIAN)). +-define(wxLANGUAGE_RUSSIAN, wxe_util:get_const(wxLANGUAGE_RUSSIAN)). +-define(wxLANGUAGE_RUSSIAN_UKRAINE, wxe_util:get_const(wxLANGUAGE_RUSSIAN_UKRAINE)). +-define(wxLANGUAGE_SAMOAN, wxe_util:get_const(wxLANGUAGE_SAMOAN)). +-define(wxLANGUAGE_SANGHO, wxe_util:get_const(wxLANGUAGE_SANGHO)). +-define(wxLANGUAGE_SANSKRIT, wxe_util:get_const(wxLANGUAGE_SANSKRIT)). +-define(wxLANGUAGE_SCOTS_GAELIC, wxe_util:get_const(wxLANGUAGE_SCOTS_GAELIC)). +-define(wxLANGUAGE_SERBIAN, wxe_util:get_const(wxLANGUAGE_SERBIAN)). +-define(wxLANGUAGE_SERBIAN_CYRILLIC, wxe_util:get_const(wxLANGUAGE_SERBIAN_CYRILLIC)). +-define(wxLANGUAGE_SERBIAN_LATIN, wxe_util:get_const(wxLANGUAGE_SERBIAN_LATIN)). +-define(wxLANGUAGE_SERBO_CROATIAN, wxe_util:get_const(wxLANGUAGE_SERBO_CROATIAN)). +-define(wxLANGUAGE_SESOTHO, wxe_util:get_const(wxLANGUAGE_SESOTHO)). +-define(wxLANGUAGE_SETSWANA, wxe_util:get_const(wxLANGUAGE_SETSWANA)). +-define(wxLANGUAGE_SHONA, wxe_util:get_const(wxLANGUAGE_SHONA)). +-define(wxLANGUAGE_SINDHI, wxe_util:get_const(wxLANGUAGE_SINDHI)). +-define(wxLANGUAGE_SINHALESE, wxe_util:get_const(wxLANGUAGE_SINHALESE)). +-define(wxLANGUAGE_SISWATI, wxe_util:get_const(wxLANGUAGE_SISWATI)). +-define(wxLANGUAGE_SLOVAK, wxe_util:get_const(wxLANGUAGE_SLOVAK)). +-define(wxLANGUAGE_SLOVENIAN, wxe_util:get_const(wxLANGUAGE_SLOVENIAN)). +-define(wxLANGUAGE_SOMALI, wxe_util:get_const(wxLANGUAGE_SOMALI)). +-define(wxLANGUAGE_SPANISH, wxe_util:get_const(wxLANGUAGE_SPANISH)). +-define(wxLANGUAGE_SPANISH_ARGENTINA, wxe_util:get_const(wxLANGUAGE_SPANISH_ARGENTINA)). +-define(wxLANGUAGE_SPANISH_BOLIVIA, wxe_util:get_const(wxLANGUAGE_SPANISH_BOLIVIA)). +-define(wxLANGUAGE_SPANISH_CHILE, wxe_util:get_const(wxLANGUAGE_SPANISH_CHILE)). +-define(wxLANGUAGE_SPANISH_COLOMBIA, wxe_util:get_const(wxLANGUAGE_SPANISH_COLOMBIA)). +-define(wxLANGUAGE_SPANISH_COSTA_RICA, wxe_util:get_const(wxLANGUAGE_SPANISH_COSTA_RICA)). +-define(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC, wxe_util:get_const(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC)). +-define(wxLANGUAGE_SPANISH_ECUADOR, wxe_util:get_const(wxLANGUAGE_SPANISH_ECUADOR)). +-define(wxLANGUAGE_SPANISH_EL_SALVADOR, wxe_util:get_const(wxLANGUAGE_SPANISH_EL_SALVADOR)). +-define(wxLANGUAGE_SPANISH_GUATEMALA, wxe_util:get_const(wxLANGUAGE_SPANISH_GUATEMALA)). +-define(wxLANGUAGE_SPANISH_HONDURAS, wxe_util:get_const(wxLANGUAGE_SPANISH_HONDURAS)). +-define(wxLANGUAGE_SPANISH_MEXICAN, wxe_util:get_const(wxLANGUAGE_SPANISH_MEXICAN)). +-define(wxLANGUAGE_SPANISH_MODERN, wxe_util:get_const(wxLANGUAGE_SPANISH_MODERN)). +-define(wxLANGUAGE_SPANISH_NICARAGUA, wxe_util:get_const(wxLANGUAGE_SPANISH_NICARAGUA)). +-define(wxLANGUAGE_SPANISH_PANAMA, wxe_util:get_const(wxLANGUAGE_SPANISH_PANAMA)). +-define(wxLANGUAGE_SPANISH_PARAGUAY, wxe_util:get_const(wxLANGUAGE_SPANISH_PARAGUAY)). +-define(wxLANGUAGE_SPANISH_PERU, wxe_util:get_const(wxLANGUAGE_SPANISH_PERU)). +-define(wxLANGUAGE_SPANISH_PUERTO_RICO, wxe_util:get_const(wxLANGUAGE_SPANISH_PUERTO_RICO)). +-define(wxLANGUAGE_SPANISH_URUGUAY, wxe_util:get_const(wxLANGUAGE_SPANISH_URUGUAY)). +-define(wxLANGUAGE_SPANISH_US, wxe_util:get_const(wxLANGUAGE_SPANISH_US)). +-define(wxLANGUAGE_SPANISH_VENEZUELA, wxe_util:get_const(wxLANGUAGE_SPANISH_VENEZUELA)). +-define(wxLANGUAGE_SUNDANESE, wxe_util:get_const(wxLANGUAGE_SUNDANESE)). +-define(wxLANGUAGE_SWAHILI, wxe_util:get_const(wxLANGUAGE_SWAHILI)). +-define(wxLANGUAGE_SWEDISH, wxe_util:get_const(wxLANGUAGE_SWEDISH)). +-define(wxLANGUAGE_SWEDISH_FINLAND, wxe_util:get_const(wxLANGUAGE_SWEDISH_FINLAND)). +-define(wxLANGUAGE_TAGALOG, wxe_util:get_const(wxLANGUAGE_TAGALOG)). +-define(wxLANGUAGE_TAJIK, wxe_util:get_const(wxLANGUAGE_TAJIK)). +-define(wxLANGUAGE_TAMIL, wxe_util:get_const(wxLANGUAGE_TAMIL)). +-define(wxLANGUAGE_TATAR, wxe_util:get_const(wxLANGUAGE_TATAR)). +-define(wxLANGUAGE_TELUGU, wxe_util:get_const(wxLANGUAGE_TELUGU)). +-define(wxLANGUAGE_THAI, wxe_util:get_const(wxLANGUAGE_THAI)). +-define(wxLANGUAGE_TIBETAN, wxe_util:get_const(wxLANGUAGE_TIBETAN)). +-define(wxLANGUAGE_TIGRINYA, wxe_util:get_const(wxLANGUAGE_TIGRINYA)). +-define(wxLANGUAGE_TONGA, wxe_util:get_const(wxLANGUAGE_TONGA)). +-define(wxLANGUAGE_TSONGA, wxe_util:get_const(wxLANGUAGE_TSONGA)). +-define(wxLANGUAGE_TURKISH, wxe_util:get_const(wxLANGUAGE_TURKISH)). +-define(wxLANGUAGE_TURKMEN, wxe_util:get_const(wxLANGUAGE_TURKMEN)). +-define(wxLANGUAGE_TWI, wxe_util:get_const(wxLANGUAGE_TWI)). +-define(wxLANGUAGE_UIGHUR, wxe_util:get_const(wxLANGUAGE_UIGHUR)). +-define(wxLANGUAGE_UKRAINIAN, wxe_util:get_const(wxLANGUAGE_UKRAINIAN)). +-define(wxLANGUAGE_URDU, wxe_util:get_const(wxLANGUAGE_URDU)). +-define(wxLANGUAGE_URDU_INDIA, wxe_util:get_const(wxLANGUAGE_URDU_INDIA)). +-define(wxLANGUAGE_URDU_PAKISTAN, wxe_util:get_const(wxLANGUAGE_URDU_PAKISTAN)). +-define(wxLANGUAGE_UZBEK, wxe_util:get_const(wxLANGUAGE_UZBEK)). +-define(wxLANGUAGE_UZBEK_CYRILLIC, wxe_util:get_const(wxLANGUAGE_UZBEK_CYRILLIC)). +-define(wxLANGUAGE_UZBEK_LATIN, wxe_util:get_const(wxLANGUAGE_UZBEK_LATIN)). +-define(wxLANGUAGE_VIETNAMESE, wxe_util:get_const(wxLANGUAGE_VIETNAMESE)). +-define(wxLANGUAGE_VOLAPUK, wxe_util:get_const(wxLANGUAGE_VOLAPUK)). +-define(wxLANGUAGE_WELSH, wxe_util:get_const(wxLANGUAGE_WELSH)). +-define(wxLANGUAGE_WOLOF, wxe_util:get_const(wxLANGUAGE_WOLOF)). +-define(wxLANGUAGE_XHOSA, wxe_util:get_const(wxLANGUAGE_XHOSA)). +-define(wxLANGUAGE_YIDDISH, wxe_util:get_const(wxLANGUAGE_YIDDISH)). +-define(wxLANGUAGE_YORUBA, wxe_util:get_const(wxLANGUAGE_YORUBA)). +-define(wxLANGUAGE_ZHUANG, wxe_util:get_const(wxLANGUAGE_ZHUANG)). +-define(wxLANGUAGE_ZULU, wxe_util:get_const(wxLANGUAGE_ZULU)). +-define(wxLANGUAGE_USER_DEFINED, wxe_util:get_const(wxLANGUAGE_USER_DEFINED)). +-define(wxLANGUAGE_VALENCIAN, wxe_util:get_const(wxLANGUAGE_VALENCIAN)). +-define(wxLANGUAGE_SAMI, wxe_util:get_const(wxLANGUAGE_SAMI)). % From "intl.h": wxLayoutDirection -define(wxLayout_Default, 0). -define(wxLayout_LeftToRight, 1). diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index ebae32aeb8..465299a649 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -529,7 +529,6 @@ toolbar(Config) -> wxFrame:show(Frame), wx_test_lib:wx_destroy(Frame,Config). - popup(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); popup(Config) -> Wx = wx:new(), @@ -579,3 +578,32 @@ popup(Config) -> wxPopupTransientWindow:dismiss(Pop) end, wx_test_lib:wx_destroy(Frame,Config). + +locale(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo); +locale(_Config) -> + wx:new(), + io:format("SystemEncoding: ~p~n",[wxLocale:getSystemEncoding()]), + io:format("SystemEncodingName: ~ts~n",[wxLocale:getSystemEncodingName()]), + io:format("SystemLanguage: ~p~n",[wxLocale:getSystemLanguage()]), + io:format("SystemLanguageName: ~p~n",[wxLocale:getLanguageName(wxLocale:getSystemLanguage())]), + lang_env(), + LC = wxLocale:new(), + %% wxLocale:addCatalog(LC, "wxstd"), + io:format("Swedish: ~p~n",[wxLocale:getLanguageName(?wxLANGUAGE_SWEDISH)]), + R0 = wxLocale:init(LC, [{language, ?wxLANGUAGE_SWEDISH}, {flags, 0}]), + io:format("initiated ~p~n",[R0]), + lang_env(), + ok. +%% wx_test_lib:wx_destroy(Frame,Config). + +lang_env() -> + Env0 = os:getenv(), + Env = [[R,"\n"]||R <- Env0], + %%io:format("~p~n",[lists:sort(Env)]), + Opts = [global, multiline, {capture, all, list}], + format_env(re:run(Env, "LC_ALL.*", Opts)), + format_env(re:run(Env, "^LANG.*=.*$", Opts)), + ok. +format_env({match, List}) -> + [io:format(" ~ts~n",[L]) || L <- List]; +format_env(nomatch) -> ok. -- cgit v1.2.3 From 941ddfbeab3357177ce6eac709456fd881ac2429 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 15 Jun 2015 22:09:53 +0200 Subject: ssh: Initial ssh_tprt_test_lib.erl and ssh_protocol_SUITE This test lib is intended for deeper testing of the SSH application. It makes it possible to do exact steps in the message exchange to test "corner cases" --- lib/ssh/test/Makefile | 2 + lib/ssh/test/ssh_protocol_SUITE.erl | 314 ++++++++++ lib/ssh/test/ssh_protocol_SUITE_data/id_dsa | 13 + lib/ssh/test/ssh_protocol_SUITE_data/id_rsa | 15 + .../test/ssh_protocol_SUITE_data/ssh_host_dsa_key | 13 + .../ssh_protocol_SUITE_data/ssh_host_dsa_key.pub | 11 + .../test/ssh_protocol_SUITE_data/ssh_host_rsa_key | 16 + .../ssh_protocol_SUITE_data/ssh_host_rsa_key.pub | 5 + lib/ssh/test/ssh_trpt_test_lib.erl | 691 +++++++++++++++++++++ 9 files changed, 1080 insertions(+) create mode 100644 lib/ssh/test/ssh_protocol_SUITE.erl create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/id_dsa create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/id_rsa create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key.pub create mode 100644 lib/ssh/test/ssh_trpt_test_lib.erl (limited to 'lib') diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 6503d5b643..47c189c162 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -33,8 +33,10 @@ VSN=$(GS_VSN) MODULES= \ ssh_test_lib \ + ssh_trpt_test_lib \ ssh_sup_SUITE \ ssh_basic_SUITE \ + ssh_protocol_SUITE \ ssh_to_openssh_SUITE \ ssh_sftp_SUITE \ ssh_sftpd_SUITE \ diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl new file mode 100644 index 0000000000..3fb2840a19 --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -0,0 +1,314 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssh_protocol_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("kernel/include/inet.hrl"). +-include_lib("ssh/src/ssh.hrl"). % ?UINT32, ?BYTE, #ssh{} ... +-include_lib("ssh/src/ssh_transport.hrl"). +-include_lib("ssh/src/ssh_auth.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-define(NEWLINE, <<"\r\n">>). +-define(REKEY_DATA_TMO, 65000). + +-define(v(Key, Config), proplists:get_value(Key, Config)). +-define(v(Key, Config, Default), proplists:get_value(Key, Config, Default)). + + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + [{group,tool_tests} + ]. + +groups() -> + [{tool_tests, [], [lib_works_as_client, + lib_works_as_server, + lib_match, + lib_no_match + ]} + ]. + + +init_per_suite(Config) -> + start_std_daemon( setup_dirs( start_apps(Config))). + +end_per_suite(Config) -> + stop_apps(Config). + + +init_per_testcase(_TestCase, Config) -> + check_std_daemon_works(Config, ?LINE). + +end_per_testcase(_TestCase, Config) -> + check_std_daemon_works(Config, ?LINE). + + +%%%-------------------------------------------------------------------- +%%% Test Cases -------------------------------------------------------- +%%%-------------------------------------------------------------------- + +%%%-------------------------------------------------------------------- +%%% Connect to an erlang server and check that the testlib acts as a client. +lib_works_as_client(Config) -> + %% Connect and negotiate keys + {ok,InitialState} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {connect, + server_host(Config),server_port(Config), + [{silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}]}, + receive_hello, + {send, hello}, + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, ssh_msg_kexdh_init}, + {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, + {send, #ssh_msg_newkeys{}}, + {match, #ssh_msg_newkeys{_='_'}, receive_msg} + ] + ), + + %% Do the authentcation + {User,Pwd} = server_user_password(Config), + {ok,EndState} = + ssh_trpt_test_lib:exec( + [{send, #ssh_msg_service_request{name = "ssh-userauth"}}, + {match, #ssh_msg_service_accept{name = "ssh-userauth"}, receive_msg}, + {send, #ssh_msg_userauth_request{user = User, + service = "ssh-connection", + method = "password", + data = <> + }}, + {match, #ssh_msg_userauth_success{_='_'}, receive_msg} + ], InitialState), + + %% Disconnect + {ok,_} = + ssh_trpt_test_lib:exec( + [{send, #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION, + description = "End of the fun", + language = "" + }}, + close_socket + ], EndState). + + +%%-------------------------------------------------------------------- +%%% Connect an erlang client and check that the testlib can act as a server. +lib_works_as_server(Config) -> + {User,_Pwd} = server_user_password(Config), + + %% Create a listening socket as server socket: + {ok,InitialState} = ssh_trpt_test_lib:exec(listen), + HostPort = ssh_trpt_test_lib:server_host_port(InitialState), + + %% Start a process handling one connection on the server side: + spawn_link( + fun() -> + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_messages]}, + {accept, [{system_dir, system_dir(Config)}, + {user_dir, user_dir(Config)}]}, + receive_hello, + {send, hello}, + + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + + {match, #ssh_msg_kexdh_init{_='_'}, receive_msg}, + {send, ssh_msg_kexdh_reply}, + + {send, #ssh_msg_newkeys{}}, + {match, #ssh_msg_newkeys{_='_'}, receive_msg}, + + {match, #ssh_msg_service_request{name="ssh-userauth"}, receive_msg}, + {send, #ssh_msg_service_accept{name="ssh-userauth"}}, + + {match, #ssh_msg_userauth_request{service="ssh-connection", + method="none", + user=User, + _='_'}, receive_msg}, + + {send, #ssh_msg_userauth_failure{authentications = "password", + partial_success = false}}, + + {match, #ssh_msg_userauth_request{service="ssh-connection", + method="password", + user=User, + _='_'}, receive_msg}, + {send, #ssh_msg_userauth_success{}}, + close_socket, + print_state + ], + InitialState) + end), + + %% and finally connect to it with a regular Erlang SSH client: + {ok,_} = std_connect(HostPort, Config). + +%%-------------------------------------------------------------------- +%%% Matching +lib_match(_Config) -> + {ok,_} = + ssh_trpt_test_lib:exec([{set_options, [print_ops]}, + {match, abc, abc}, + {match, '$a', {cde,fgh}}, + {match, {cde,fgh}, '$a'}, + {match, '_', {cde,fgh}}, + {match, [a,'$a',b], [a,{cde,fgh},b]}, + {match, [a,'$a'|'$b'], [a,{cde,fgh},b,c]}, + {match, '$b', [b,c]} + ]). + +%%-------------------------------------------------------------------- +%%% Not matching +lib_no_match(_Config) -> + case ssh_trpt_test_lib:exec([{set_options, [print_ops]}, + {match, '$x', b}, + {match, a, '$x'}]) + of + {ok,_} -> {fail,"Unexpected match"}; + {error, {_Op,{expected,a,b},_State}} -> ok + end. + +%%%================================================================ +%%%==== Internal functions ======================================== +%%%================================================================ + +%%%---- init_suite and end_suite --------------------------------------- +start_apps(Config) -> + catch crypto:stop(), + case catch crypto:start() of + ok -> + catch ssh:stop(), + ok = ssh:start(), + [{stop_apps, + fun() -> + ssh:stop(), + crypto:stop() + end} | Config]; + _Else -> + {skip, "Crypto could not be started!"} + end. + + +stop_apps(Config) -> + (?v(stop_apps, Config, fun()-> ok end))(), + ssh:stop(). + + +setup_dirs(Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_rsa(DataDir, PrivDir), + Config. + +system_dir(Config) -> filename:join(?config(priv_dir, Config), system). + +user_dir(Config) -> ?config(priv_dir, Config). + +%%%---------------------------------------------------------------- +start_std_daemon(Config) -> + start_std_daemon(Config, []). + +start_std_daemon(Config, ExtraOpts) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + UserPasswords = [{"user1","pwd1"}], + Options = [{system_dir, system_dir(Config)}, + {user_dir, user_dir(Config)}, + {user_passwords, UserPasswords}, + {failfun, fun ssh_test_lib:failfun/2} + | ExtraOpts], + Ref = {Server, Host, Port} = ssh_test_lib:daemon(Options), + ct:log("Std server ~p started at ~p:~p~nOptions=~p",[Server, Host, Port, Options]), + [{server,Ref}, {user_passwords, UserPasswords} | Config]. + + +stop_std_daemon(Config) -> + ssh:stop_daemon(server_pid(Config)), + ct:log("Std server ~p at ~p:~p stopped", [server_pid(Config), server_host(Config), server_port(Config)]), + lists:keydelete(server, 1, Config). + +check_std_daemon_works(Config, Line) -> + case std_connect(Config) of + {ok,C} -> + ct:log("Server ~p:~p ~p is ok at line ~p", + [server_host(Config), server_port(Config), + server_pid(Config), Line]), + ok = ssh:close(C), + Config; + Error = {error,_} -> + {fail, + lists:flatten( + io_lib:format("Standard server ~p:~p ~p is ill at line ~p: ~p", + [server_host(Config), server_port(Config), + server_pid(Config), Line, Error]) + ) + } + end. + +server_pid(Config) -> element(1,?v(server,Config)). +server_host(Config) -> element(2,?v(server,Config)). +server_port(Config) -> element(3,?v(server,Config)). + +server_user_password(Config) -> server_user_password(1, Config). + +server_user_password(N, Config) -> lists:nth(N, ?v(user_passwords,Config)). + + +std_connect(Config) -> + {User,Pwd} = server_user_password(Config), + std_connect(server_host(Config), server_port(Config), + Config, + [{user,User},{password,Pwd}]). + +std_connect({Host,Port}, Config) -> + {User,Pwd} = server_user_password(Config), + std_connect(Host, Port, Config, [{user,User},{password,Pwd}]). + +std_connect({Host,Port}, Config, Opts) -> + std_connect(Host, Port, Config, Opts). + +std_connect(Host, Port, Config, Opts) -> + ssh:connect(Host, Port, + [{silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false} | Opts], + 30000). + + +%%%---------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/id_dsa b/lib/ssh/test/ssh_protocol_SUITE_data/id_dsa new file mode 100644 index 0000000000..d306f8b26e --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/id_dsa @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ +APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod +/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP +kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW +JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD +OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt ++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e +uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX +Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE +ZU8w8Q+H7z0j+a+70x2iAw== +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/id_rsa b/lib/ssh/test/ssh_protocol_SUITE_data/id_rsa new file mode 100644 index 0000000000..9d7e0dd5fb --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/id_rsa @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU +DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl +zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB +AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V +TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3 +CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK +SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p +z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd +WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39 +sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3 +xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ +dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x +ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak= +-----END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..75d2025c71 --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/ssh_host_rsa_key.pub @@ -0,0 +1,5 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8 +semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW +RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl new file mode 100644 index 0000000000..8623020a31 --- /dev/null +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -0,0 +1,691 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2015. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% + +-module(ssh_trpt_test_lib). + +%%-compile(export_all). + +-export([exec/1, exec/2, + format_msg/1, + server_host_port/1 + ] + ). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("ssh/src/ssh.hrl"). % ?UINT32, ?BYTE, #ssh{} ... +-include_lib("ssh/src/ssh_transport.hrl"). +-include_lib("ssh/src/ssh_auth.hrl"). + +%%%---------------------------------------------------------------- +-record(s, { + socket, + listen_socket, + opts = [], + timeout = 5000, % ms + seen_hello = false, + enc = <<>>, + ssh = #ssh{}, % #ssh{} + own_kexinit, + peer_kexinit, + vars = dict:new(), + reply = [], % Some repy msgs are generated hidden in ssh_transport :[ + prints = [], + return_value + }). + +-define(role(S), ((S#s.ssh)#ssh.role) ). + + +server_host_port(S=#s{}) -> + {Host,Port} = ok(inet:sockname(S#s.listen_socket)), + {host(Host), Port}. + + +%%% Options: {print_messages, false} true|detail +%%% {print_seqnums,false} true +%%% {print_ops,false} true + +exec(L) -> exec(L, #s{}). + +exec(L, S) when is_list(L) -> lists:foldl(fun exec/2, S, L); + +exec(Op, S0=#s{}) -> + S1 = init_op_traces(Op, S0), + try seqnum_trace( + op(Op, S1)) + of + S = #s{} -> + print_traces(S), + {ok,S} + catch + {fail,Reason,Se} -> + report_trace('', Reason, Se), + {error,{Op,Reason,Se}}; + + throw:Term -> + report_trace(throw, Term, S1), + throw(Term); + + error:Error -> + report_trace(error, Error, S1), + error(Error); + + exit:Exit -> + report_trace(exit, Exit, S1), + exit(Exit) + end; +exec(Op, {ok,S=#s{}}) -> exec(Op, S); +exec(_, Error) -> Error. + + +%%%---- Server ops +op(listen, S) when ?role(S) == undefined -> op({listen,0}, S); + +op({listen,Port}, S) when ?role(S) == undefined -> + S#s{listen_socket = ok(gen_tcp:listen(Port, mangle_opts([]))), + ssh = (S#s.ssh)#ssh{role=server} + }; + +op({accept,Opts}, S) when ?role(S) == server -> + {ok,Socket} = gen_tcp:accept(S#s.listen_socket, S#s.timeout), + {Host,_Port} = ok(inet:sockname(Socket)), + S#s{socket = Socket, + ssh = init_ssh(server,Socket,[{host,host(Host)}|Opts]), + return_value = ok}; + +%%%---- Client ops +op({connect,Host,Port,Opts}, S) when ?role(S) == undefined -> + Socket = ok(gen_tcp:connect(host(Host), Port, mangle_opts([]))), + S#s{socket = Socket, + ssh = init_ssh(client, Socket, [{host,host(Host)}|Opts]), + return_value = ok}; + +%%%---- ops for both client and server +op(close_socket, S) -> + catch tcp_gen:close(S#s.socket), + catch tcp_gen:close(S#s.listen_socket), + S#s{socket = undefined, + listen_socket = undefined, + return_value = ok}; + +op({set_options,Opts}, S) -> + S#s{opts = Opts}; + +op({send,X}, S) -> + send(S, instantiate(X,S)); + +op(receive_hello, S0) when S0#s.seen_hello =/= true -> + case recv(S0) of + S1=#s{return_value={hello,_}} -> S1; + S1=#s{} -> op(receive_hello, receive_wait(S1)) + end; + +op(receive_msg, S) when S#s.seen_hello == true -> + try recv(S) + catch + {tcp,Exc} -> S#s{return_value=Exc} + end; + + +op({expect,timeout,E}, S0) -> + try op(E, S0) + of + S=#s{} -> fail({expected,timeout,S#s.return_value}, S) + catch + {receive_timeout,_} -> S0#s{return_value=timeout} + end; + +op({match,M,E}, S0) -> + {Val,S2} = op_val(E, S0), + case match(M, Val, S2) of + {true,S3} -> + opt(print_ops,S3, + fun(true) -> + case dict:fold( + fun(K,V,Acc) -> + case dict:find(K,S0#s.vars) of + error -> [{K,V}|Acc]; + _ -> Acc + end + end, [], S3#s.vars) + of + [] -> {"Matches! No new bindings.",[]}; + New -> + Width = lists:max([length(atom_to_list(K)) || {K,_} <- New]), + {lists:flatten( + ["Matches! New bindings:~n" | + [io_lib:format(" ~*s = ~p~n",[Width,K,V]) || {K,V}<-New]]), + []} + end + end); + false -> + fail({expected,M,Val}, + opt(print_ops,S2,fun(true) -> {"nomatch!!~n",[]} end) + ) + end; + +op({print,E}, S0) -> + {Val,S} = op_val(E, S0), + io:format("Result of ~p ~p =~n~s~n",[?role(S0),E,format_msg(Val)]), + S; + +op(print_state, S) -> + io:format("State(~p)=~n~s~n",[?role(S), format_msg(S)]), + S; + +op('$$', S) -> + %% For matching etc + S. + + +op_val(E, S0) -> + case catch op(E, S0) of + {'EXIT',{function_clause,[{ssh_trpt_test_lib,op,[E,S0],_}|_]}} -> + {instantiate(E,S0), S0}; + S=#s{} -> + {S#s.return_value, S} + end. + + +fail(Reason, S) -> + throw({fail, Reason, S}). + +%%%---------------------------------------------------------------- +%% No optimizations :) + +match('$$', V, S) -> + match(S#s.return_value, V, S); + +match('_', _, S) -> + {true, S}; + +match(P, V, S) when is_atom(P) -> + case atom_to_list(P) of + "$"++_ -> + %% Variable + case dict:find(P,S#s.vars) of + {ok,Val} -> match(Val, V, S); + error -> {true,S#s{vars = dict:store(P,V,S#s.vars)}} + end; + _ when P==V -> + {true,S}; + _ -> + false + end; + +match(P, V, S) when P==V -> + {true, S}; + +match(P, V, S) when is_tuple(P), + is_tuple(V) -> + match(tuple_to_list(P), tuple_to_list(V), S); + +match([Hp|Tp], [Hv|Tv], S0) -> + case match(Hp, Hv, S0) of + {true,S} -> match(Tp, Tv, S); + false -> false + end; + +match(_, _, _) -> + false. + + + +instantiate('$$', S) -> + S#s.return_value; % FIXME: What if $$ or $... in return_value? + +instantiate(A, S) when is_atom(A) -> + case atom_to_list(A) of + "$"++_ -> + %% Variable + case dict:find(A,S#s.vars) of + {ok,Val} -> Val; % FIXME: What if $$ or $... in Val? + error -> throw({unbound,A}) + end; + _ -> + A + end; + +instantiate(T, S) when is_tuple(T) -> + list_to_tuple( instantiate(tuple_to_list(T),S) ); + +instantiate([H|T], S) -> + [instantiate(H,S) | instantiate(T,S)]; + +instantiate(X, _S) -> + X. + +%%%================================================================ +%%% +init_ssh(Role, Socket, Options0) -> + Options = [{user_interaction,false} + | Options0], + ssh_connection_handler:init_ssh(Role, + {2,0}, + lists:concat(["SSH-2.0-ErlangTestLib ",Role]), + Options, Socket). + +mangle_opts(Options) -> + SysOpts = [{reuseaddr, true}, + {active, false}, + {mode, binary} + ], + SysOpts ++ lists:foldl(fun({K,_},Opts) -> + lists:keydelete(K,1,Opts) + end, Options, SysOpts). + +host({0,0,0,0}) -> "localhost"; +host(H) -> H. + +%%%---------------------------------------------------------------- +send(S=#s{ssh=C}, hello) -> + Hello = case ?role(S) of + client -> C#ssh.c_version; + server -> C#ssh.s_version + end ++ "\r\n", + send(S, list_to_binary(Hello)); + +send(S0, ssh_msg_kexinit) -> + {Msg, Bytes, C0} = ssh_transport:key_exchange_init_msg(S0#s.ssh), + S1 = opt(print_messages, S0, + fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), + S = case ?role(S1) of + server when is_record(S1#s.peer_kexinit, ssh_msg_kexinit) -> + {ok, C} = + ssh_transport:handle_kexinit_msg(S1#s.peer_kexinit, Msg, C0), + S1#s{peer_kexinit = used, + own_kexinit = used, + ssh = C}; + _ -> + S1#s{ssh = C0, + own_kexinit = Msg} + end, + send_bytes(Bytes, S#s{return_value = Msg}); + +send(S0, ssh_msg_kexdh_init) when ?role(S0) == client, + is_record(S0#s.peer_kexinit, ssh_msg_kexinit), + is_record(S0#s.own_kexinit, ssh_msg_kexinit) -> + {ok, NextKexMsgBin, C} = + ssh_transport:handle_kexinit_msg(S0#s.peer_kexinit, S0#s.own_kexinit, S0#s.ssh), + + S = opt(print_messages, S0, + fun(X) when X==true;X==detail -> + #ssh{keyex_key = {{_Private, Public}, {_G, _P}}} = C, + Msg = #ssh_msg_kexdh_init{e = Public}, + {"Send (reconstructed)~n~s~n",[format_msg(Msg)]} + end), + + send_bytes(NextKexMsgBin, S#s{ssh = C, + peer_kexinit = used, + own_kexinit = used}); + +send(S0, ssh_msg_kexdh_reply) -> + Bytes = proplists:get_value(ssh_msg_kexdh_reply, S0#s.reply), + S = opt(print_messages, S0, + fun(X) when X==true;X==detail -> + {{_Private, Public}, _} = (S0#s.ssh)#ssh.keyex_key, + Msg = #ssh_msg_kexdh_reply{public_host_key = 'Key', + f = Public, + h_sig = 'H_SIG' + }, + {"Send (reconstructed)~n~s~n",[format_msg(Msg)]} + end), + send_bytes(Bytes, S#s{return_value = Bytes}); + +send(S0, Line) when is_binary(Line) -> + S = opt(print_messages, S0, + fun(X) when X==true;X==detail -> {"Send line~n~p~n",[Line]} end), + send_bytes(Line, S#s{return_value = Line}); + +%%% Msg = #ssh_msg_*{} +send(S0, Msg) when is_tuple(Msg) -> + S = opt(print_messages, S0, + fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), + {Packet, C} = ssh_transport:ssh_packet(Msg, S#s.ssh), + send_bytes(Packet, S#s{ssh = C, %%inc_send_seq_num(C), + return_value = Msg}). + +send_bytes(B, S0) -> + S = opt(print_messages, S0, fun(detail) -> {"Send bytes~n~p~n",[B]} end), + ok(gen_tcp:send(S#s.socket, B)), + S. + +%%%---------------------------------------------------------------- +recv(S0 = #s{}) -> + S1 = receive_poll(S0), + case S1#s.seen_hello of + {more,Seen} -> + %% Has received parts of a line. Has not seen a complete hello. + try_find_crlf(Seen, S1); + false -> + %% Must see hello before binary messages + try_find_crlf(<<>>, S1); + true -> + %% Has seen hello, therefore no more crlf-messages are alowed. + S = receive_binary_msg(S1), + case M=S#s.return_value of + #ssh_msg_kexinit{} when ?role(S) == server, + S#s.own_kexinit =/= undefined -> + {ok, C} = + ssh_transport:handle_kexinit_msg(M, S#s.own_kexinit, S#s.ssh), + S#s{peer_kexinit = used, + own_kexinit = used, + ssh = C}; + #ssh_msg_kexinit{} -> + S#s{peer_kexinit = M}; + #ssh_msg_kexdh_init{} -> % Always the server + {ok, Reply, C} = ssh_transport:handle_kexdh_init(M, S#s.ssh), + S#s{ssh = C, + reply = [{ssh_msg_kexdh_reply,Reply} | S#s.reply] + }; + #ssh_msg_kexdh_reply{} -> + {ok, _NewKeys, C} = ssh_transport:handle_kexdh_reply(M, S#s.ssh), + S#s{ssh=C#ssh{send_sequence=S#s.ssh#ssh.send_sequence}}; % Back the number + #ssh_msg_newkeys{} -> + {ok, C} = ssh_transport:handle_new_keys(M, S#s.ssh), + S#s{ssh=C}; + _ -> + S + end + end. + +%%%================================================================ +try_find_crlf(Seen, S0) -> + case erlang:decode_packet(line,S0#s.enc,[]) of + {more,_} -> + Line = <>, + S0#s{seen_hello = {more,Line}, + enc = <<>>, % didn't find a complete line + % -> no more characters to test + return_value = {more,Line} + }; + {ok,Used,Rest} -> + Line = <>, + case handle_hello(Line, S0) of + false -> + S = opt(print_messages, S0, + fun(X) when X==true;X==detail -> {"Recv info~n~p~n",[Line]} end), + S#s{seen_hello = false, + enc = Rest, + return_value = {info,Line}}; + S1=#s{} -> + S = opt(print_messages, S1, + fun(X) when X==true;X==detail -> {"Recv hello~n~p~n",[Line]} end), + S#s{seen_hello = true, + enc = Rest, + return_value = {hello,Line}} + end + end. + + +handle_hello(Bin, S=#s{ssh=C}) -> + case {ssh_transport:handle_hello_version(binary_to_list(Bin)), + ?role(S)} + of + {{undefined,_}, _} -> false; + {{Vp,Vs}, client} -> S#s{ssh = C#ssh{s_vsn=Vp, s_version=Vs}}; + {{Vp,Vs}, server} -> S#s{ssh = C#ssh{c_vsn=Vp, c_version=Vs}} + end. + +receive_binary_msg(S0=#s{ssh=C0=#ssh{decrypt_block_size = BlockSize, + recv_mac_size = MacSize + } + }) -> + case size(S0#s.enc) >= max(8,BlockSize) of + false -> + %% Need more bytes to decode the packet_length field + Remaining = max(8,BlockSize) - size(S0#s.enc), + receive_binary_msg( receive_wait(Remaining, S0) ); + true -> + %% Has enough bytes to decode the packet_length field + {_, <>, _} = + ssh_transport:decrypt_blocks(S0#s.enc, BlockSize, C0), % FIXME: BlockSize should be at least 4 + + %% FIXME: Check that ((4+PacketLen) rem BlockSize) == 0 ? + + S1 = if + PacketLen > ?SSH_MAX_PACKET_SIZE -> + fail({too_large_message,PacketLen},S0); % FIXME: disconnect + + ((4+PacketLen) rem BlockSize) =/= 0 -> + fail(bad_packet_length_modulo, S0); % FIXME: disconnect + + size(S0#s.enc) >= (4 + PacketLen + MacSize) -> + %% has the whole packet + S0; + + true -> + %% need more bytes to get have the whole packet + Remaining = (4 + PacketLen + MacSize) - size(S0#s.enc), + receive_wait(Remaining, S0) + end, + + %% Decrypt all, including the packet_length part (re-use the initial #ssh{}) + {C1, SshPacket = <>, EncRest} = + ssh_transport:decrypt_blocks(S1#s.enc, PacketLen+4, C0), + + PayloadLen = PacketLen - 1 - PadLen, + <> = Tail, + + {C2, Payload} = ssh_transport:decompress(C1, CompressedPayload), + + <> = EncRest, + + case {ssh_transport:is_valid_mac(Mac, SshPacket, C2), + catch ssh_message:decode(Payload)} + of + {false, _} -> fail(bad_mac,S1); + {_, {'EXIT',_}} -> fail(decode_failed,S1); + + {true, Msg} -> + C3 = case Msg of + #ssh_msg_kexinit{} -> + ssh_transport:key_init(opposite_role(C2), C2, Payload); + _ -> + C2 + end, + S2 = opt(print_messages, S1, + fun(X) when X==true;X==detail -> {"Recv~n~s~n",[format_msg(Msg)]} end), + S3 = opt(print_messages, S2, + fun(detail) -> {"decrypted bytes ~p~n",[SshPacket]} end), + S3#s{ssh = inc_recv_seq_num(C3), + enc = Rest, + return_value = Msg + } + end + end. + + +receive_poll(S=#s{socket=Sock}) -> + inet:setopts(Sock, [{active,once}]), + receive + {tcp,Sock,Data} -> + receive_poll( S#s{enc = <<(S#s.enc)/binary,Data/binary>>} ); + {tcp_closed,Sock} -> + throw({tcp,tcp_closed}); + {tcp_error, Sock, Reason} -> + throw({tcp,{tcp_error,Reason}}) + after 0 -> + S + end. + +receive_wait(S=#s{socket=Sock, + timeout=Timeout}) -> + inet:setopts(Sock, [{active,once}]), + receive + {tcp,Sock,Data} -> + S#s{enc = <<(S#s.enc)/binary,Data/binary>>}; + {tcp_closed,Sock} -> + throw({tcp,tcp_closed}); + {tcp_error, Sock, Reason} -> + throw({tcp,{tcp_error,Reason}}) + after Timeout -> + fail(receive_timeout,S) + end. + +receive_wait(N, S=#s{socket=Sock, + timeout=Timeout, + enc=Enc0}) when N>0 -> + inet:setopts(Sock, [{active,once}]), + receive + {tcp,Sock,Data} -> + receive_wait(N-size(Data), S#s{enc = <>}); + {tcp_closed,Sock} -> + throw({tcp,tcp_closed}); + {tcp_error, Sock, Reason} -> + throw({tcp,{tcp_error,Reason}}) + after Timeout -> + fail(receive_timeout, S) + end; +receive_wait(_N, S) -> + S. + +%% random_padding_len(PaddingLen1, ChunkSize) -> +%% MaxAdditionalRandomPaddingLen = % max 255 bytes padding totaö +%% (255 - PaddingLen1) - ((255 - PaddingLen1) rem ChunkSize), +%% AddLen0 = crypto:rand_uniform(0,MaxAdditionalRandomPaddingLen), +%% AddLen0 - (AddLen0 rem ChunkSize). % preserve the blocking + +inc_recv_seq_num(C=#ssh{recv_sequence=N}) -> C#ssh{recv_sequence=(N+1) band 16#ffffffff}. +%%%inc_send_seq_num(C=#ssh{send_sequence=N}) -> C#ssh{send_sequence=(N+1) band 16#ffffffff}. + +opposite_role(#ssh{role=R}) -> opposite_role(R); +opposite_role(client) -> server; +opposite_role(server) -> client. + +ok(ok) -> ok; +ok({ok,R}) -> R; +ok({error,E}) -> erlang:error(E). + + +%%%================================================================ +%%% +%%% Formating of records +%%% + +format_msg(M) -> format_msg(M, 0). + +format_msg(M, I0) -> + case fields(M) of + undefined -> io_lib:format('~p',[M]); + Fields -> + [Name|Args] = tuple_to_list(M), + Head = io_lib:format('#~p{',[Name]), + I = lists:flatlength(Head)+I0, + NL = io_lib:format('~n~*c',[I,$ ]), + Sep = io_lib:format(',~n~*c',[I,$ ]), + Tail = [begin + S0 = io_lib:format('~p = ',[F]), + I1 = I + lists:flatlength(S0), + [S0,format_msg(A,I1)] + end + || {F,A} <- lists:zip(Fields,Args)], + [[Head|string:join(Tail,Sep)],NL,"}"] + end. + +fields(M) -> + case M of + #ssh_msg_debug{} -> record_info(fields, ssh_msg_debug); + #ssh_msg_disconnect{} -> record_info(fields, ssh_msg_disconnect); + #ssh_msg_ignore{} -> record_info(fields, ssh_msg_ignore); + #ssh_msg_kex_dh_gex_group{} -> record_info(fields, ssh_msg_kex_dh_gex_group); + #ssh_msg_kex_dh_gex_init{} -> record_info(fields, ssh_msg_kex_dh_gex_init); + #ssh_msg_kex_dh_gex_reply{} -> record_info(fields, ssh_msg_kex_dh_gex_reply); + #ssh_msg_kex_dh_gex_request{} -> record_info(fields, ssh_msg_kex_dh_gex_request); + #ssh_msg_kex_dh_gex_request_old{} -> record_info(fields, ssh_msg_kex_dh_gex_request_old); + #ssh_msg_kexdh_init{} -> record_info(fields, ssh_msg_kexdh_init); + #ssh_msg_kexdh_reply{} -> record_info(fields, ssh_msg_kexdh_reply); + #ssh_msg_kexinit{} -> record_info(fields, ssh_msg_kexinit); + #ssh_msg_newkeys{} -> record_info(fields, ssh_msg_newkeys); + #ssh_msg_service_accept{} -> record_info(fields, ssh_msg_service_accept); + #ssh_msg_service_request{} -> record_info(fields, ssh_msg_service_request); + #ssh_msg_unimplemented{} -> record_info(fields, ssh_msg_unimplemented); + #ssh_msg_userauth_request{} -> record_info(fields, ssh_msg_userauth_request); + #ssh_msg_userauth_failure{} -> record_info(fields, ssh_msg_userauth_failure); + #ssh_msg_userauth_success{} -> record_info(fields, ssh_msg_userauth_success); + #ssh_msg_userauth_banner{} -> record_info(fields, ssh_msg_userauth_banner); + #ssh_msg_userauth_passwd_changereq{} -> record_info(fields, ssh_msg_userauth_passwd_changereq); + #ssh_msg_userauth_pk_ok{} -> record_info(fields, ssh_msg_userauth_pk_ok); + #ssh_msg_userauth_info_request{} -> record_info(fields, ssh_msg_userauth_info_request); + #ssh_msg_userauth_info_response{} -> record_info(fields, ssh_msg_userauth_info_response); + #s{} -> record_info(fields, s); + #ssh{} -> record_info(fields, ssh); + #alg{} -> record_info(fields, alg); + _ -> undefined + end. + +%%%================================================================ +%%% +%%% Trace handling +%%% + +init_op_traces(Op, S0) -> + opt(print_ops, S0#s{prints=[]}, + fun(true) -> + case ?role(S0) of + undefined -> {"-- ~p~n",[Op]}; + Role -> {"-- ~p ~p~n",[Role,Op]} + end + end + ). + +report_trace(Class, Term, S) -> + print_traces( + opt(print_ops, S, + fun(true) -> {"~s ~p",[Class,Term]} end) + ). + +seqnum_trace(S) -> + opt(print_seqnums, S, + fun(true) when S#s.ssh#ssh.send_sequence =/= S#s.ssh#ssh.send_sequence, + S#s.ssh#ssh.recv_sequence =/= S#s.ssh#ssh.recv_sequence -> + {"~p seq num: send ~p->~p, recv ~p->~p~n", + [?role(S), + S#s.ssh#ssh.send_sequence, S#s.ssh#ssh.send_sequence, + S#s.ssh#ssh.recv_sequence, S#s.ssh#ssh.recv_sequence + ]}; + (true) when S#s.ssh#ssh.send_sequence =/= S#s.ssh#ssh.send_sequence -> + {"~p seq num: send ~p->~p~n", + [?role(S), + S#s.ssh#ssh.send_sequence, S#s.ssh#ssh.send_sequence]}; + (true) when S#s.ssh#ssh.recv_sequence =/= S#s.ssh#ssh.recv_sequence -> + {"~p seq num: recv ~p->~p~n", + [?role(S), + S#s.ssh#ssh.recv_sequence, S#s.ssh#ssh.recv_sequence]} + end). + +print_traces(S) when S#s.prints == [] -> S; +print_traces(S) -> + ct:log("~s", + [lists:foldl(fun({Fmt,Args}, Acc) -> + [io_lib:format(Fmt,Args) | Acc] + end, "", S#s.prints)] + ). + +opt(Flag, S, Fun) when is_function(Fun,1) -> + try Fun(proplists:get_value(Flag,S#s.opts)) + of P={Fmt,Args} when is_list(Fmt), is_list(Args) -> + save_prints(P, S) + catch _:_ -> + S + end. + +save_prints({Fmt,Args}, S) -> + S#s{prints = [{Fmt,Args}|S#s.prints]}. -- cgit v1.2.3 From a9bedfb5b9a469642c0e8bf315f41a2505444cd6 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 30 Jun 2015 15:40:16 +0200 Subject: ssh: testcases for no common algorithms in key exchange --- lib/ssh/src/ssh_transport.erl | 33 +++++++++---- lib/ssh/test/ssh_basic_SUITE.erl | 2 + lib/ssh/test/ssh_protocol_SUITE.erl | 93 ++++++++++++++++++++++++++++++++++++- lib/ssh/test/ssh_trpt_test_lib.erl | 4 +- 4 files changed, 120 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index f4e6a23a1e..2e7391e1f8 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -246,26 +246,41 @@ handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own, Ssh0#ssh{algorithms = Algoritms}); _ -> %% TODO: Correct code? - throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, description = "Selection of key exchange" " algorithm failed", - language = "en"}) + language = ""}) end; handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own, #ssh{role = server} = Ssh) -> {ok, Algoritms} = select_algorithm(server, CounterPart, Own), - {ok, Ssh#ssh{algorithms = Algoritms}}. + case verify_algorithm(Algoritms) of + true -> + {ok, Ssh#ssh{algorithms = Algoritms}}; + _ -> + throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Selection of key exchange" + " algorithm failed", + language = ""}) + end. %% TODO: diffie-hellman-group14-sha1 should also be supported. %% Maybe check more things ... -verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) -> - true; -verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) -> - true; -verify_algorithm(_) -> - false. + +verify_algorithm(#alg{kex = undefined}) -> false; +verify_algorithm(#alg{hkey = undefined}) -> false; +verify_algorithm(#alg{send_mac = undefined}) -> false; +verify_algorithm(#alg{recv_mac = undefined}) -> false; +verify_algorithm(#alg{encrypt = undefined}) -> false; +verify_algorithm(#alg{decrypt = undefined}) -> false; +verify_algorithm(#alg{compress = undefined}) -> false; +verify_algorithm(#alg{decompress = undefined}) -> false; + +verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) -> true; +verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) -> true; +verify_algorithm(_) -> false. key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) -> {G, P} = dh_group1(), diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 9ff3eb8d0b..bf9fe54c57 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -1838,6 +1838,8 @@ check_error("Invalid state") -> ok; check_error("Connection closed") -> ok; +check_error("Selection of key exchange algorithm failed") -> + ok; check_error(Error) -> ct:fail(Error). diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 3fb2840a19..58c8306c31 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -45,7 +45,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [{group,tool_tests} + [{group,tool_tests}, + {group,kex} ]. groups() -> @@ -53,7 +54,10 @@ groups() -> lib_works_as_server, lib_match, lib_no_match - ]} + ]}, + {kex, [], [no_common_alg_server_disconnects, + no_common_alg_client_disconnects + ]} ]. @@ -203,6 +207,91 @@ lib_no_match(_Config) -> {error, {_Op,{expected,a,b},_State}} -> ok end. +%%-------------------------------------------------------------------- +%%% Algo negotiation fail. This should result in a ssh_msg_disconnect +%%% being sent from the server. +no_common_alg_server_disconnects(Config) -> + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {connect, + server_host(Config),server_port(Config), + [{silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}, + {preferred_algorithms,[{public_key,['ssh-dss']}]} + ]}, + receive_hello, + {send, hello}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, ssh_msg_kexinit}, + {match, + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, + receive_msg} + ] + ). + +%%-------------------------------------------------------------------- +%%% Algo negotiation fail. This should result in a ssh_msg_disconnect +%%% being sent from the client. +no_common_alg_client_disconnects(Config) -> + %% Create a listening socket as server socket: + {ok,InitialState} = ssh_trpt_test_lib:exec(listen), + HostPort = ssh_trpt_test_lib:server_host_port(InitialState), + Parent = self(), + + %% Start a process handling one connection on the server side: + Pid = + spawn_link( + fun() -> + Parent ! + {result,self(), + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_messages]}, + {accept, [{system_dir, system_dir(Config)}, + {user_dir, user_dir(Config)}]}, + receive_hello, + {send, hello}, + + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, #ssh_msg_kexinit{ + cookie = 247381486335508958743193106082599558706, + kex_algorithms = ["diffie-hellman-group1-sha1"], + server_host_key_algorithms = ["some-unknown"], + encryption_algorithms_client_to_server = ["aes128-ctr"], + encryption_algorithms_server_to_client = ["aes128-ctr"], + mac_algorithms_client_to_server = ["hmac-sha2-256"], + mac_algorithms_server_to_client = ["hmac-sha2-256"], + compression_algorithms_client_to_server = ["none"], + compression_algorithms_server_to_client = ["none"], + languages_client_to_server = [], + languages_server_to_client = [], + first_kex_packet_follows = false, + reserved = 0 + }}, + + {match, + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, + receive_msg} + ], + InitialState) + } + end), + + %% and finally connect to it with a regular Erlang SSH client: + Result = std_connect(HostPort, Config, [{preferred_algorithms,[{public_key,['ssh-dss']}]}]), + ct:log("Result of connect is ~p",[Result]), + + receive + {result,Pid,{ok,_}} -> + ok; + {result,Pid,{error,{Op,ExecResult,S}}} -> + ct:pal("ERROR!~nOp = ~p~nExecResult = ~p~nState =~n~s", + [Op,ExecResult,ssh_trpt_test_lib:format_msg(S)]), + {fail, ExecResult}; + X -> ct:fail(X) + end. + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 8623020a31..a604fca1ac 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -200,7 +200,9 @@ op_val(E, S0) -> {'EXIT',{function_clause,[{ssh_trpt_test_lib,op,[E,S0],_}|_]}} -> {instantiate(E,S0), S0}; S=#s{} -> - {S#s.return_value, S} + {S#s.return_value, S}; + F={fail,receive_timeout,_St} -> + throw(F) end. -- cgit v1.2.3 From 81b2c2d32e82eb53a8ae05f6f0085e4d940a4692 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 25 Jun 2015 12:42:41 +0200 Subject: ssl: Tune timeouts --- lib/ssl/test/ssl_ECC_SUITE.erl | 2 +- lib/ssl/test/ssl_basic_SUITE.erl | 23 ++++++++++++++++++++--- lib/ssl/test/ssl_payload_SUITE.erl | 11 ++++++++++- 3 files changed, 31 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 6ea0466dde..85152fda22 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -143,7 +143,7 @@ init_per_testcase(TestCase, Config) -> ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]), end_per_testcase(TestCase, Config), ssl:start(), - ct:timetrap({seconds, 5}), + ct:timetrap({seconds, 15}), Config. end_per_testcase(_TestCase, Config) -> diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index ecedb89c23..378f42c2ee 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -265,12 +265,12 @@ init_per_testcase(protocol_versions, Config) -> Config; init_per_testcase(reuse_session_expired, Config) -> - ct:timetrap({seconds, 30}), ssl:stop(), application:load(ssl), application:set_env(ssl, session_lifetime, ?EXPIRE), application:set_env(ssl, session_delay_cleanup_time, 500), ssl:start(), + ct:timetrap({seconds, 30}), Config; init_per_testcase(empty_protocol_versions, Config) -> @@ -303,7 +303,24 @@ init_per_testcase(TestCase, Config) when TestCase == client_renegotiate; ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), ct:timetrap({seconds, 30}), Config; -init_per_testcase(ssl_accept_timeout, Config) -> + +init_per_testcase(TestCase, Config) when TestCase == psk_cipher_suites; + TestCase == psk_with_hint_cipher_suites; + TestCase == ciphers_rsa_signed_certs; + TestCase == ciphers_rsa_signed_certs_openssl_names; + TestCase == versions_option, + TestCase == tcp_connect_big -> + ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), + + ct:timetrap({seconds, 30}), + Config; +init_per_testcase(rizzo, Config) -> + ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), + ct:timetrap({seconds, 40}), + Config; + +init_per_testcase(TestCase, Config) when TestCase == ssl_accept_timeout; + TestCase == client_closes_socket -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), ct:timetrap({seconds, 15}), Config; @@ -1428,6 +1445,7 @@ tcp_connect_big(Config) when is_list(Config) -> {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), TcpOpts = [binary, {reuseaddr, true}], + Rand = crypto:rand_bytes(?MAX_CIPHER_TEXT_LENGTH+1), Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0}, {from, self()}, {timeout, 5000}, @@ -1439,7 +1457,6 @@ tcp_connect_big(Config) when is_list(Config) -> {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]), ct:log("Testcase ~p connected to Server ~p ~n", [self(), Server]), - Rand = crypto:rand_bytes(?MAX_CIPHER_TEXT_LENGTH+1), gen_tcp:send(Socket, <>), diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl index b05f19d756..fb3890a811 100644 --- a/lib/ssl/test/ssl_payload_SUITE.erl +++ b/lib/ssl/test/ssl_payload_SUITE.erl @@ -105,7 +105,16 @@ init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge; TestCase == client_echos_passive_huge; TestCase == client_echos_active_once_huge; TestCase == client_echos_active_huge -> - ct:timetrap({seconds, 30}), + ct:timetrap({seconds, 90}), + Config; + +init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_big; + TestCase == server_echos_active_once_big; + TestCase == server_echos_active_big; + TestCase == client_echos_passive_big; + TestCase == client_echos_active_once_big; + TestCase == client_echos_active_big -> + ct:timetrap({seconds, 60}), Config; init_per_testcase(_TestCase, Config) -> -- cgit v1.2.3 From 37c12e0025c69bbcd19c4fa149a4c088c2181eed Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 26 Jun 2015 13:55:11 +0200 Subject: ssl: Exclude broken OpenSSL version from ECC test --- lib/ssl/test/ssl_test_lib.erl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index da744f7368..8317148aa5 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1076,6 +1076,9 @@ is_sane_ecc(openssl) -> "OpenSSL 1.0.0" ++ _ -> % Known bug in openssl %% manifests as SSL_CHECK_SERVERHELLO_TLSEXT:tls invalid ecpointformat list false; + "OpenSSL 1.0.1l" ++ _ -> + %% Breaks signature verification + false; "OpenSSL 0.9.8" ++ _ -> % Does not support ECC false; "OpenSSL 0.9.7" ++ _ -> % Does not support ECC -- cgit v1.2.3 From c95f0a64e5189ad1240fc547fcd774fe60f414a2 Mon Sep 17 00:00:00 2001 From: Stefan Strigler Date: Fri, 22 May 2015 11:11:36 +0200 Subject: introduce odbc port_timeout This introduces a new application environment variable 'port_timeout' that lets you set a custom timeout for ODBC when connecting to the port drivers upon initialization within odbc:connect/2. Default is still 5000 msec. --- lib/odbc/src/odbc.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl index 4901821e9c..12560bfb6e 100644 --- a/lib/odbc/src/odbc.erl +++ b/lib/odbc/src/odbc.erl @@ -26,6 +26,8 @@ -include("odbc_internal.hrl"). +-define(ODBC_PORT_TIMEOUT, 5000). + %% API -------------------------------------------------------------------- -export([start/0, start/1, stop/0, @@ -523,10 +525,10 @@ handle_msg({connect, ODBCCmd, AutoCommitMode, SrollableCursors}, NewState = State#state{auto_commit_mode = AutoCommitMode, scrollable_cursors = SrollableCursors}, - case gen_tcp:accept(ListenSocketSup, 5000) of + case gen_tcp:accept(ListenSocketSup, port_timeout()) of {ok, SupSocket} -> gen_tcp:close(ListenSocketSup), - case gen_tcp:accept(ListenSocketOdbc, 5000) of + case gen_tcp:accept(ListenSocketOdbc, port_timeout()) of {ok, OdbcSocket} -> gen_tcp:close(ListenSocketOdbc), odbc_send(OdbcSocket, ODBCCmd), @@ -983,3 +985,6 @@ string_terminate_value(Binary) when is_binary(Binary) -> <>; string_terminate_value(null) -> null. + +port_timeout() -> + application:get_env(?MODULE, port_timeout, ?ODBC_PORT_TIMEOUT). -- cgit v1.2.3 From 1aab177fecf6784769cf7f44e8e8d3f7ca908d44 Mon Sep 17 00:00:00 2001 From: Stefan Strigler Date: Thu, 2 Jul 2015 14:07:31 +0200 Subject: add doc for odbc port_timeout --- lib/odbc/doc/src/odbc.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib') diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml index 01bc0cb7ff..6a2a3587e4 100644 --- a/lib/odbc/doc/src/odbc.xml +++ b/lib/odbc/doc/src/odbc.xml @@ -221,6 +221,18 @@ and their meanings are dependent on the database being used. Reason is as per the Reason field when extended errors are not enabled. + + +

The current implementation spawns a port programm + written in C that utilizes the actual ODBC driver. There + is a default timeout of 5000 msec for this port programm + to connect to the Erlang ODBC application. This timeout + can be changed by setting an application specific + environment variable 'port_timeout' with the number of + milliseconds for the ODBC application. E.g.: [{odbc, + [{port_timeout, 60000}]}] to set it to 60 seconds. +

+
-- cgit v1.2.3 From 40a02d4e75e088b31df8e25973bd741ae0c39797 Mon Sep 17 00:00:00 2001 From: Stefan Strigler Date: Thu, 2 Jul 2015 14:07:45 +0200 Subject: add test for odbc port_timeout --- lib/odbc/test/odbc_connect_SUITE.erl | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'lib') diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl index 93e949faf6..2d4173a008 100644 --- a/lib/odbc/test/odbc_connect_SUITE.erl +++ b/lib/odbc/test/odbc_connect_SUITE.erl @@ -120,7 +120,16 @@ end_per_suite(_Config) -> %% Note: This function is free to add any key/value pairs to the Config %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- +init_per_testcase(connect_port_timeout, Config) -> + odbc:stop(), + application:load(odbc), + application:set_env(odbc, port_timeout, 0), + odbc:start(), + init_per_testcase_common(Config); init_per_testcase(_TestCase, Config) -> + init_per_testcase_common(Config). + +init_per_testcase_common(Config) -> test_server:format("ODBCINI = ~p~n", [os:getenv("ODBCINI")]), Dog = test_server:timetrap(?default_timeout), Temp = lists:keydelete(connection_ref, 1, Config), @@ -135,7 +144,16 @@ init_per_testcase(_TestCase, Config) -> %% A list of key/value pairs, holding the test case configuration. %% Description: Cleanup after each test case %%-------------------------------------------------------------------- + +end_per_testcase(connect_port_timeout, Config) -> + application:unset_env(odbc, port_timeout), + odbc:stop(), + odbc:start(), + end_per_testcase_common(Config); end_per_testcase(_TestCase, Config) -> + end_per_testcase_common(Config). + +end_per_testcase_common(Config) -> Table = ?config(tableName, Config), {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()), Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table), @@ -423,6 +441,18 @@ connect_timeout(Config) when is_list(Config) -> %% Need to return ok here "{'EXIT',timeout} return value" will %% be interpreted as that the testcase has timed out. ok. + +%%------------------------------------------------------------------------- +connect_port_timeout(doc) -> + ["Test the timeout for the port program to connect back to the odbc " + "application within the connect function."]; +connect_port_timeout(suite) -> []; +connect_port_timeout(Config) when is_list(Config) -> + %% Application environment var 'port_timeout' has been set to 0 by + %% init_per_testcase/2. + {error,timeout} = odbc:connect(?RDBMS:connection_string(), + odbc_test_lib:platform_options()). + %%------------------------------------------------------------------------- timeout(doc) -> ["Test that timeouts don't cause unwanted behavior sush as receiving" -- cgit v1.2.3 From 70cb9432dc03ac9435b2c8c5fe2e8fd0608015dc Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 2 Jul 2015 19:22:37 +0200 Subject: wx: Event callbacks could hang wx application temporary After applying a command make sure that it didn't recurse to a callback invocation, then we must re-start from the saved command queue. --- lib/wx/c_src/wxe_impl.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index e6ed236962..5b34f08704 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -60,6 +60,7 @@ wxeFifo * wxe_queue = NULL; wxeFifo * wxe_queue_cb_saved = NULL; unsigned int wxe_needs_signal = 0; // inside batch if larger than 0 +unsigned int wxe_cb_invoked = 0; /* ************************************************************ * Commands from erlang @@ -233,6 +234,7 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process) app->recurse_level--; // fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr); driver_demonitor_process(port, &monitor); + wxe_cb_invoked = 1; } } @@ -240,10 +242,16 @@ void WxeApp::dispatch_cmds() { if(wxe_status != WXE_INITIATED) return; - recurse_level++; - int level = dispatch(wxe_queue_cb_saved, 0, WXE_STORED); - dispatch(wxe_queue, level, WXE_NORMAL); - recurse_level--; + do { + wxe_cb_invoked = 0; + recurse_level++; + // fprintf(stderr, "\r\ndispatch_saved 0 \r\n");fflush(stderr); + int level = dispatch(wxe_queue_cb_saved, 0, WXE_STORED); + // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr); + dispatch(wxe_queue, level, WXE_NORMAL); + // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr); + recurse_level--; + } while(wxe_cb_invoked); // Cleanup old memenv's and deleted objects if(recurse_level == 0) { @@ -313,7 +321,12 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type) break; } event->Delete(); - if(list_type == WXE_NORMAL) erl_drv_mutex_lock(wxe_batch_locker_m); + if(list_type == WXE_NORMAL) { + if(wxe_cb_invoked) + return blevel; + else + erl_drv_mutex_lock(wxe_batch_locker_m); + } } if(list_type == WXE_STORED) return blevel; -- cgit v1.2.3 From 2c0fc495ffe04ab704a52192faa098b4c1b67121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 3 Jul 2015 14:10:00 +0200 Subject: mnesia: Update gitignore --- lib/.gitignore | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/.gitignore b/lib/.gitignore index 58c49adce0..b1da61706d 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -133,10 +133,12 @@ # mnesia +/mnesia/doc/src/Mnesia_App_A.xml /mnesia/doc/src/Mnesia_App_B.xml /mnesia/doc/src/Mnesia_App_C.xml /mnesia/doc/src/Mnesia_App_D.xml /mnesia/doc/src/Mnesia_chap2.xml +/mnesia/doc/src/Mnesia_chap3.xml /mnesia/doc/src/Mnesia_chap4.xml /mnesia/doc/src/Mnesia_chap5.xml /mnesia/doc/src/Mnesia_chap7.xml -- cgit v1.2.3 From e0694680a8b59641369a478b1aec58c2c2acc5d4 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Sat, 4 Jul 2015 10:49:33 +0200 Subject: ssh: add disjunction to ssh_trpt_test_lib:match --- lib/ssh/test/ssh_trpt_test_lib.erl | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index a604fca1ac..75f495b6d7 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -218,6 +218,13 @@ match('$$', V, S) -> match('_', _, S) -> {true, S}; +match({'or',[P]}, V, S) -> match(P,V,S); +match({'or',[Ph|Pt]}, V, S) -> + case match(Ph,V,S) of + false -> match({'or',Pt}, V, S); + {true,S} -> {true,S} + end; + match(P, V, S) when is_atom(P) -> case atom_to_list(P) of "$"++_ -> -- cgit v1.2.3 From 9931cad6d5f653a8be2bb324450c1d4b2c5637cf Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Sat, 4 Jul 2015 10:50:22 +0200 Subject: ssh: be more generous about disconnect expects --- lib/ssh/test/ssh_protocol_SUITE.erl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 58c8306c31..d82cdaf2c7 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -226,7 +226,8 @@ no_common_alg_server_disconnects(Config) -> {match, #ssh_msg_kexinit{_='_'}, receive_msg}, {send, ssh_msg_kexinit}, {match, - #ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, + {'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, + tcp_closed]}, receive_msg} ] ). @@ -269,10 +270,10 @@ no_common_alg_client_disconnects(Config) -> first_kex_packet_follows = false, reserved = 0 }}, - - {match, - #ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, - receive_msg} + {match, + {'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, + tcp_closed]}, + receive_msg} ], InitialState) } -- cgit v1.2.3 From 9c2d22a6ceff4aa49de6a4e14973ac7b8994261c Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 6 Jul 2015 20:26:05 +0200 Subject: Handle EINTR in trace_file_drv --- lib/runtime_tools/c_src/trace_file_drv.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c index 08bace80ef..f5980b4a57 100644 --- a/lib/runtime_tools/c_src/trace_file_drv.c +++ b/lib/runtime_tools/c_src/trace_file_drv.c @@ -326,9 +326,11 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff) | O_BINARY #endif , 0777)) < 0) { + int saved_errno = errno; if (wrap) driver_free(wrap); driver_free(data); + errno = saved_errno; return ERL_DRV_ERROR_ERRNO; } @@ -524,14 +526,19 @@ static void *my_alloc(size_t size) ** A write wrapper that regards it as an error if not all data was written. */ static int do_write(FILETYPE fd, unsigned char *buff, int siz) { - int w = write(fd, buff, siz); - if (w != siz) { - if (w >= 0) { - errno = ENOSPC; + int w; + while (1) { + w = write(fd, buff, siz); + if (w < 0 && errno == EINTR) + continue; + else if (w != siz) { + if (w >= 0) { + errno = ENOSPC; + } + return -1; } - return -1; + return siz; } - return siz; } /* @@ -626,8 +633,10 @@ static void close_unlink_port(TraceFileData *data) */ static int wrap_file(TraceFileData *data) { if (my_flush(data) < 0) { + int saved_errno = errno; close(data->fd); data->fd = -1; + errno = saved_errno; return -1; } close(data->fd); @@ -643,12 +652,15 @@ static int wrap_file(TraceFileData *data) { next_name(&data->wrap->del); } next_name(&data->wrap->cur); +try_open: data->fd = open(data->wrap->cur.name, O_WRONLY | O_TRUNC | O_CREAT #ifdef O_BINARY | O_BINARY #endif , 0777); if (data->fd < 0) { + if (errno == EINTR) + goto try_open; data->fd = -1; return -1; } -- cgit v1.2.3 From fb8d80f91ebfc328c3229a5908c3b4d527bfc1e6 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Mon, 6 Jul 2015 21:14:34 +0200 Subject: Prepare release --- lib/runtime_tools/doc/src/notes.xml | 17 +++++++++++++++++ lib/runtime_tools/vsn.mk | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index 1612c62c98..011c9a87a2 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -31,6 +31,23 @@

This document describes the changes made to the Runtime_Tools application.

+
Runtime_Tools 1.8.16.1 + +
Fixed Bugs and Malfunctions + + +

+ The trace_file_drv did not handle EINTR + correct which caused it to fail when the runtime system + received a signal.

+

+ Own Id: OTP-12890 Aux Id: seq12885

+
+
+
+ +
+
Runtime_Tools 1.8.16
Fixed Bugs and Malfunctions diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index e9f43df1aa..71eeba472c 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.8.16 +RUNTIME_TOOLS_VSN = 1.8.16.1 -- cgit v1.2.3 From fcbc24440945a13b379b2b6135599c982bf8bdf0 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 7 Jul 2015 10:38:38 +0200 Subject: wx: Add event callback fastpath Avoids spawn but can deadlock --- lib/wx/api_gen/wx_extra/wxEvtHandler.erl | 2 ++ lib/wx/src/gen/wxEvtHandler.erl | 2 ++ lib/wx/src/wxe_server.erl | 35 ++++++++++++++++++-------------- lib/wx/test/wx_event_SUITE.erl | 11 +++++++--- 4 files changed, 32 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl index c9726fd475..85ebc093f5 100644 --- a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl +++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl @@ -70,6 +70,8 @@ connect(This=#wx_ref{type=ThisT}, EventType, Options) -> parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) -> %% Check Fun Arity? parse_opts(R, Opts#evh{cb=Fun}); +parse_opts([{callback,CB={nospawn, Fun}}|R], Opts) when is_function(Fun) -> + parse_opts(R, Opts#evh{cb=CB}); parse_opts([callback|R], Opts) -> parse_opts(R, Opts#evh{cb=self()}); parse_opts([{userData, UserData}|R],Opts) -> diff --git a/lib/wx/src/gen/wxEvtHandler.erl b/lib/wx/src/gen/wxEvtHandler.erl index 6e9770bbb6..2d0a87f4dd 100644 --- a/lib/wx/src/gen/wxEvtHandler.erl +++ b/lib/wx/src/gen/wxEvtHandler.erl @@ -90,6 +90,8 @@ connect(This=#wx_ref{type=ThisT}, EventType, Options) -> parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) -> %% Check Fun Arity? parse_opts(R, Opts#evh{cb=Fun}); +parse_opts([{callback,CB={nospawn, Fun}}|R], Opts) when is_function(Fun) -> + parse_opts(R, Opts#evh{cb=CB}); parse_opts([callback|R], Opts) -> parse_opts(R, Opts#evh{cb=self()}); parse_opts([{userData, UserData}|R],Opts) -> diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl index 6679fcfbe1..cc253b1143 100644 --- a/lib/wx/src/wxe_server.erl +++ b/lib/wx/src/wxe_server.erl @@ -240,6 +240,8 @@ handle_connect(Object, EvData=#evh{handler=Handler}, invoke_cb({{Ev=#wx{}, Ref=#wx_ref{}}, FunId,_}, _S) -> %% Event callbacks case get(FunId) of + {{nospawn, Fun}, _} when is_function(Fun) -> + invoke_callback_fun(fun() -> Fun(Ev, Ref), <<>> end); {Fun,_} when is_function(Fun) -> invoke_callback(fun() -> Fun(Ev, Ref), <<>> end); {Pid,_} when is_pid(Pid) -> %% wx_object sync event @@ -258,21 +260,10 @@ invoke_cb({FunId, Args, _}, _S) when is_list(Args), is_integer(FunId) -> invoke_callback(Fun) -> Env = get(?WXE_IDENTIFIER), - CB = fun() -> - wx:set_env(Env), - wxe_util:cast(?WXE_CB_START, <<>>), - Res = try - Return = Fun(), - true = is_binary(Return), - Return - catch _:Reason -> - ?log("Callback fun crashed with {'EXIT, ~p, ~p}~n", - [Reason, erlang:get_stacktrace()]), - <<>> - end, - wxe_util:cast(?WXE_CB_RETURN, Res) - end, - spawn(CB), + spawn(fun() -> + wx:set_env(Env), + invoke_callback_fun(Fun) + end), ok. invoke_callback(Pid, Ev, Ref) -> @@ -302,6 +293,20 @@ invoke_callback(Pid, Ev, Ref) -> spawn(CB), ok. +invoke_callback_fun(Fun) -> + wxe_util:cast(?WXE_CB_START, <<>>), + Res = try + Return = Fun(), + true = is_binary(Return), + Return + catch _:Reason -> + ?log("Callback fun crashed with {'EXIT, ~p, ~p}~n", + [Reason, erlang:get_stacktrace()]), + <<>> + end, + wxe_util:cast(?WXE_CB_RETURN, Res). + + get_wx_object_state(Pid) -> case process_info(Pid, dictionary) of {dictionary, Dict} -> diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl index 2d6f7b6aaa..7e71d6ca69 100644 --- a/lib/wx/test/wx_event_SUITE.erl +++ b/lib/wx/test/wx_event_SUITE.erl @@ -78,7 +78,6 @@ connect(Config) -> Tester ! {got_size, UserD} end, - ?m(ok, wxFrame:connect(Frame, size)), ?m(ok, wxEvtHandler:connect(Panel, size,[{skip, true},{userData, panel}])), ?m(ok, wxEvtHandler:connect(Panel, size,[{callback,CB},{userData, panel}])), @@ -91,12 +90,16 @@ connect(Config) -> ?m(ok, wxWindow:connect(Window, size,[{callback,CB},{userData, window}])), ?m(ok, wxWindow:connect(Window, size,[{skip,true},{userData, window}])), + %% For trivial side effect free callbacks, can deadlock easily otherwise + CB1 = fun(_,_) -> Tester ! {got_size, nospawn_cb} end, + ?m(ok, wxWindow:connect(Frame, size, [{callback,{nospawn, CB1}}])), + ?m(ok, wxFrame:connect(Frame, size, [{skip, true}])), ?m(true, wxFrame:show(Frame)), wxWindow:setSize(Panel, {200,100}), wxWindow:setSize(Window, {200,100}), - get_size_messages(Frame, [frame, panel_cb, window_cb, window]), + get_size_messages(Frame, [frame, panel_cb, window_cb, window, nospawn_cb]), wx_test_lib:wx_destroy(Frame, Config). @@ -115,7 +118,9 @@ get_size_messages(Frame, Msgs) -> ?m(false, lists:member(window, Msgs)), get_size_messages(Frame, lists:delete(window_cb, Msgs)); {got_size,panel} -> - get_size_messages(Frame, lists:delete(panel_cb, Msgs)); + get_size_messages(Frame, lists:delete(panel_cb, Msgs)); + {got_size,nospawn_cb} -> + get_size_messages(Frame, lists:delete(nospawn_cb, Msgs)); Other -> ?error("Got unexpected msg ~p ~p~n", [Other,Msgs]) after 1000 -> -- cgit v1.2.3 From b602ed02a44e2cb6eec2d8e79f723cf607138934 Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Tue, 7 Jul 2015 11:02:15 +0200 Subject: Export shell:catch_exception/1 as documented --- lib/stdlib/src/shell.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index c64123a207..f215a66812 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -23,7 +23,7 @@ -export([whereis_evaluator/0, whereis_evaluator/1]). -export([start_restricted/1, stop_restricted/0]). -export([local_allowed/3, non_local_allowed/3]). --export([prompt_func/1, strings/1]). +-export([catch_exception/1, prompt_func/1, strings/1]). -define(LINEMAX, 30). -define(CHAR_MAX, 60). -- cgit v1.2.3 From 5d6aea209c3dafa1bfdb35ea559809185b060bfa Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 8 Jul 2015 20:31:29 +0200 Subject: Prepare release --- lib/runtime_tools/doc/src/notes.xml | 17 +++++++++++++++++ lib/runtime_tools/vsn.mk | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index 71b244ec6b..5aebea98ce 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -32,6 +32,23 @@

This document describes the changes made to the Runtime_Tools application.

+
Runtime_Tools 1.9.1 + +
Fixed Bugs and Malfunctions + + +

+ The trace_file_drv did not handle EINTR + correct which caused it to fail when the runtime system + received a signal.

+

+ Own Id: OTP-12890 Aux Id: seq12885

+
+
+
+ +
+
Runtime_Tools 1.9
Improvements and New Features diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index 3aadc46ab6..83e3612561 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.9 +RUNTIME_TOOLS_VSN = 1.9.1 -- cgit v1.2.3 From bb66bb749248fdef7634b5753000b62a0c3ad1a6 Mon Sep 17 00:00:00 2001 From: Constantin Rack Date: Tue, 19 May 2015 17:14:59 +0200 Subject: Fix small typo --- lib/tools/doc/src/make.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tools/doc/src/make.xml b/lib/tools/doc/src/make.xml index e63163d689..5c2e5e5d62 100644 --- a/lib/tools/doc/src/make.xml +++ b/lib/tools/doc/src/make.xml @@ -76,7 +76,7 @@ Load mode. Loads all recompiled modules. netload

- Net load mode. Loads all recompiled modules an all known nodes.
+ Net load mode. Loads all recompiled modules on all known nodes.

All items in Options that are not make options are assumed to be compiler options and are passed as-is to -- cgit v1.2.3 From c431a065ba515d27830f01c852f70940efb3003b Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 2 Jul 2015 11:13:32 +0200 Subject: ose: Remove all code related to the OSE port The OSE port is no longer supported and this commit removed it and any changes related to it. The things that were general improvements have been left in the code. --- lib/Makefile | 2 +- lib/asn1/c_src/Makefile | 7 - lib/crypto/Makefile | 4 - lib/crypto/c_src/Makefile.in | 7 - lib/crypto/c_src/crypto.c | 132 ----- lib/crypto/test/crypto_SUITE.erl | 6 +- lib/hipe/cerl/erl_bif_types.erl | 3 +- lib/kernel/doc/src/notes.xml | 3 +- lib/kernel/doc/src/ref_man.xml.src | 68 --- lib/kernel/src/inet_config.erl | 3 - lib/kernel/src/os.erl | 2 +- lib/kernel/test/erl_prim_loader_SUITE.erl | 71 ++- lib/kernel/test/file_SUITE.erl | 22 +- lib/kernel/test/gen_tcp_misc_SUITE.erl | 16 - lib/kernel/test/prim_file_SUITE.erl | 12 +- lib/ose/Makefile | 37 -- lib/ose/doc/html/.gitignore | 0 lib/ose/doc/man3/.gitignore | 0 lib/ose/doc/man6/.gitignore | 0 lib/ose/doc/pdf/.gitignore | 0 lib/ose/doc/src/.gitignore | 1 - lib/ose/doc/src/Makefile | 133 ------ lib/ose/doc/src/book.xml | 49 -- lib/ose/doc/src/notes.xml | 109 ----- lib/ose/doc/src/ose_app.xml | 38 -- lib/ose/doc/src/ose_erl_driver.xml | 111 ----- lib/ose/doc/src/ose_intro.xml | 154 ------ lib/ose/doc/src/ose_signals_chapter.xml | 240 ---------- lib/ose/doc/src/part.xml | 39 -- lib/ose/doc/src/ref_man.xml | 40 -- lib/ose/ebin/.gitignore | 0 lib/ose/include/.gitignore | 0 lib/ose/info | 2 - lib/ose/src/Makefile | 107 ----- lib/ose/src/ose.app.src | 28 -- lib/ose/src/ose.appup.src | 23 - lib/ose/src/ose.erl | 453 ------------------ lib/ose/test/Makefile | 67 --- lib/ose/test/ose.cover | 2 - lib/ose/test/ose.spec | 1 - lib/ose/test/ose_SUITE.erl | 766 ------------------------------ lib/ose/vsn.mk | 1 - lib/runtime_tools/c_src/Makefile.in | 7 - lib/stdlib/src/slave.erl | 23 +- lib/stdlib/test/filename_SUITE.erl | 35 +- lib/tools/c_src/Makefile.in | 8 - 46 files changed, 56 insertions(+), 2776 deletions(-) delete mode 100644 lib/kernel/doc/src/ref_man.xml.src delete mode 100644 lib/ose/Makefile delete mode 100644 lib/ose/doc/html/.gitignore delete mode 100644 lib/ose/doc/man3/.gitignore delete mode 100644 lib/ose/doc/man6/.gitignore delete mode 100644 lib/ose/doc/pdf/.gitignore delete mode 100644 lib/ose/doc/src/.gitignore delete mode 100644 lib/ose/doc/src/Makefile delete mode 100644 lib/ose/doc/src/book.xml delete mode 100644 lib/ose/doc/src/notes.xml delete mode 100644 lib/ose/doc/src/ose_app.xml delete mode 100644 lib/ose/doc/src/ose_erl_driver.xml delete mode 100644 lib/ose/doc/src/ose_intro.xml delete mode 100644 lib/ose/doc/src/ose_signals_chapter.xml delete mode 100644 lib/ose/doc/src/part.xml delete mode 100644 lib/ose/doc/src/ref_man.xml delete mode 100644 lib/ose/ebin/.gitignore delete mode 100644 lib/ose/include/.gitignore delete mode 100644 lib/ose/info delete mode 100644 lib/ose/src/Makefile delete mode 100644 lib/ose/src/ose.app.src delete mode 100644 lib/ose/src/ose.appup.src delete mode 100644 lib/ose/src/ose.erl delete mode 100644 lib/ose/test/Makefile delete mode 100644 lib/ose/test/ose.cover delete mode 100644 lib/ose/test/ose.spec delete mode 100644 lib/ose/test/ose_SUITE.erl delete mode 100644 lib/ose/vsn.mk (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index 34c2fe9a9e..64143a39e0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -36,7 +36,7 @@ ALL_ERLANG_APPLICATIONS = xmerl edoc erl_docgen snmp otp_mibs erl_interface \ public_key ssl observer odbc diameter \ cosTransactions cosEvent cosTime cosNotification \ cosProperty cosFileTransfer cosEventDomain et megaco webtool \ - eunit ssh typer percept eldap dialyzer hipe ose + eunit ssh typer percept eldap dialyzer hipe ifdef BUILD_ALL ERLANG_APPLICATIONS += $(ALL_ERLANG_APPLICATIONS) diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile index 2b72e1a214..e0d4f09a70 100644 --- a/lib/asn1/c_src/Makefile +++ b/lib/asn1/c_src/Makefile @@ -97,12 +97,7 @@ endif _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -ifneq ($(findstring ose,$(TARGET)),ose) opt: $(NIF_SHARED_OBJ_FILE) -else -# Do not build dynamic files on OSE -opt: -endif debug: opt @@ -140,9 +135,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" -ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib" -endif $(INSTALL_DIR) "$(RELSYSDIR)/c_src" $(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src" diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 24db75bf91..fbf108c410 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -24,11 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # -ifneq ($(findstring ose,$(TARGET)),ose) SUB_DIRECTORIES = src c_src doc/src -else -SUB_DIRECTORIES = src doc/src -endif static_lib: SUB_DIRECTORIES = c_src include vsn.mk diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index e66c0ca916..e7f750b60a 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -127,12 +127,7 @@ ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES) _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -ifneq ($(findstring ose,$(TARGET)),ose) debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB) -else -# Do not build dynamic files on OSE -debug opt valgrind: -endif static_lib: $(NIF_ARCHIVE) @@ -203,14 +198,12 @@ release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" $(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj" -ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib" ifeq ($(DYNAMIC_CRYPTO_LIB),yes) $(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib" endif -endif release_docs_spec: diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 9de8dc74c2..e9cac30c9c 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -507,47 +507,6 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*); #define PRINTF_ERR1(FMT,A1) #define PRINTF_ERR2(FMT,A1,A2) -#ifdef __OSE__ - -/* For crypto on OSE we have to initialize the crypto library on each - process that uses it. So since we do not know which scheduler is going - to execute the nif we have to check before each nif call that we have - initialized crypto in that process. */ - -#include "ose.h" -#include "openssl/osessl.h" - -static ErlNifTSDKey crypto_init_key; -static int check_ose_crypto(void); -static int init_ose_crypto(void); - -static int check_ose_crypto() { - int key = (int)enif_tsd_get(crypto_init_key); - if (!key) { - if (!CRYPTO_OSE5_init()) { - PRINTF_ERR0("CRYPTO: Call to CRYPTO_OSE5_init failed"); - return 0; - } - enif_tsd_set(crypto_init_key,1); - } - return 1; -} - -static int init_ose_crypto() { - /* Crypto nif upgrade does not work on OSE so no need to - destroy this key */ - enif_tsd_key_create("crypto_init_key", &crypto_init_key); - return check_ose_crypto(); -} - -#define INIT_OSE_CRYPTO() init_ose_crypto() -#define CHECK_OSE_CRYPTO() check_ose_crypto() -#else -#define INIT_OSE_CRYPTO() 1 -#define CHECK_OSE_CRYPTO() -#endif - - static int verify_lib_version(void) { const unsigned long libv = SSLeay(); @@ -609,9 +568,6 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) ErlNifBinary lib_bin; char lib_buf[1000]; - if (!INIT_OSE_CRYPTO()) - return 0; - if (!verify_lib_version()) return 0; @@ -853,7 +809,6 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -865,7 +820,6 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret)); return ret; } @@ -874,7 +828,6 @@ static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv MD5_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { @@ -891,7 +844,6 @@ static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; MD5_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) { return enif_make_badarg(env); } @@ -904,7 +856,6 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -916,7 +867,6 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret)); return ret; } @@ -925,7 +875,6 @@ static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TER RIPEMD160_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { @@ -942,7 +891,6 @@ static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary ctx_bin; RIPEMD160_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) { return enif_make_badarg(env); } @@ -956,7 +904,6 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -968,7 +915,6 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret)); return ret; } @@ -977,7 +923,6 @@ static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv SHA_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -993,7 +938,6 @@ static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; SHA_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) { return enif_make_badarg(env); } @@ -1007,7 +951,6 @@ static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA224 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1023,7 +966,6 @@ static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA224 ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); return ret; #else @@ -1036,7 +978,6 @@ static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA256_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1056,7 +997,6 @@ static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA256_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { return enif_make_badarg(env); } @@ -1073,7 +1013,6 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA256 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1089,7 +1028,6 @@ static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA256 ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); return ret; #else @@ -1102,7 +1040,6 @@ static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA256_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1122,7 +1059,6 @@ static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA256_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { return enif_make_badarg(env); } @@ -1139,7 +1075,6 @@ static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA384 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1155,7 +1090,6 @@ static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM {/* () */ #ifdef HAVE_SHA384 ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret)); return ret; #else @@ -1168,7 +1102,6 @@ static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA512_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1188,7 +1121,6 @@ static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA512_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { return enif_make_badarg(env); } @@ -1205,7 +1137,6 @@ static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv #ifdef HAVE_SHA512 ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1233,7 +1164,6 @@ static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE SHA512_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1253,7 +1183,6 @@ static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER ErlNifBinary ctx_bin; SHA512_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { return enif_make_badarg(env); } @@ -1270,7 +1199,6 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { return enif_make_badarg(env); } @@ -1282,7 +1210,6 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret)); return ret; } @@ -1291,7 +1218,6 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv MD4_CTX* new_ctx; ErlNifBinary ctx_bin, data_bin; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); @@ -1307,7 +1233,6 @@ static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary ctx_bin; MD4_CTX ctx_clone; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) { return enif_make_badarg(env); } @@ -1322,7 +1247,6 @@ static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) { @@ -1340,7 +1264,6 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) { @@ -1360,7 +1283,6 @@ static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) { @@ -1383,7 +1305,6 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) { @@ -1406,7 +1327,6 @@ static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) { @@ -1430,7 +1350,6 @@ static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ErlNifBinary key, data; unsigned mac_sz; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !enif_inspect_iolist_as_binary(env, argv[1], &data) || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) { @@ -1462,7 +1381,6 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ const EVP_MD *md; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (argv[0] == atom_sha) md = EVP_sha1(); #ifdef HAVE_SHA224 @@ -1502,7 +1420,6 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ErlNifBinary data; struct hmac_context* obj; - CHECK_OSE_CRYPTO(); if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj) || !enif_inspect_iolist_as_binary(env, argv[1], &data)) { @@ -1529,7 +1446,6 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv unsigned int req_len = 0; unsigned int mac_len; - CHECK_OSE_CRYPTO(); if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj) || (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) { @@ -1564,7 +1480,6 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 @@ -1587,7 +1502,6 @@ static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 @@ -1607,7 +1521,6 @@ static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ErlNifBinary key, text; DES_key_schedule schedule; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) { return enif_make_badarg(env); @@ -1627,7 +1540,6 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 @@ -1657,7 +1569,6 @@ static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_N DES_cblock ivec_clone; /* writable copy */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 @@ -1714,7 +1625,6 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE int new_ivlen = 0; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || !(key.size == 16 || key.size == 24 || key.size == 32) @@ -1744,7 +1654,6 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned int num = 0; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 @@ -1777,7 +1686,6 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N unsigned char * ivec2_buf; unsigned char * ecount2_buf; - CHECK_OSE_CRYPTO(); if (!enif_get_tuple(env, argv[0], &state_arity, &state_term) || state_arity != 4 @@ -1816,7 +1724,6 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *outp; ERL_NIF_TERM out, out_tag; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 @@ -1866,7 +1773,6 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *outp; ERL_NIF_TERM out; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 @@ -1937,7 +1843,6 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER unsigned char poly1305_key[32]; poly1305_state poly1305; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN @@ -1991,7 +1896,6 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER unsigned char mac[POLY1305_TAG_LEN]; poly1305_state poly1305; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN @@ -2045,7 +1949,6 @@ static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a unsigned char* ret_ptr; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) @@ -2074,7 +1977,6 @@ static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -2088,7 +1990,6 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -2106,7 +2007,6 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned char* data; unsigned top_mask, bot_mask; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bytes) || !enif_get_uint(env, argv[1], &top_mask) || !enif_get_uint(env, argv[2], &bot_mask)) { @@ -2130,7 +2030,6 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_get_uint(env, argv[0], &bits) || !enif_get_int(env, argv[1], &top) @@ -2200,7 +2099,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_mpint(env, argv[0], &bn_from) || !get_bn_from_mpint(env, argv[1], &bn_rand)) { @@ -2233,7 +2131,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg unsigned extra_byte; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_base) || !get_bn_from_bin(env, argv[1], &bn_exponent) @@ -2277,7 +2174,6 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM DSA *dsa; int i; - CHECK_OSE_CRYPTO(); if (argv[0] == atom_sha) { if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { @@ -2446,7 +2342,6 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM struct digest_type_t* digp = NULL; unsigned char* digest = NULL; - CHECK_OSE_CRYPTO(); digp = get_digest_type(type); if (!digp) { @@ -2508,7 +2403,6 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a unsigned char* ret_ptr; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) @@ -2569,7 +2463,6 @@ static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE unsigned char* ret_ptr; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 16 && key_bin.size != 32) @@ -2607,7 +2500,6 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) int i; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &d1) || !enif_inspect_iolist_as_binary(env,argv[1], &d2) @@ -2629,7 +2521,6 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg RC4_KEY rc4_key; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &key) || !enif_inspect_iolist_as_binary(env,argv[1], &data)) { @@ -2647,7 +2538,6 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ErlNifBinary key; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) { return enif_make_badarg(env); @@ -2664,7 +2554,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N RC4_KEY* rc4_key; ERL_NIF_TERM new_state, new_data; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env,argv[0], &state) || state.size != sizeof(RC4_KEY) @@ -2686,7 +2575,6 @@ static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ERL_NIF_TERM ret; unsigned char iv_copy[8]; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16) @@ -2748,7 +2636,6 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar struct digest_type_t *digp; unsigned char* digest; - CHECK_OSE_CRYPTO(); digp = get_digest_type(argv[0]); if (!digp) { @@ -2816,7 +2703,6 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar DSA* dsa; int i; - CHECK_OSE_CRYPTO(); if (argv[0] == atom_sha) { if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { @@ -2903,7 +2789,6 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER int padding, i; RSA* rsa; - CHECK_OSE_CRYPTO(); rsa = RSA_new(); @@ -2953,7 +2838,6 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE int padding, i; RSA* rsa; - CHECK_OSE_CRYPTO(); rsa = RSA_new(); @@ -3001,7 +2885,6 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E unsigned char *p_ptr, *g_ptr; ERL_NIF_TERM ret_p, ret_g; - CHECK_OSE_CRYPTO(); if (!enif_get_int(env, argv[0], &prime_len) || !enif_get_int(env, argv[1], &generator)) { @@ -3030,7 +2913,6 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] int i; ERL_NIF_TERM ret, head, tail; - CHECK_OSE_CRYPTO(); dh_params = DH_new(); @@ -3066,7 +2948,6 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail; int mpint; /* 0 or 4 */ - CHECK_OSE_CRYPTO(); dh_params = DH_new(); @@ -3112,7 +2993,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ErlNifBinary ret_bin; ERL_NIF_TERM ret, head, tail; - CHECK_OSE_CRYPTO(); dh_params = DH_new(); @@ -3154,7 +3034,6 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_multiplier) || !get_bn_from_bin(env, argv[1], &bn_verifier) @@ -3216,7 +3095,6 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_a) || !get_bn_from_bin(env, argv[1], &bn_u) @@ -3297,7 +3175,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!get_bn_from_bin(env, argv[0], &bn_verifier) || !get_bn_from_bin(env, argv[1], &bn_b) @@ -3359,7 +3236,6 @@ static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM int bf_n = 0; /* blowfish ivec pos */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -3384,7 +3260,6 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned char bf_tkey[8]; /* blowfish ivec */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -3409,7 +3284,6 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar BF_KEY bf_key; /* blowfish key 8 */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin) @@ -3431,7 +3305,6 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N int bf_n = 0; /* blowfish ivec pos */ ERL_NIF_TERM ret; - CHECK_OSE_CRYPTO(); if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) || !enif_inspect_binary(env, argv[1], &ivec_bin) @@ -3756,7 +3629,6 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM priv_key; ERL_NIF_TERM pub_key = atom_undefined; - CHECK_OSE_CRYPTO(); if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key)) goto badarg; @@ -3799,7 +3671,6 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM struct digest_type_t *digp; unsigned char* digest; - CHECK_OSE_CRYPTO(); digp = get_digest_type(argv[0]); if (!digp) { @@ -3868,7 +3739,6 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER struct digest_type_t* digp = NULL; unsigned char* digest = NULL; - CHECK_OSE_CRYPTO(); digp = get_digest_type(type); if (!digp) { @@ -3933,7 +3803,6 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF EC_POINT *my_ecpoint; EC_KEY *other_ecdh = NULL; - CHECK_OSE_CRYPTO(); if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) return enif_make_badarg(env); @@ -3978,7 +3847,6 @@ out_err: static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary seed_bin; - CHECK_OSE_CRYPTO(); if (!enif_inspect_binary(env, argv[0], &seed_bin)) return enif_make_badarg(env); RAND_seed(seed_bin.data,seed_bin.size); diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index e84f5e1075..0b955c0965 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -118,10 +118,10 @@ init_per_suite(Config) -> _ -> Config catch error:low_entropy -> - %% Make sure we are on OSE, otherwise we want to crash - {ose,_} = os:type(), + %% We are testing on an OS with low entropy in its random + %% seed. So we have to seed it with a binary to get started. - %% This is NOT how you want to seed this, it is just here + %% This is NOT how you want to do seeding, it is just here %% to make the tests pass. Check your OS manual for how you %% really want to seed. {H,M,L} = erlang:now(), diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 41a6c731c9..0b033ca439 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -913,8 +913,7 @@ type(erlang, system_info, 1, Xs, Opaques) -> t_list(t_pid()); ['os_type'] -> t_tuple([t_sup([t_atom('unix'), - t_atom('win32'), - t_atom('ose')]), + t_atom('win32')]), t_atom()]); ['os_version'] -> t_sup(t_tuple([t_non_neg_fixnum(), diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index b8db22aba7..e759f214df 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -423,8 +423,7 @@ Erlang/OTP has been ported to the realtime operating system OSE. The port supports both smp and non-smp emulator. For details around the port and how to started - see the User's Guide in the ose application.

+ see the User's Guide in the ose application.

Note that not all parts of Erlang/OTP has been ported.

diff --git a/lib/kernel/doc/src/ref_man.xml.src b/lib/kernel/doc/src/ref_man.xml.src deleted file mode 100644 index 7eb48a5f1d..0000000000 --- a/lib/kernel/doc/src/ref_man.xml.src +++ /dev/null @@ -1,68 +0,0 @@ - - - - -

- - 19962013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Kernel Reference Manual - - - - -
- -

The Kernel application has all the code necessary to run - the Erlang runtime system itself: file servers and code servers - and so on.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl index 803fae846e..a0d5344f11 100644 --- a/lib/kernel/src/inet_config.erl +++ b/lib/kernel/src/inet_config.erl @@ -188,9 +188,6 @@ do_load_resolv({win32,Type}, longnames) -> win32_load_from_registry(Type), inet_db:set_lookup([native]); -do_load_resolv({ose,_}, _) -> - inet_db:set_lookup([file]); - do_load_resolv(_, _) -> inet_db:set_lookup([native]). diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 3330b38d84..ffb899e5ca 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -93,7 +93,7 @@ unsetenv(_) -> %%% End of BIFs -spec type() -> {Osfamily, Osname} when - Osfamily :: unix | win32 | ose, + Osfamily :: unix | win32, Osname :: atom(). type() -> diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index 0803cf428f..ffcde5e458 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -260,46 +260,41 @@ multiple_slaves(doc) -> ["Start nodes in parallell, all using the 'inet' loading method, ", "verify that the boot server manages"]; multiple_slaves(Config) when is_list(Config) -> - case os:type() of - {ose,_} -> - {comment, "OSE: multiple nodes not supported"}; - _ -> - ?line Name = erl_prim_test_multiple_slaves, - ?line Host = host(), - ?line Cookie = atom_to_list(erlang:get_cookie()), - ?line IpStr = ip_str(Host), - ?line LFlag = get_loader_flag(os:type()), - ?line Args = LFlag ++ " -hosts " ++ IpStr ++ - " -setcookie " ++ Cookie, - - NoOfNodes = 10, % no of slave nodes to be started - - NamesAndNodes = - lists:map(fun(N) -> - NameN = atom_to_list(Name) ++ - integer_to_list(N), - NodeN = NameN ++ "@" ++ Host, - {list_to_atom(NameN),list_to_atom(NodeN)} - end, lists:seq(1, NoOfNodes)), - - ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []), - - %% "queue up" the nodes to wait for the boot server to respond - %% (note: test_server supervises each node start by accept() - %% on a socket, the timeout value for the accept has to be quite - %% long for this test to work). - ?line test_server:sleep(test_server:seconds(5)), - %% start the code loading circus! - ?line {ok,BootPid} = erl_boot_server:start_link([Host]), - %% give the nodes a chance to boot up before attempting to stop them - ?line test_server:sleep(test_server:seconds(10)), + ?line Name = erl_prim_test_multiple_slaves, + ?line Host = host(), + ?line Cookie = atom_to_list(erlang:get_cookie()), + ?line IpStr = ip_str(Host), + ?line LFlag = get_loader_flag(os:type()), + ?line Args = LFlag ++ " -hosts " ++ IpStr ++ + " -setcookie " ++ Cookie, + + NoOfNodes = 10, % no of slave nodes to be started + + NamesAndNodes = + lists:map(fun(N) -> + NameN = atom_to_list(Name) ++ + integer_to_list(N), + NodeN = NameN ++ "@" ++ Host, + {list_to_atom(NameN),list_to_atom(NodeN)} + end, lists:seq(1, NoOfNodes)), + + ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []), + + %% "queue up" the nodes to wait for the boot server to respond + %% (note: test_server supervises each node start by accept() + %% on a socket, the timeout value for the accept has to be quite + %% long for this test to work). + ?line test_server:sleep(test_server:seconds(5)), + %% start the code loading circus! + ?line {ok,BootPid} = erl_boot_server:start_link([Host]), + %% give the nodes a chance to boot up before attempting to stop them + ?line test_server:sleep(test_server:seconds(10)), - ?line wait_and_shutdown(lists:reverse(Nodes), 30), + ?line wait_and_shutdown(lists:reverse(Nodes), 30), - ?line unlink(BootPid), - ?line exit(BootPid, kill), - ok - end. + ?line unlink(BootPid), + ?line exit(BootPid, kill), + ok. start_multiple_nodes([{Name,Node} | NNs], Args, Started) -> ?line {ok,Node} = start_node(Name, Args, [{wait, false}]), diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 8856be31c2..5263130574 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -167,12 +167,7 @@ init_per_suite(Config) when is_list(Config) -> ok -> [{sasl,started}] end, - ok = case os:type() of - {ose,_} -> - ok; - _ -> - application:start(os_mon) - end, + application:start(os_mon), case os:type() of {win32, _} -> @@ -198,12 +193,7 @@ end_per_suite(Config) when is_list(Config) -> ok end, - case os:type() of - {ose,_} -> - ok; - _ -> - application:stop(os_mon) - end, + application:stop(os_mon), case proplists:get_value(sasl, Config) of started -> application:stop(sasl); @@ -888,10 +878,7 @@ open1(Config) when is_list(Config) -> ?line io:format(Fd1,Str,[]), ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), ?line Str = io:get_line(Fd1,''), - ?line case io:get_line(Fd2,'') of - Str -> Str; - eof -> Str - end, + ?line Str = io:get_line(Fd2,''), ?line ok = ?FILE_MODULE:close(Fd2), ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof), ?line ok = ?FILE_MODULE:truncate(Fd1), @@ -2346,9 +2333,6 @@ e_rename(Config) when is_list(Config) -> %% At least Windows NT can %% successfully move a file to %% another drive. - ok; - {ose, _} -> - %% disabled for now ok end, [] = flush(), diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 81c6dcd0fd..3adca83ec9 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -58,14 +58,6 @@ oct_acceptor/1, otp_7731_server/1, zombie_server/2, do_iter_max_socks/2]). -init_per_testcase(wrapping_oct, Config) when is_list(Config) -> - Dog = case os:type() of - {ose,_} -> - test_server:timetrap(test_server:minutes(20)); - _Else -> - test_server:timetrap(test_server:seconds(600)) - end, - [{watchdog, Dog}|Config]; init_per_testcase(iter_max_socks, Config) when is_list(Config) -> Dog = case os:type() of {win32,_} -> @@ -74,14 +66,6 @@ init_per_testcase(iter_max_socks, Config) when is_list(Config) -> test_server:timetrap(test_server:seconds(240)) end, [{watchdog, Dog}|Config]; -init_per_testcase(accept_system_limit, Config) when is_list(Config) -> - case os:type() of - {ose,_} -> - {skip,"Skip in OSE"}; - _ -> - Dog = test_server:timetrap(test_server:seconds(240)), - [{watchdog,Dog}|Config] - end; init_per_testcase(wrapping_oct, Config) when is_list(Config) -> Dog = test_server:timetrap(test_server:seconds(600)), [{watchdog, Dog}|Config]; diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 3e6d8492f7..366231d2cc 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -455,10 +455,7 @@ open1(Config) when is_list(Config) -> ?line ?PRIM_FILE:write(Fd1,Str), ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), ?line {ok, Str} = ?PRIM_FILE:read(Fd1,Length), - ?line case ?PRIM_FILE:read(Fd2,Length) of - {ok,Str} -> Str; - eof -> Str - end, + ?line {ok, Str} = ?PRIM_FILE:read(Fd2,Length), ?line ok = ?PRIM_FILE:close(Fd2), ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof), ?line ok = ?PRIM_FILE:truncate(Fd1), @@ -1629,7 +1626,7 @@ e_rename(Config) when is_list(Config) -> %% successfully move a file to %% another drive. ok; - {unix, _ } -> + _ -> OtherFs = "/tmp", ?line NameOnOtherFs = filename:join(OtherFs, @@ -1653,10 +1650,7 @@ e_rename(Config) when is_list(Config) -> Else -> Else end, - Com; - {ose, _} -> - %% disabled for now - ok + Com end, ?line test_server:timetrap_cancel(Dog), Comment. diff --git a/lib/ose/Makefile b/lib/ose/Makefile deleted file mode 100644 index 6119b75c3f..0000000000 --- a/lib/ose/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2009. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# -# Macros -# - -SUB_DIRECTORIES = src doc/src - -include vsn.mk -VSN = $(OSE_VSN) - -SPECIAL_TARGETS = - -# -# Default Subdir Targets -# -include $(ERL_TOP)/make/otp_subdir.mk diff --git a/lib/ose/doc/html/.gitignore b/lib/ose/doc/html/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/ose/doc/man3/.gitignore b/lib/ose/doc/man3/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/ose/doc/man6/.gitignore b/lib/ose/doc/man6/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/ose/doc/pdf/.gitignore b/lib/ose/doc/pdf/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/ose/doc/src/.gitignore b/lib/ose/doc/src/.gitignore deleted file mode 100644 index 860e9e703e..0000000000 --- a/lib/ose/doc/src/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ose.xml diff --git a/lib/ose/doc/src/Makefile b/lib/ose/doc/src/Makefile deleted file mode 100644 index 7ebd4125ba..0000000000 --- a/lib/ose/doc/src/Makefile +++ /dev/null @@ -1,133 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../../vsn.mk -VSN=$(OSE_VSN) -APPLICATION=ose - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) - -# ---------------------------------------------------- -# Help application directory specification -# ---------------------------------------------------- -EDOC_DIR = $(ERL_TOP)/lib/edoc -SYNTAX_TOOLS_DIR = $(ERL_TOP)/lib/syntax_tools - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- -XML_APPLICATION_FILES = ref_man.xml - -XML_REF3_FILES = \ - ose.xml \ - ose_erl_driver.xml - -XML_REF6_FILES = ose_app.xml - -XML_PART_FILES = part.xml -XML_CHAPTER_FILES = notes.xml ose_intro.xml ose_signals_chapter.xml - -BOOK_FILES = book.xml - -XML_FILES = \ - $(BOOK_FILES) $(XML_CHAPTER_FILES) \ - $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \ - $(XML_APPLICATION_FILES) - -# ---------------------------------------------------- - -HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) - -INFO_FILE = ../../info - -MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) -MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6) - -HTML_REF_MAN_FILE = $(HTMLDIR)/index.html - -TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf - -SPECS_FILES = - -TOP_SPECS_FILE = - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -XML_FLAGS += - -SPECS_FLAGS = -I../../include -I../../../kernel/include - -OSE_SRC_DIR = ../../src - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- -docs: man pdf html - -$(TOP_PDF_FILE): $(XML_FILES) - -pdf: $(TOP_PDF_FILE) - -html: $(HTML_REF_MAN_FILE) - -man: $(MAN3_FILES) $(MAN6_FILES) - -ose.xml: $(OSE_SRC_DIR)/ose.erl - escript $(DOCGEN)/priv/bin/xml_from_edoc.escript\ - $(OSE_SRC_DIR)/$(@:%.xml=%.erl) - -debug opt: - -clean clean_docs: - rm -rf $(HTMLDIR)/* - rm -f $(MAN3DIR)/* - rm -f $(MAN6DIR)/* - rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) - rm -f $(SPECDIR)/* - rm -f errs core *~ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_docs_spec: docs - $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(HTMLDIR)/* \ - "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" - $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6" - $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6" - -release_spec: diff --git a/lib/ose/doc/src/book.xml b/lib/ose/doc/src/book.xml deleted file mode 100644 index d62e0d32f4..0000000000 --- a/lib/ose/doc/src/book.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - -
- - 20142014 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - OSE - Lukas Larsson - - 2014-01-08 - 1.0 - book.xml -
- - - OSE - - - - - - - - - - - - - - -
diff --git a/lib/ose/doc/src/notes.xml b/lib/ose/doc/src/notes.xml deleted file mode 100644 index 06881b6c99..0000000000 --- a/lib/ose/doc/src/notes.xml +++ /dev/null @@ -1,109 +0,0 @@ - - - - -
- - 20142014 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - OSE Release Notes - - - - - notes.xml -
-

This document describes the changes made to the OSE application.

- -
Ose 1.1 - -
Improvements and New Features - - -

- Change license text from Erlang Public License to Apache - Public License v2

-

- Own Id: OTP-12845

-
-
-
- -
- -
Ose 1.0.2 - -
Fixed Bugs and Malfunctions - - -

- Add missing release notes for the OSE application.

-

- Own Id: OTP-12177

-
-
-
- -
- -
Ose 1.0.1 - -
Fixed Bugs and Malfunctions - - -

- Fix some spelling mistakes in documentation

-

- Own Id: OTP-12152

-
-
-
- -
- -
Ose 1.0 - -
Improvements and New Features - - -

- Erlang/OTP has been ported to the realtime operating - system OSE. The port supports both smp and non-smp - emulator. For details around the port and how to started - see the User's Guide in the ose application.

-

- Note that not all parts of Erlang/OTP has been ported.

-

- Notable things that work are: non-smp and smp emulators, - OSE signal interaction, crypto, asn1, run_erl/to_erl, - tcp, epmd, distribution and most if not all non-os - specific functionality of Erlang.

-

- Notable things that does not work are: udp/sctp, os_mon, - erl_interface, binding of schedulers.

-

- Own Id: OTP-11334

-
-
-
- -
- -
diff --git a/lib/ose/doc/src/ose_app.xml b/lib/ose/doc/src/ose_app.xml deleted file mode 100644 index d555f0ec4f..0000000000 --- a/lib/ose/doc/src/ose_app.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - -
- - 20142014 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Enea OSE - - - - -
- ose - The OSE Application - -

The OSE application contains modules and documentation that only - applies when running Erlang/OTP on Enea OSE.

-
- -
diff --git a/lib/ose/doc/src/ose_erl_driver.xml b/lib/ose/doc/src/ose_erl_driver.xml deleted file mode 100644 index b804c29d2d..0000000000 --- a/lib/ose/doc/src/ose_erl_driver.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - - -
- - 20132014 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - erl_driver for Enea OSE - Lukas Larsson - - 2014-01-08 - A - ose_erl_driver.xml -
- ose_erl_driver - Linked-in drivers in Enea OSE - -

Writing Linked-in drivers that also work on Enea OSE is very similar for - how you would do it for Unix. The difference from Unix is that - driver_select, ready_input and ready_output all work with signals - instead of file descriptors. This means that the driver_select is - used to specify which type of signal should trigger calls to - ready_input/ready_output. The functions described below are available - to driver programmers on Enea OSE to facilitate this. -

-
-
- DATA TYPES - - - union SIGNAL - See the Enea OSE SPI documentation for a description. - SIGSELECT - See the Enea OSE SPI documentation for a description. - ErlDrvEvent - The ErlDrvEvent is a handle to a signal number and id combination. It is passed to driver_select(3). - ErlDrvOseEventId - This is the id used to associate a specific signal to a - certain driver instance. - -
- - - union SIGNAL *erl_drv_ose_get_signal(ErlDrvEvent drv_event) - - -

Fetch the next signal associated with drv_event. - Signals will be returned in the order which they were received and - when no more signals are available NULL will be returned. - Use this function in the ready_input/ready_output callbacks - to get signals.

-
-
- - ErlDrvEventerl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, ErlDrvOseEventId (*resolve_signal)(union SIGNAL* sig), void *extra) - - -

Create a new ErlDrvEvent associated with signo, - id and uses the resolve_signal function to extract - the id from a signal with signo. The extra - parameter can be used for additional data. See - - Signals in a Linked-in driver in the OSE User's Guide. -

-
-
- - voiderl_drv_ose_event_free(ErlDrvEvent drv_event) - - -

Free a ErlDrvEvent. This should always be done in the - stop_select - callback when the event is no longer being used.

-
-
- - voiderl_drv_ose_event_fetch(ErlDrvEvent drv_event, SIGSELECT *signo, ErlDrvOseEventId *id, void **extra) - - -

Write the signal number, id and any extra data associated with drv_event - into *signo and *id respectively. NULL can be - also passed as signo or id in order to ignore that field. -

-
-
-
-
- SEE ALSO -

- driver_entry(3), - erl_driver(3) -

-
-
diff --git a/lib/ose/doc/src/ose_intro.xml b/lib/ose/doc/src/ose_intro.xml deleted file mode 100644 index 982516c8bd..0000000000 --- a/lib/ose/doc/src/ose_intro.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - - -
- - 20132014 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Introduction - Lukas Larsson - - 2014-01-08 - A - ose_intro.xml -
- -
- Features -
- -
- Starting Erlang/OTP -

- Starting Erlang/OTP on OSE is not as simple as on Unix/Windows (yet). - First of all you have to explicitly use the beam (or beam.smp) executables - found in erts-X.Y.Z/bin as the load module that you run. This in turn - means that you have to supply the raw beam arguments to the emulator - when starting. Fortunately erl on Unix/Windows has a - undocumented flag called -emu_args_exit that can be used to - figure out what the arguments to beam look like. For example:

- # erl +Mut false +A 10 +S 4:4 +Muycs256 +P 2096 +Q 2096 -emu_args_exit --Mut -false --A -10 --S -4:4 --Muycs256 --P -2096 --Q -2096 --- --root -/usr/local/lib/erlang --progname -erl --- --home -/home/erlang --- -

- The arguments are printed on separate lines to make it possible to know - what has to be quoted with ". Each line is one quotable unit. - So taking the arguments above you can supply them to pm_create or - just execute directly on the command line. For example:

- rtose@acp3400> pm_install erlang /mst/erlang/erts-6.0/bin/beam.smp -rtose@acp3400> pm_create -c ARGV="-Mut false -A 10 -S 4:4 -Muycs256 -P 2096 -Q 2099 -- -root /mst/erlang -progname erl -- -home /mst/erlang --" erlang -pid: 0x110059 -rtose@acp3400> pm_start 0x110059 -

- Also note that since we are running erl to figure out the arguments on a - separate machine the paths have to be updated. In the example above - /usr/local/lib/erlang was replaced by /mst/erlang/. The - goal is to in future releases not have to do the special argument handling - but for now (OTP 17.0) you have to do it. -

- - Because of a limitation in the way the OSE handles stdio when starting - load modules using pm_install/create the Erlang shell only reads every - other command from stdin. However if you start Erlang using run_erl - you do not have this problem. So it is highly recommended that you - start Erlang using run_erl. - -
- -
- run_erl and to_erl -

- In OSE run_erl and to_erl are combined into a single load module called - run_erl_lm. Installing and starting the load module will add two new - shell commands called run_erl and to_erl. They work in exactly the same - way as the unix variants of run_erl and to_erl, except that the read - and write pipes have to be placed under the /pipe vm. One additional - option also exists to run_erl on ose: - - -block Name - The name of the install handle and block that will be created/used by - installing and exectuting the first part of the command. If nothing - if given the basename of the load module will be used for this value. - Example: - pm_install erlang /path/to/erlang/vm/beam.smp -run_erl -daemon -block erlang /pipe/ /mst/erlang_logs/ "beam.smp -A 1 -- -root /mst/erlang -- -home /mst --" - - - The same argument munching as when starting Erlang/OTP without run_erl - has to be done. If -daemon is given then all error printouts - are sent to the ramlog. - See also - run_erl for more details. -

-

- Below is an example of how to get started with run_erl_lm. - rtose@acp3400> pm_install run_erl_lm /mst/erlang/erts-6.0/bin/run_erl_lm -rtose@acp3400> pm_create run_erl_lm -pid: 0x1c005d -rtose@acp3400> pm_start 0x1c005d -rtose@acp3400> mkdir /mst/erlang_log -rtose@acp3400> run_erl -daemon /pipe/ /mst/erlang_log/ "/mst/erlang/erts-6.0/bin/beam.smp -A 1 -- -root /mst/erlang -- -home /mst --" -rtose@acp3400> to_erl -Attaching to /pipe/erlang.pipe.1 (^C to exit) -os:type(). -{ose,release} -2> -'to_erl' terminated. - Note that Ctrl-C is used instead of Ctrl-D to exit the to_erl shell. -

-
- -
- epmd -

- In OSE epmd will not be started automatically so if you want to use - Erlang distribution you have to manually start epmd. -

-
- -
- VM Process Priorities -

- It is possible to set the priorities you want for the OSE processes that - thr emulator creates in the lmconf. An example of how to do it can be - found in the default lmconf file in - $ERL_TOP/erts/emulator/sys/ose/beam.lmconf. -

-
- -
diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml deleted file mode 100644 index bcf2259577..0000000000 --- a/lib/ose/doc/src/ose_signals_chapter.xml +++ /dev/null @@ -1,240 +0,0 @@ - - - - -
- - 20132014 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Interacting with Enea OSE - Lukas Larsson - - 2014-01-08 - A - ose_signals_chapter.xml -
- - -
- Introduction -

The main way which programs on Enea OSE interact is through the - usage of message passing, much the same way as Erlang processes - communicate. There are two ways in which an Erlang programmer can - interact with the signals sent from other Enea OSE processes; either - through the provided ose module, or by writing a custom linked-in - driver. This User's Guide describes and provides examples for both - approaches. -

-
- - -
- Signals in Erlang -

Erlang/OTP on OSE provides a erlang module called - ose that can be used to interact - with other OSE processes using message passing. The api in the module - is very similar to the native OSE api, so for details of how the - functions work please refer to the official OSE documenation. Below - is an example usage of the API. -

- 1> P1 = ose:open("p1"). -#Port>0.344> -2> ose:hunt(P1,"p2"). -{#Port>0.344>,1} -3> P2 = ose:open("p2"). -#Port>0.355> -4> flush(). -Shell got {mailbox_up,#Port>0.344>,{#Port>0.344>,1},852189} -ok -5> ose:listen(P1,[1234]). -ok -6> ose:send(P2,ose:get_id(P1),1234,>>"hello">>). -ok -7> flush(). -Shell got {message,#Port>0.344>,{852189,1245316,1234,>>"hello">>}} -ok -
- - -
- Signals in a Linked-in driver -

- Writing Linked-in drivers for OSE is very similar to how it is done - for Unix/Windows. It is only the way in which the driver subscribes - and consumed external events that is different. In Unix (and Windows) - file descriptiors (and Event Objects) are used to select on. On OSE - we use signals to deliver the same functionality. There are two large - differences between a signal and an fd. -

-

- In OSE it is not possible for a signal number to be a unique identifier - for a resource in the same way as an fd is. For example; let's say we - implement a driver that does an asynchronous hunt that uses signal - number 1234 as the hunt_sig. If we want to be able to have multiple - hunt ports running at the same time we have to have someway of routing - the signal to the correct port. This is achieved by supplying a secondary - id that can be retrieved through the meta-data or payload of the signal, - e.g: - ErlDrvEvent event = erl_drv_ose_event_alloc(1234,port,resolver); - The event you get back from - - erl_drv_ose_event_alloc can then be used by - driver_select - to subscribe to signals. The first argument is just the signal number - that we are interested in. The second is the id that we choose to use, - in this case the port id that we got in the - start callback is - used. The third argument is a function pointer to a function that can - be used to figure out the id from a given signal. The fourth argument can - point to any additional data you might want to associate with the event. - There is a complete. You can examine the data contained in the event with - erl_drv_ose_event_fetch - , eg: - erl_drv_ose_event_fetch(event, &signal, &port, (void **)&extra); - example of what this could look like in - the next section. - It is very important to issue the driver_select call before - any of the signals you are interested in are sent. If driver_select - is called after the signal is sent, there is a high probability that it - will be lost. -

-

- The other difference from unix is that in OSE the payload of the event - (i.e. the signal data) is already received when the ready_output/input - callbacks are called. This means that you access the data of a signal - by calling - erl_drv_ose_get_signal. Additionally multiple signals might be - associated with the event, so you should call - - erl_drv_ose_get_signal until NULL is returned. -

-
- - -
- Example Linked-in driver -#include "erl_driver.h" -#include "ose.h" - -struct huntsig { - SIGSELECT signo; - ErlDrvPort port; -}; - -union SIGNAL { - SIGSELECT signo; - struct huntsig; -} - -/* Here we have to get the id from the signal. In this case we use the - port id since we have control over the data structure of the signal. - It is however possible to use anything in here. The only restriction - is that the same id has to be used for all signals of the same number.*/ -ErlDrvOseEventId resolver(union SIGNAL *sig) { - return (ErlDrvOseEventId)sig->huntsig.port; -} - -static int drv_init(void) { return 0; }; - -static ErlDrvData drv_start(ErlDrvPort port, char *command) { - return (ErlDrvData)port; -} - -static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd, - char *buf, ErlDrvSizeT len, - char **rbuf, ErlDrvSizeT rlen) { - ErlDrvPort port = (ErlDrvPort)driver_data; - - /* An example of extra data to associate with the event */ - char *extra_data = driver_alloc(80); - snprintf("extra_data, "Event, sig_no: 1234, and port: %d", port); - - /* Create a new event to select on */ - ErlDrvOseEvent evt = erl_drv_ose_event_alloc(1234,port,resolver, extra_data); - - /* Make sure to do the select call _BEFORE_ the signal arrives. - The signal might get lost if the hunt call is done before the - select. */ - driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,1); - - union SIGNAL *sig = alloc(sizeof(union SIGNAL),1234); - sig->huntsig.port = port; - hunt("testprocess",0,NULL,&sig); - return 0; -} - -static void ready_input(ErlDrvData driver_data, ErlDrvEvent evt) { - char *extra_data; - /* Get the first signal payload from the event */ - union SIGNAL *sig = erl_drv_ose_get_signal(evt); - ErlDrvPort port = (ErlDrvPort)driver_data; - while (sig != NULL) { - if (sig->signo == 1234) { - /* Print out the string we added as the extra parameter */ - erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&extra_data); - printf("We've received: %s\n", extra_data); - - /* If it is our signal we send a message with the sender of the signal - to the controlling erlang process */ - ErlDrvTermData reply[] = { ERL_DRV_UINT, (ErlDrvUInt)sender(&sig) }; - erl_drv_send_term(port,reply,sizeof(reply) / sizeof(reply[0])); - } - - /* Cleanup the signal and deselect on the event. - Note that the event itself has to be free'd in the stop_select - callback. */ - free_buf(&sig); - driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,0); - - /* There could be more than one signal waiting in this event, so - we have to loop until sig == NULL */ - sig = erl_drv_ose_get_signal(evt); - } -} - -static void stop_select(ErlDrvEvent event, void *reserved) -{ - /* Free the extra_data */ - erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&extra_data); - driver_free(extra_data); - - /* Free the event itself */ - erl_drv_ose_event_free(event); -} - -/** - * Setup the driver entry for the Erlang runtime - **/ -ErlDrvEntry ose_signal_driver_entry = { - .init = drv_init, - .start = drv_start, - .stop = drv_stop, - .ready_input = ready_input, - .driver_name = DRIVER_NAME, - .control = control, - .extended_marker = ERL_DRV_EXTENDED_MARKER, - .major_version = ERL_DRV_EXTENDED_MAJOR_VERSION, - .minor_version = ERL_DRV_EXTENDED_MINOR_VERSION, - .driver_flags = ERL_DRV_FLAG_USE_PORT_LOCKING, - .stop_select = stop_select -}; - -
- -
diff --git a/lib/ose/doc/src/part.xml b/lib/ose/doc/src/part.xml deleted file mode 100644 index 0c9ebd16c0..0000000000 --- a/lib/ose/doc/src/part.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - -
- - 2014 - 2014 - Ericsson AB, All Rights Reserved - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - - - OSE User's Guide - Lukas Larsson - - 2014-01-08 - 1.0 - part.xml -
- -

OSE.

-
- - -
diff --git a/lib/ose/doc/src/ref_man.xml b/lib/ose/doc/src/ref_man.xml deleted file mode 100644 index 964e5ab8ff..0000000000 --- a/lib/ose/doc/src/ref_man.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - -
- - 20142014 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - OSE Reference Manual - Lukas Larsson - - 2014-01-08 - 1.0 - ref_man.xml -
- -

The Standard Erlang Libraries application, STDLIB, - contains modules for manipulating lists, strings and files etc.

-

-
- - - -
diff --git a/lib/ose/ebin/.gitignore b/lib/ose/ebin/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/ose/include/.gitignore b/lib/ose/include/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/ose/info b/lib/ose/info deleted file mode 100644 index 85c07dbe82..0000000000 --- a/lib/ose/info +++ /dev/null @@ -1,2 +0,0 @@ -group: misc Miscellaneous Applications -short: Description of Enea OSE specific functionality diff --git a/lib/ose/src/Makefile b/lib/ose/src/Makefile deleted file mode 100644 index a89e9392e9..0000000000 --- a/lib/ose/src/Makefile +++ /dev/null @@ -1,107 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2013. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../vsn.mk -VSN=$(OSE_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/ose-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- -MODULES= \ - ose - -HRL_FILES= - -INTERNAL_HRL_FILES= - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET) - -APP_FILE= ose.app - -APP_SRC= $(APP_FILE).src -APP_TARGET= $(EBIN)/$(APP_FILE) - -APPUP_FILE= ose.appup - -APPUP_SRC= $(APPUP_FILE).src -APPUP_TARGET= $(EBIN)/$(APPUP_FILE) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- - -ifeq ($(NATIVE_LIBS_ENABLED),yes) -ERL_COMPILE_FLAGS += +native -endif -ERL_COMPILE_FLAGS += -I../include -I../../kernel/include -Werror - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) - -clean: - rm -f $(TARGET_FILES) - rm -f core - rm -f erl_parse.erl - -docs: - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(APP_TARGET): $(APP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/src" - $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src" - $(INSTALL_DIR) "$(RELSYSDIR)/include" - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" - -release_docs_spec: - -# ---------------------------------------------------- -# Dependencies -- alphabetically, please -# ---------------------------------------------------- diff --git a/lib/ose/src/ose.app.src b/lib/ose/src/ose.app.src deleted file mode 100644 index 036779eb16..0000000000 --- a/lib/ose/src/ose.app.src +++ /dev/null @@ -1,28 +0,0 @@ -%% This is an -*- erlang -*- file. -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -{application, ose, - [{description, "Enea OSE specific modules"}, - {vsn, "%VSN%"}, - {modules, [ose]}, - {registered,[]}, - {applications, [stdlib,kernel]}, - {env, []}, - {runtime_dependencies, ["stdlib-2.0","erts-6.0"]}]}. diff --git a/lib/ose/src/ose.appup.src b/lib/ose/src/ose.appup.src deleted file mode 100644 index 28b6da3439..0000000000 --- a/lib/ose/src/ose.appup.src +++ /dev/null @@ -1,23 +0,0 @@ -%% -*- erlang -*- -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -{"%VSN%", - [ - ], - [ - ]}. diff --git a/lib/ose/src/ose.erl b/lib/ose/src/ose.erl deleted file mode 100644 index 5534dba4d4..0000000000 --- a/lib/ose/src/ose.erl +++ /dev/null @@ -1,453 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -%% @doc Interface module for OSE messaging and process monitoring from Erlang -%% -%% For each mailbox created through {@link open/1} a OSE phantom process with -%% that name is started. Since phantom processes are used the memory footprint -%% of each mailbox is quite small. -%% -%% To receive messages you first have to subscribe to the specific message -%% numbers that you are interested in with {@link listen/2}. The messages -%% will be sent to the Erlang process that created the mailbox. -%% -%% @end -%% --module(ose). - -%%============================================================================== -%% Exported API -%%============================================================================== --export([open/1, - close/1, - get_id/1, - get_name/2, - hunt/2, - dehunt/2, - attach/2, - detach/2, - send/4, - send/5, - listen/2 - ]). - -%%============================================================================== -%% Types -%%============================================================================== --opaque mailbox() :: port(). -%% Mailbox handle. Implemented as an erlang port. - --opaque mailbox_id() :: integer(). -%% Mailbox ID, this is the same as the process id of an OSE process. -%% An integer. - --type message_number() :: 0..4294967295. -%% OSE Signal number - --opaque hunt_ref() :: {mailbox(),integer()}. -%% Reference from a hunt request. This term will be included -%% in a successful hunt response. - --opaque attach_ref() :: {mailbox(),integer()}. -%% Reference from an attach request. This term will be included -%% in the term returned when the attached mailbox disappears. - --export_type([mailbox_id/0, - message_number/0, - mailbox/0, - hunt_ref/0, - attach_ref/0]). - -%%============================================================================== -%% Defines -%%============================================================================== --define(DRIVER_NAME, "ose_signal_drv"). --define(GET_SPID, 1). --define(GET_NAME, 2). --define(HUNT, 100). --define(DEHUNT, 101). --define(ATTACH, 102). --define(DETACH, 103). --define(SEND, 104). --define(SEND_W_S, 105). --define(LISTEN, 106). --define(OPEN, 200). - --define(INT_32BIT(Int),(is_integer(Int) andalso (Int >= 0) andalso (Int < (1 bsl 32)))). - -%%============================================================================== -%% API functions -%%============================================================================== - -%%------------------------------------------------------------------------------ -%% @doc Create a mailbox with the given name and return a port that handles -%% the mailbox. -%% -%% An OSE phantom process with the given name will be created that will send any -%% messages sent through this mailbox. Any messages sent to the new OSE process -%% will automatically be converted to an Erlang message and sent to the Erlang -%% process that calls this function. See {@link listen/2} for details about the -%% format of the message sent. -%% -%% The caller gets linked to the created mailbox. -%% -%% raises: `badarg' | `system_limit' -%% -%% @see listen/2 -%% @end -%%------------------------------------------------------------------------------ --spec open(Name) -> Port when - Name :: iodata(), - Port :: mailbox(). -open(Name) -> - try open_port({spawn_driver,?DRIVER_NAME}, [binary]) of - Port -> - try port_command(Port,[?OPEN,Name]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - close(Port), - erlang:error(Error,[Name]); - {ose_drv_reply,Port,ok} -> - Port - end - catch - error:badarg -> close(Port),erlang:error(badarg,[Name]) - end - catch - error:badarg -> erlang:error(badarg,[Name]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Close a mailbox -%% -%% This kills the OSE phantom process associated with this mailbox. -%% -%% Will also consume any ``{'EXIT',Port,_}'' message from the port that comes -%% due to the port closing when the calling process traps exits. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec close(Port) -> ok when - Port :: mailbox(). -close(Port) when is_port(Port) -> - %% Copied from prim_inet - case erlang:process_info(self(), trap_exit) of - {trap_exit,true} -> - link(Port), - catch erlang:port_close(Port), - receive {'EXIT',Port,_} -> ok end; - {trap_exit,false} -> - catch erlang:port_close(Port), - ok - end; -close(NotPort) -> - erlang:error(badarg,[NotPort]). - -%%------------------------------------------------------------------------------ -%% @doc Get the mailbox id for the given port. -%% -%% The mailbox id is the same as the OSE process id of the OSE phantom process -%% that this mailbox represents. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec get_id(Port) -> Pid when - Port :: mailbox(), - Pid :: mailbox_id(). -get_id(Port) -> - try port_control(Port, ?GET_SPID, <<>>) of - <> -> Spid - catch error:_Error -> - erlang:error(badarg,[Port]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Get the mailbox name for the given mailbox id. -%% -%% The mailbox name is the name of the OSE process with process id Pid. -%% -%% This call will fail with badarg if the underlying system does not support -%% getting the name from a process id. -%% -%% raises: `badarg' -%% @end -%%------------------------------------------------------------------------------ --spec get_name(Port, Pid) -> Name | undefined when - Port :: mailbox(), - Pid :: mailbox_id(), - Name :: binary(). -get_name(Port, Pid) when ?INT_32BIT(Pid) -> - try port_control(Port, ?GET_NAME, <>) of - [] -> undefined; - Res -> Res - catch error:_Error -> - erlang:error(badarg,[Port,Pid]) - end; -get_name(Port, Pid) -> - erlang:error(badarg,[Port,Pid]). - - -%%------------------------------------------------------------------------------ -%% @doc Hunt for OSE process by name. -%% -%% Will send `{mailbox_up, Port, Ref, MboxId}' -%% to the calling process when the OSE process becomes available. -%% -%% Returns a reference term that can be used to cancel the hunt -%% using {@link dehunt/2}. -%% -%% raises: `badarg' -%% -%% @end -%%------------------------------------------------------------------------------ --spec hunt(Port, HuntPath) -> Ref when - Port :: mailbox(), - HuntPath :: iodata(), - Ref :: hunt_ref(). -hunt(Port, HuntPath) -> - try port_command(Port, [?HUNT,HuntPath]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,HuntPath]); - {ose_drv_reply,Port,Ref} -> - Ref - end - catch error:_Error -> - erlang:error(badarg,[Port,HuntPath]) - end. - -%%------------------------------------------------------------------------------ -%% @doc Stop hunting for OSE process. -%% -%% If a message for this hunt has been sent but not received -%% by the calling process, it is removed from the message queue. -%% Note that this only works if the same process that did -%% the hunt does the dehunt. -%% -%% raises: `badarg' -%% -%% @see hunt/2 -%% @end -%%------------------------------------------------------------------------------ --spec dehunt(Port, Ref) -> ok when - Port :: mailbox(), - Ref :: hunt_ref(). -dehunt(Port, {Port,Ref}) when ?INT_32BIT(Ref) -> - try port_command(Port, <>) of - true -> - receive - {ose_drv_reply,Port,{error,enoent}} -> - %% enoent could mean that it is in the message queue - receive - {mailbox_up, Port, {Port,Ref}, _} -> - ok - after 0 -> - ok - end; - {ose_drv_reply,Port,ok} -> - ok - end - catch error:_Error -> - erlang:error(badarg,[Port,{Port,Ref}]) - end; -dehunt(Port,Ref) -> - erlang:error(badarg,[Port,Ref]). - -%%------------------------------------------------------------------------------ -%% @doc Attach to an OSE process. -%% -%% Will send `{mailbox_down, Port, Ref, MboxId}' -%% to the calling process if the OSE process exits. -%% -%% Returns a reference that can be used to cancel the attachment -%% using {@link detach/2}. -%% -%% raises: `badarg' | `enomem' -%% -%% @end -%%------------------------------------------------------------------------------ --spec attach(Port,Pid) -> Ref when - Port :: mailbox(), - Pid :: mailbox_id(), - Ref :: attach_ref(). -attach(Port, Spid) when ?INT_32BIT(Spid) -> - try port_command(Port, <>) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,Spid]); - {ose_drv_reply,Port,Ref} -> - Ref - end - catch error:_Error -> - erlang:error(badarg,[Port,Spid]) - end; -attach(Port,Spid) -> - erlang:error(badarg,[Port,Spid]). - - -%%------------------------------------------------------------------------------ -%% @doc Remove attachment to an OSE process. -%% -%% If a message for this monitor has been sent but not received -%% by the calling process, it is removed from the message queue. -%% Note that this only works of the same process -%% that did the attach does the detach. -%% -%% raises: `badarg' -%% -%% @see attach/2 -%% @end -%%------------------------------------------------------------------------------ --spec detach(Port,Ref) -> ok when - Port :: mailbox(), - Ref :: attach_ref(). -detach(Port, {Port,Ref} ) when ?INT_32BIT(Ref) -> - try port_command(Port, <>) of - true -> - receive - {ose_drv_reply,Port,{error,enoent}} -> - %% enoent could mean that it is in the message queue - receive - {mailbox_down,Port,{Port,Ref},_} -> - ok - after 0 -> - ok - end; - {ose_drv_reply,Port,ok} -> - ok - end - catch error:_Error -> - erlang:error(badarg,[Port,{Port,Ref}]) - end; -detach(Port,Ref) -> - erlang:error(badarg,[Port,Ref]). - -%%------------------------------------------------------------------------------ -%% @doc Send an OSE message. -%% -%% The message is sent from the OSE process' own ID that is: `get_id(Port)'. -%% -%% raises: `badarg' -%% -%% @see send/5 -%% @end -%%------------------------------------------------------------------------------ --spec send(Port,Pid,SigNo,SigData) -> ok when - Port :: mailbox(), - Pid :: mailbox_id(), - SigNo :: message_number(), - SigData :: iodata(). -send(Port, Spid, SigNo, SigData) when ?INT_32BIT(Spid), ?INT_32BIT(SigNo) -> - try erlang:port_command(Port, [<>, SigData]) of - true -> ok - catch error:_Error -> - erlang:error(badarg,[Port,Spid,SigNo,SigData]) - end; -send(Port,Spid,SigNo,SigData) -> - erlang:error(badarg,[Port,Spid,SigNo,SigData]). - - -%%------------------------------------------------------------------------------ -%% @doc Send an OSE message with different sender. -%% -%% As {@link send/4} but the sender will be `SenderPid'. -%% -%% raises: `badarg' -%% -%% @see send/4 -%% @end -%%------------------------------------------------------------------------------ --spec send(Port,Pid,SenderPid,SigNo,SigData) -> ok when - Port :: mailbox(), - Pid :: mailbox_id(), - SenderPid :: mailbox_id(), - SigNo :: message_number(), - SigData :: iodata(). -send(Port, Spid, SenderPid, SigNo, SigData) - when ?INT_32BIT(Spid), ?INT_32BIT(SenderPid), ?INT_32BIT(SigNo) -> - try erlang:port_command(Port, [<>, SigData]) of - true -> ok - catch error:_Error -> - erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]) - end; -send(Port,Spid,SenderPid,SigNo,SigData) -> - erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]). - -%%------------------------------------------------------------------------------ -%% @doc Start listening for specified OSE signal numbers. -%% -%% The mailbox will send `{message,Port,{FromMboxId,ToMboxId,MsgNo,MsgData}}' -%% to the process that created the mailbox when an OSE message with any -%% of the specified `SigNos' arrives. -%% -%% Repeated calls to listen will replace the current set of signal numbers to -%% listen to. i.e -%% -%% ```1>ose:listen(MsgB,[1234,12345]). -%% ok -%% 2> ose:listen(MsgB,[1234,123456]). -%% ok.''' -%% -%% The above will first listen for signals with numbers 1234 and 12345, and then -%% replace that with only listening to 1234 and 123456. -%% -%% With the current implementation it is not possible to listen to all signal -%% numbers. -%% -%% raises: `badarg' | `enomem' -%% -%% @end -%%------------------------------------------------------------------------------ --spec listen(Port, SigNos) -> ok when - Port :: mailbox(), - SigNos :: list(message_number()). -listen(Port, SigNos) when is_list(SigNos) -> - USSigNos = lists:usort(SigNos), - BinSigNos = try - << <> || - SigNo <- USSigNos, - ?INT_32BIT(SigNo) orelse erlang:error(badarg) - >> - catch _:_ -> - erlang:error(badarg,[Port,SigNos]) - end, - try port_command(Port, [?LISTEN, BinSigNos]) of - true -> - receive - {ose_drv_reply,Port,{error,Error}} -> - erlang:error(Error,[Port,SigNos]); - {ose_drv_reply,Port,Else} -> - Else - end - catch error:_Error -> - erlang:error(badarg,[Port,SigNos]) - end; -listen(Port, SigNos) -> - erlang:error(badarg,[Port,SigNos]). - - -%%%============================================================================= -%%% Internal functions -%%%============================================================================= diff --git a/lib/ose/test/Makefile b/lib/ose/test/Makefile deleted file mode 100644 index 7e2080ba38..0000000000 --- a/lib/ose/test/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - ose_SUITE - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) - -INSTALL_PROGS= $(TARGET_FILES) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/ose_test - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- - -ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \ - -I$(ERL_TOP)/lib/kernel/include - -EBIN = . - -EMAKEFILE=Emakefile -COVERFILE=ose.cover - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -make_emakefile: - $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ - > $(EMAKEFILE) - -tests debug opt: make_emakefile - erl $(ERL_MAKE_FLAGS) -make - -clean: - rm -f $(EMAKEFILE) - rm -f $(TARGET_FILES) - rm -f core - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - -release_tests_spec: make_emakefile - $(INSTALL_DIR) "$(RELSYSDIR)" - $(INSTALL_DATA) ose.spec $(EMAKEFILE) \ - $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)" - chmod -R u+w "$(RELSYSDIR)" - @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) - -release_docs_spec: diff --git a/lib/ose/test/ose.cover b/lib/ose/test/ose.cover deleted file mode 100644 index 7b846cfaf6..0000000000 --- a/lib/ose/test/ose.cover +++ /dev/null @@ -1,2 +0,0 @@ -%% -*- erlang -*- -{incl_app,ose,details}. diff --git a/lib/ose/test/ose.spec b/lib/ose/test/ose.spec deleted file mode 100644 index c897e8cd16..0000000000 --- a/lib/ose/test/ose.spec +++ /dev/null @@ -1 +0,0 @@ -{suites,"../ose_test",all}. diff --git a/lib/ose/test/ose_SUITE.erl b/lib/ose/test/ose_SUITE.erl deleted file mode 100644 index 31d950bd03..0000000000 --- a/lib/ose/test/ose_SUITE.erl +++ /dev/null @@ -1,766 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(ose_SUITE). - -%-compile(export_all). - --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2,init_per_testcase/2, - end_per_testcase/2]). --export([ - basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1, - hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1, - attach/1,multi_attach/1,detach/1,multi_detach/1, - open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1, - hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1, - send_errors/1,send_w_s_errors/1,listen_errors/1 - ]). - --define(INTERFACE,ose). - - -init_per_testcase(_Func, Config) -> - Config. -end_per_testcase(_Func, _Config) -> - ok. - -suite() -> [{timeout,{30,seconds}}]. - -all() -> - [ - basic,stress,multi_msg_numbers,multi_mailboxes, - hunt,multi_hunt,dehunt,multi_dehunt, - attach,multi_attach,detach,multi_detach, - - open_errors,close_errors,get_id_errors,get_name_errors, - hunt_errors,dehunt_errors,attach_errors,detach_errors, - send_errors,send_w_s_errors,listen_errors - ]. - -groups() -> - []. - -init_per_suite(Config) -> - case os:type() of - {ose,_} -> - Config; - _Else -> - {skip,"Only run on OSE"} - end. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -basic(_Config) -> - - [P1,P2] = multi_open(2,[42]), - P1Id = ?INTERFACE:get_id(P1), - P2Id = ?INTERFACE:get_id(P2), - - ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>), - receive - {message,P1,V1} -> - {P2Id,P1Id,42,<<"ping">>} = V1, - ?INTERFACE:send(P1,P2Id,42,<<"pong">>); - Else1 -> - ct:fail({got_wrong_message,Else1}) - end, - - receive - {message,P2,V2} -> - {P1Id,P2Id,42,<<"pong">>} = V2; - Else2 -> - ct:fail({got_wrong_message,Else2}) - end, - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - -%% Send 1000 messages and see if we can cope and that msg order is preserved -stress(_Config) -> - - Iterations = 1000, - - [P1,P2] = multi_open(2,[42]), - P1Id = ?INTERFACE:get_id(P1), - P2Id = ?INTERFACE:get_id(P2), - - spawn(fun() -> - n(fun(N) -> - Msg = [<<"ping">>|integer_to_list(N)], - ?INTERFACE:send(P2,P1Id,42,Msg) - end,Iterations) - end), - timer:sleep(100), - n(fun(N) -> - receive - {message,P1,Value} -> - Int = integer_to_binary(N), - {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value, - ok; - Else -> - ct:fail({got_wrong_message,Else}) - end - end,Iterations), - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - -%% Listen to 1000 different message numbers and send some random messages -multi_msg_numbers(_Config) -> - - Iterations = 100, - - [P1,P2] = multi_open(2,lists:seq(2000,3000)), - P1Id = ?INTERFACE:get_id(P1), - - n(fun(_) -> - Num = random:uniform(1000)+2000, - ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>) - end,Iterations), - - n(fun(_) -> - receive - {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000; - Id =< 3000 -> - Id = binary_to_integer(Num), - ok; - Else -> - ct:fail({got_wrong_message,Else}) - end - end,Iterations), - - ?INTERFACE:close(P1), - ?INTERFACE:close(P2). - - -%% Create 100 mailboxes and send messages to them -multi_mailboxes(_Config) -> - - Mailboxes = 100, - - [P1|MBs] = multi_open(Mailboxes,[42]), - - [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs], - - [receive - {message,P,Value} -> - Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)), - {_,_,42,<<"ping",Name/binary>>} = Value, - ok - end || P <- MBs], - - [?INTERFACE:close(P) || P <- [P1|MBs]], - ok. - -hunt(_Config) -> - [P1,P2] = multi_open(2,[]), - - Ref = ?INTERFACE:hunt(P1,"p2"), - receive - {mailbox_up,P1,Ref,Pid} -> - Pid = ?INTERFACE:get_id(P2), - ?INTERFACE:close(P1), - ?INTERFACE:close(P2); - Else -> - ct:fail({got_wrong_message,Else,Ref}) - end. - -multi_hunt(_Config) -> - - Iterations = 100, - - P = ?INTERFACE:open("p"), - - Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)], - - Pids = [begin - Prt = ?INTERFACE:open("p"++integer_to_list(N)), - Pid = ?INTERFACE:get_id(Prt), - ?INTERFACE:close(Prt), - Pid - end || N <- lists:seq(1,Iterations)], - - [receive - {mailbox_up,P,Ref,Pid} -> - ok - after 10 -> - ct:fail({did_not_get,Pid,Ref}) - end || {Pid,Ref} <- lists:zip(Pids,Refs)], - ?INTERFACE:close(P). - - -dehunt(_Config) -> - [P1] = multi_open(1,[]), - Ref = ?INTERFACE:hunt(P1,"p2"), - receive - _Else -> ct:fail({got,_Else}) - after 1000 -> - ok - end, - P2 = ?INTERFACE:open("p2"), - - % Make sure any messages are sent - receive after 10 -> ok end, - - ok = ?INTERFACE:dehunt(P1,Ref), - - % Make sure no messages are received - receive - _Else2 -> ct:fail({got,_Else2}) - after 1000 -> - ?INTERFACE:close(P1), - ?INTERFACE:close(P2) - end. - -%%% -%%% This testcase basically: -%%% spawn 10 processes that in parallel -%%% adds some hunts for different OSE processes -%%% maybe create hunted OSE process -%%% dehunt half of the hunts -%%% create more hunts -%%% if not created create hunted OSE process -%%% veryify that all expected hunt messages are received -%%% verify that all processes exited correctly -%%% -%%% This complex test is done to make sure that the internal handling -%%% of dehunt works as expected. -%%% -multi_dehunt(_Config) -> - [P1] = multi_open(1,[]), - - Scenario = - fun(Iterations) -> - - Hunted = "p"++integer_to_list(Iterations), - %% Start a couple of hunts - Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)], - - %% We alternate if the process is opened before or after the dehunt - P2O = if Iterations rem 2 == 0 -> - ?INTERFACE:open(Hunted); - true -> - undefined - end, - - %% Remove half of them - {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> - ok = ?INTERFACE:dehunt(P1,Ref), - {[],Acc+1}; - (Ref,Acc) -> - {Ref,Acc+1} - end,0,Refs), - - %% Add some new ones - NewRefs = [?INTERFACE:hunt(P1,Hunted) - || _ <- lists:seq(1,Iterations div 4)] - ++ lists:flatten(RemRefs), - - P2 = if P2O == undefined -> - ?INTERFACE:open(Hunted); - true -> - P2O - end, - P2Id = ?INTERFACE:get_id(P2), - - %% Receive all the expected ones - lists:foreach(fun(Ref) -> - receive - {mailbox_up,P1,Ref,P2Id} -> - ok - after 1000 -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), - ok = Ref - end - end,NewRefs), - - %% Check that no other have arrived - receive - _Else -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{got, _Else}}]), - ok = _Else - after 100 -> - ok - end, - ?INTERFACE:close(P2) - end, - - Self = self(), - - n(fun(N) -> - spawn(fun() -> Self ! - Scenario(N*25) - end), - ok - end,10), - - n(fun(_N) -> - receive ok -> ok - after 60000 -> ct:fail(failed) - end - end,10), - ?INTERFACE:close(P1). - -attach(_Config) -> - [P1,P2] = multi_open(2,[]), - - P2Id = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:attach(P1,P2Id), - ?INTERFACE:close(P2), - receive - {mailbox_down,P1,Ref,P2Id} -> - ?INTERFACE:close(P1); - _Else -> - ct:fail({got,_Else, {P1,Ref,P2Id}}) - after 1000 -> - ct:fail({did_not_get,P1,Ref,P2Id}) - end. - -multi_attach(_Config) -> - - Iterations = 100, - - [P1|Pids] = multi_open(Iterations,[]), - - Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids], - - [?INTERFACE:close(Pid) || Pid <- Pids], - - [receive - {mailbox_down,P1,Ref,Pid} -> - ok - after 10000 -> - ct:fail({did_not_get,Pid,Ref}) - end || {Pid,Ref} <- Refs], - ?INTERFACE:close(P1). - -detach(_Config) -> - [P1,P2] = multi_open(2,[]), - P2Id = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:attach(P1,P2Id), - receive - _Else -> ct:fail({got,_Else}) - after 100 -> - ok - end, - - ?INTERFACE:close(P2), - - % Make sure any messages are sent - receive after 10 -> ok end, - - ?INTERFACE:detach(P1,Ref), - - % Make sure no messages are received - receive - _Else2 -> ct:fail({got,_Else2}) - after 1000 -> - ?INTERFACE:close(P1) - end. - -%%% -%%% This testcase basically: -%%% spawn 10 processes that in parallel -%%% adds some attach for different OSE processes -%%% maybe close OSE process -%%% dehunt half of the hunts -%%% create more hunts -%%% if not closed close attached OSE process -%%% veryify that all expected attach messages are received -%%% verify that all processes exited correctly -%%% -%%% This complex test is done to make sure that the internal handling -%%% of dehunt works as expected. -%%% -multi_detach(_Config) -> - [P1] = multi_open(1,[]), - - Scenario = - fun(Iterations) -> - - Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)), - AttachedId = ?INTERFACE:get_id(Attached), - %% Start a couple of attachs - Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)], - - %% We alternate if the process is closed before or after the detach - P2O = if Iterations rem 2 == 0 -> - ?INTERFACE:close(Attached); - true -> - undefined - end, - - %% Remove half of them - {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 -> - ok = ?INTERFACE:detach(P1,Ref), - {[],Acc+1}; - (Ref,Acc) -> - {Ref,Acc+1} - end,0,Refs), - - %% Add some new ones - NewRefs = [?INTERFACE:attach(P1,AttachedId) - || _ <- lists:seq(1,Iterations div 4)] - ++ lists:flatten(RemRefs), - - if P2O == undefined -> - ?INTERFACE:close(Attached); - true -> - P2O - end, - - %% Receive all the expected ones - lists:foreach(fun(Ref) -> - receive - {mailbox_down,P1,Ref,AttachedId} -> - ok - after 1000 -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{did_not_get, Ref}}]), - ok = Ref - end - end,NewRefs), - - %% Check that no other have arrived - receive - _Else -> - io:format("Flush: ~p~n",[flush()]), - io:format("~p~n",[{Iterations,{got, _Else}}]), - ok = _Else - after 100 -> - ok - end - end, - - Self = self(), - - n(fun(N) -> - spawn(fun() -> Self ! - Scenario(N*5) - end), - ok - end,10), - - n(fun(_N) -> - receive ok -> ok - after 60000 -> ct:fail(failed) - end - end,10), - ?INTERFACE:close(P1). - - -open_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} = - (catch ?INTERFACE:open(inval)), - {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} = - (catch ?INTERFACE:open(["p"|1])), - {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} = - (catch ?INTERFACE:open(["p",1234])), - - ok. - -close_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} = - (catch ?INTERFACE:close(inval)), - - P1 = ?INTERFACE:open("p1"), - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P1). - - -get_id_errors(_Config) -> - {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} = - (catch ?INTERFACE:get_id(inval)), - - P1 = ?INTERFACE:open("p1"), - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} = - (catch ?INTERFACE:get_id(P1)), - - ok. - -get_name_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} = - (catch ?INTERFACE:get_name(P1,inval)), - - undefined = ?INTERFACE:get_name(P1,1234), - - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} = - (catch ?INTERFACE:get_name(P1,P2Id)), - ?INTERFACE:close(P2), - - P3 = ?INTERFACE:open([255]), - <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)), - ?INTERFACE:close(P3), - - ok. - -hunt_errors(_Config) -> - - {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} = - (catch ?INTERFACE:hunt(inval,"hello")), - - P1 = ?INTERFACE:open("p1"), - {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} = - (catch ?INTERFACE:hunt(P1,["hello",12345])), - - P2 = ?INTERFACE:open(<<255>>), - P2Pid = ?INTERFACE:get_id(P2), - Ref = ?INTERFACE:hunt(P1,[255]), - receive - {mailbox_up,P1,Ref,P2Pid} -> - ok; - Else -> - ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}}) - after 150 -> - ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}}) - end, - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P2), - {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} = - (catch ?INTERFACE:hunt(P1,["hello"])), - - ok. - -dehunt_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - Ref = ?INTERFACE:hunt(P1,"p2"), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} = - (catch ?INTERFACE:dehunt(inval,Ref)), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} = - (catch ?INTERFACE:dehunt(P1,inval)), - - ok = ?INTERFACE:dehunt(P1,Ref), - ok = ?INTERFACE:dehunt(P1,Ref), - - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} = - (catch ?INTERFACE:dehunt(P1,Ref)), - - case ?INTERFACE of - ose -> ok; - _ -> - P2 = ?INTERFACE:open("p2"), - ok = ?INTERFACE:close(P2) - end, - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -attach_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} = - (catch ?INTERFACE:attach(inval,P2Id)), - - {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} = - (catch ?INTERFACE:attach(P1,[12345])), - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:close(P2), - {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} = - (catch ?INTERFACE:attach(P1,P2Id)), - - ok. - -detach_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - Ref = ?INTERFACE:attach(P1,P2Id), - - {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} = - (catch ?INTERFACE:detach(inval,Ref)), - - {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} = - (catch ?INTERFACE:detach(P1,inval)), - - ok = ?INTERFACE:detach(P1,Ref), - ok = ?INTERFACE:detach(P1,Ref), - - case ?INTERFACE of - ose -> ok; - _ -> - ok = ?INTERFACE:close(P1) - end, - - ok = ?INTERFACE:close(P2), - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} = - (catch ?INTERFACE:detach(P1,Ref)), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -send_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - - {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(inval,P2Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,inval,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,inval,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,42,inval)), - - ok = ?INTERFACE:close(P2), - ok = ?INTERFACE:send(P1,P2Id,42,"hello"), - ok = ?INTERFACE:close(P1), - - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,42,"hello")), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -send_w_s_errors(_Config) -> - P1 = ?INTERFACE:open("p1"), - P1Id = ?INTERFACE:get_id(P1), - P2 = ?INTERFACE:open("p2"), - P2Id = ?INTERFACE:get_id(P2), - P3 = ?INTERFACE:open("p3"), - P3Id = ?INTERFACE:get_id(P3), - - {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")), - {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} = - (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)), - - ok = ?INTERFACE:close(P3), - ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"), - - ok = ?INTERFACE:close(P1), - ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"), - ok = ?INTERFACE:close(P2), - - {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} = - (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")), - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end. - -listen_errors(_Config) -> - - P1 = ?INTERFACE:open("p1"), - P1Id = ?INTERFACE:get_id(P1), - - {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} = - (catch ?INTERFACE:listen(inval,[42])), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} = - (catch ?INTERFACE:listen(P1,inval)), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} = - (catch ?INTERFACE:listen(P1,[1 bsl 33])), - - ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]), - - case ?INTERFACE of - ose -> ok; - _ -> - ?INTERFACE:send(P1,P1Id,42,"hello"), - timer:sleep(50), - ?INTERFACE:listen(P1,[]), - ?INTERFACE:send(P1,P1Id,42,"hello2"), - - receive - {message,P1,42,"hello"} -> ok - end, - - receive - Else -> ct:fail({got,Else}) - after 100 -> - ok - end - end, - - ok = ?INTERFACE:close(P1), - {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} = - (catch ?INTERFACE:listen(P1,[42])), - - ok. - -%% -%% Internal functions -%% -multi_open(N,ListenNums) -> - multi_open(N,ListenNums,[]). - -multi_open(0,_,Acc) -> - Acc; -multi_open(N,ListenNums,Acc) -> - P = ?INTERFACE:open("p"++integer_to_list(N)), - ok = ?INTERFACE:listen(P,ListenNums), - multi_open(N-1,ListenNums,[P|Acc]). - -n(_F,0) -> - ok; -n(F,N) -> - ok = F(N), - n(F,N-1). - - -flush() -> - receive - Msg -> - [Msg|flush()] - after 0 -> - [] - end. diff --git a/lib/ose/vsn.mk b/lib/ose/vsn.mk deleted file mode 100644 index fb1cf8219f..0000000000 --- a/lib/ose/vsn.mk +++ /dev/null @@ -1 +0,0 @@ -OSE_VSN = 1.1 diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in index 448b8c62c2..aeacee0655 100644 --- a/lib/runtime_tools/c_src/Makefile.in +++ b/lib/runtime_tools/c_src/Makefile.in @@ -102,12 +102,7 @@ endif _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -ifneq ($(findstring ose,$(TARGET)),ose) debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(NIF_LIB) -else -# We do not build this on OSE -debug opt valgrind: -endif DYNTRACE_OBJS = $(before_DTrace_OBJS) @@ -159,10 +154,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" -ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib" -endif release_docs_spec: diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl index 24fc8ce204..4e629a5e56 100644 --- a/lib/stdlib/src/slave.erl +++ b/lib/stdlib/src/slave.erl @@ -289,10 +289,7 @@ register_unique_name(Number) -> %% no need to use rsh. mk_cmd(Host, Name, Args, Waiter, Prog0) -> - Prog = case os:type() of - {ose,_} -> mk_ose_prog(Prog0); - _ -> quote_progname(Prog0) - end, + Prog = quote_progname(Prog0), BasicCmd = lists:concat([Prog, " -detached -noinput -master ", node(), " ", long_or_short(), Name, "@", Host, @@ -312,24 +309,6 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) -> end end. -%% On OSE we have to pass the beam arguments directory to the slave -%% process. To find out what arguments that should be passed on we -%% make an assumption. All arguments after the last "--" should be -%% skipped. So given these arguments: -%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' -- -name test@localhost -%% we send -%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' -- -%% to the slave with whatever other args that are added in mk_cmd. -mk_ose_prog(Prog) -> - SkipTail = fun("--",[]) -> - ["--"]; - (_,[]) -> - []; - (Arg,Args) -> - [Arg," "|Args] - end, - [Prog,tl(lists:foldr(SkipTail,[],erlang:system_info(emu_args)))]. - %% This is an attempt to distinguish between spaces in the program %% path and spaces that separate arguments. The program is quoted to %% allow spaces in the path. diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl index fd47da8150..4372e77df9 100644 --- a/lib/stdlib/test/filename_SUITE.erl +++ b/lib/stdlib/test/filename_SUITE.erl @@ -97,20 +97,11 @@ absname(Config) when is_list(Config) -> ?line file:set_cwd(Cwd), ok; - Type -> - case Type of - {unix, _} -> - ?line ok = file:set_cwd("/usr"), - ?line "/usr/foo" = filename:absname(foo), - ?line "/usr/foo" = filename:absname("foo"), - ?line "/usr/../ebin" = filename:absname("../ebin"); - {ose, _} -> - ?line ok = file:set_cwd("/romfs"), - ?line "/romfs/foo" = filename:absname(foo), - ?line "/romfs/foo" = filename:absname("foo"), - ?line "/romfs/../ebin" = filename:absname("../ebin") - end, - + {unix, _} -> + ?line ok = file:set_cwd("/usr"), + ?line "/usr/foo" = filename:absname(foo), + ?line "/usr/foo" = filename:absname("foo"), + ?line "/usr/../ebin" = filename:absname("../ebin"), ?line file:set_cwd("/"), ?line "/foo" = filename:absname(foo), ?line "/foo" = filename:absname("foo"), @@ -494,18 +485,10 @@ absname_bin(Config) when is_list(Config) -> ?line file:set_cwd(Cwd), ok; - Type -> - case Type of - {unix,_} -> - ?line ok = file:set_cwd(<<"/usr">>), - ?line <<"/usr/foo">> = filename:absname(<<"foo">>), - ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>); - {ose,_} -> - ?line ok = file:set_cwd(<<"/romfs">>), - ?line <<"/romfs/foo">> = filename:absname(<<"foo">>), - ?line <<"/romfs/../ebin">> = filename:absname(<<"../ebin">>) - end, - + {unix, _} -> + ?line ok = file:set_cwd(<<"/usr">>), + ?line <<"/usr/foo">> = filename:absname(<<"foo">>), + ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>), ?line file:set_cwd(<<"/">>), ?line <<"/foo">> = filename:absname(<<"foo">>), ?line <<"/../ebin">> = filename:absname(<<"../ebin">>), diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in index 66bba229f6..e8bce149b1 100644 --- a/lib/tools/c_src/Makefile.in +++ b/lib/tools/c_src/Makefile.in @@ -97,11 +97,8 @@ DRIVERS= ifneq ($(strip $(ETHR_LIB_NAME)),) # Need ethread package for emem -ifneq ($(findstring ose,$(TARGET)),ose) -# Do not build on OSE PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@ endif -endif EMEM_OBJ_DIR=$(OBJ_DIR)/emem CREATE_DIRS += $(EMEM_OBJ_DIR) @@ -152,12 +149,7 @@ ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE _create_dirs := $(shell mkdir -p $(CREATE_DIRS)) -ifneq ($(findstring ose,$(TARGET)),ose) all: $(PROGS) $(DRIVERS) -else -# Do not build dynamic files on OSE -all: -endif $(ERTS_LIB): $(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) -- cgit v1.2.3 From d2a0690865339a2d37badc4b79025f97b34e3d46 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 2 Jul 2015 16:07:32 +0200 Subject: Remove OSE from erl_interface --- lib/erl_interface/src/Makefile.in | 63 --------------------------------------- 1 file changed, 63 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in index 777d709b1e..d6176ec053 100644 --- a/lib/erl_interface/src/Makefile.in +++ b/lib/erl_interface/src/Makefile.in @@ -126,11 +126,7 @@ else WARNFLAGS = @WFLAGS@ endif -ifneq ($(findstring ose,$(TARGET)),ose) CFLAGS = @LIB_CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -else -CFLAGS = @CFLAGS@ $(INCFLAGS) -endif PROG_CFLAGS = @CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -Ilegacy ifeq ($(findstring vxworks,$(TARGET)),vxworks) @@ -210,12 +206,8 @@ MDD_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface_mdd$(LIBEXT) # Specify targets to build ########################################################################### -ifneq ($(findstring ose,$(TARGET)),ose) EXE_TARGETS = \ $(ERL_CALL) -else -EXE_TARGETS = -endif ifeq ($(USING_VC),yes) @@ -480,44 +472,6 @@ ERLSOURCES = \ SOURCES = $(EISOURCES) $(ERLSOURCES) -OSE_EISOURCES = \ - $(DECODESRC) \ - $(ENCODESRC) \ - misc/ei_decode_term.c \ - misc/ei_format.c \ - misc/ei_locking.c \ - misc/ei_malloc.c \ - misc/ei_printterm.c \ - misc/ei_pthreads.c \ - misc/ei_trace.c \ - misc/ei_x_encode.c \ - misc/eimd5.c \ - misc/get_type.c \ - misc/show_msg.c \ - misc/ei_compat.c \ - registry/hash_dohash.c \ - registry/hash_foreach.c \ - registry/hash_freetab.c \ - registry/hash_insert.c \ - registry/hash_isprime.c \ - registry/hash_lookup.c \ - registry/hash_newtab.c \ - registry/hash_remove.c \ - registry/hash_resize.c \ - registry/hash_rlookup.c - -OSE_ERLSOURCES = \ - legacy/decode_term.c \ - legacy/encode_term.c \ - legacy/erl_error.c \ - legacy/erl_eterm.c \ - legacy/erl_fix_alloc.c \ - legacy/erl_format.c \ - legacy/erl_malloc.c \ - legacy/erl_marshal.c - -OSE_SOURCES = $(OSE_EISOURCES) $(OSE_ERLSOURCES) - NEVERUSED = \ whereis.c \ ei_send.c \ @@ -532,13 +486,8 @@ ERLCALL = \ # Note that encode/decode_term.c defines ei functions that is # located in the erl_interface library, not ei library. -ifneq ($(findstring ose,$(TARGET)),ose) ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) -else -ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_EISOURCES:.c=.o))) -ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_ERLSOURCES:.c=.o))) -endif MT_EIOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) MT_ERLOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) MD_EIOBJECTS = $(addprefix $(MD_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) @@ -587,14 +536,6 @@ $(TARGET)/config.h: $(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@ endif -ifeq ($(findstring ose,$(TARGET)),ose) -$(TARGET)/config.h: - $(gen_verbose) - $(V_at)echo "/* Generated by Makefile */" > $@ - $(V_at)echo "#define HAVE_STRERROR 1" >> $@ - $(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@ -endif - ########################################################################### # Default rules, normal and threaded ########################################################################### @@ -718,9 +659,6 @@ $(ST_OBJDIR)/erl_call.o: prog/erl_call.c $(ST_OBJDIR)/erl_start.o: prog/erl_start.c $(V_CC) $(CFLAGS) -c $< -o $@ -else -ifeq ($(findstring ose,$(TARGET)),ose) -$(ERL_CALL): else ifdef THR_DEFS $(ERL_CALL): $(ERLCALL) ../include/ei.h $(MT_EILIB) @@ -733,7 +671,6 @@ $(ERL_CALL): $(ERLCALL) ../include/ei.h $(ST_EILIB) endif endif endif -endif ########################################################################### # Fake application targets used to test header files and linking -- cgit v1.2.3 From d0143499cd9ff1c1cf029ff33c65c908229536c7 Mon Sep 17 00:00:00 2001 From: Luca Favatella Date: Thu, 2 Jul 2015 23:57:37 +0100 Subject: Teach Dialyzer arity of funs with literal arity Re-insert logic for `erlang:make_fun/3` in `erl_bif_types`. It had been removed in bd941f5 while type spec-ing `erlang.erl`. Type spec in `erlang.erl` cannot express arity of returned fun based on value of argument hence re-introducing logic in `erl_bif_types`. Re-definition of logic in `erl_bif_types` follows approach in 9d870a0. --- .../test/small_SUITE_data/results/fun_arity | 35 ++++++ .../test/small_SUITE_data/src/fun_arity.erl | 127 +++++++++++++++++++++ lib/hipe/cerl/erl_bif_types.erl | 14 +++ 3 files changed, 176 insertions(+) create mode 100644 lib/dialyzer/test/small_SUITE_data/results/fun_arity create mode 100644 lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl (limited to 'lib') diff --git a/lib/dialyzer/test/small_SUITE_data/results/fun_arity b/lib/dialyzer/test/small_SUITE_data/results/fun_arity new file mode 100644 index 0000000000..280f5490d0 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/fun_arity @@ -0,0 +1,35 @@ + +fun_arity.erl:100: Fun application will fail since _cor1 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:100: Function 'Mfa_0_ko'/1 has no local return +fun_arity.erl:104: Fun application will fail since _cor1 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:104: Function 'Mfa_1_ko'/1 has no local return +fun_arity.erl:111: Fun application will fail since _cor1 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:111: Function mFa_0_ko/1 has no local return +fun_arity.erl:115: Fun application will fail since _cor1 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:115: Function mFa_1_ko/1 has no local return +fun_arity.erl:122: Fun application will fail since _cor2 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:122: Function 'MFa_0_ko'/2 has no local return +fun_arity.erl:126: Fun application will fail since _cor2 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:126: Function 'MFa_1_ko'/2 has no local return +fun_arity.erl:35: Fun application will fail since _cor0 :: fun(() -> 'ok') is not a function of arity 1 +fun_arity.erl:35: Function f_0_ko/0 has no local return +fun_arity.erl:39: Fun application will fail since _cor0 :: fun((_) -> 'ok') is not a function of arity 0 +fun_arity.erl:39: Function f_1_ko/0 has no local return +fun_arity.erl:48: Fun application will fail since _cor0 :: fun(() -> 'ok') is not a function of arity 1 +fun_arity.erl:48: Function fa_0_ko/0 has no local return +fun_arity.erl:53: Fun application will fail since _cor0 :: fun((_) -> 'ok') is not a function of arity 0 +fun_arity.erl:53: Function fa_1_ko/0 has no local return +fun_arity.erl:63: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:63: Function mfa_0_ko/0 has no local return +fun_arity.erl:68: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:68: Function mfa_1_ko/0 has no local return +fun_arity.erl:76: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:76: Function mfa_ne_0_ko/0 has no local return +fun_arity.erl:78: Function mf_ne/0 will never be called +fun_arity.erl:81: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:81: Function mfa_ne_1_ko/0 has no local return +fun_arity.erl:83: Function mf_ne/1 will never be called +fun_arity.erl:89: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:89: Function mfa_nd_0_ko/0 has no local return +fun_arity.erl:93: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:93: Function mfa_nd_1_ko/0 has no local return diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl new file mode 100644 index 0000000000..850d2fd331 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl @@ -0,0 +1,127 @@ +%%-------------------------------------------------------------------------- +%% Module which contains calls to funs of different arity. +%%-------------------------------------------------------------------------- +-module(fun_arity). + +-export([f_0_ok/0, f_0_ko/0]). +-export([f_1_ok/0, f_1_ko/0]). + +-export([fa_0_ok/0, fa_0_ko/0]). +-export([fa_1_ok/0, fa_1_ko/0]). + +-export([mfa_0_ok/0, mfa_0_ko/0, mf/0]). +-export([mfa_1_ok/0, mfa_1_ko/0, mf/1]). + +-export([mfa_ne_0_ok/0, mfa_ne_0_ko/0]). +-export([mfa_ne_1_ok/0, mfa_ne_1_ko/0]). + +-export([mfa_nd_0_ok/0, mfa_nd_0_ko/0]). +-export([mfa_nd_1_ok/0, mfa_nd_1_ko/0]). + +-export(['Mfa_0_ok'/1, 'Mfa_0_ko'/1]). +-export(['Mfa_1_ok'/1, 'Mfa_1_ko'/1]). + +-export(['mFa_0_ok'/1, 'mFa_0_ko'/1]). +-export(['mFa_1_ok'/1, 'mFa_1_ko'/1]). + +-export(['MFa_0_ok'/2, 'MFa_0_ko'/2]). +-export(['MFa_1_ok'/2, 'MFa_1_ko'/2]). + +%%-------------------------------------------------------------------------- + +%% Funs like "fun(...) -> ... end". + +f_0_ok() -> (fun_f_0())(). +f_0_ko() -> (fun_f_0())(1). +fun_f_0() -> fun() -> ok end. + +f_1_ok() -> (fun_f_1())(1). +f_1_ko() -> (fun_f_1())(). +fun_f_1() -> fun(_) -> ok end . + +%%-------------------------------------------------------------------------- + +%% Funs like "fun F/A" when F is literal atom and A is literal +%% non-negative integer. + +fa_0_ok() -> (fun_fa_0())(). +fa_0_ko() -> (fun_fa_0())(1). +fun_fa_0() -> fun f/0. +f() -> ok. + +fa_1_ok() -> (fun_fa_1())(1). +fa_1_ko() -> (fun_fa_1())(). +fun_fa_1() -> fun f/1. +f(_) -> ok. + +%%-------------------------------------------------------------------------- + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is (defined and) exported. + +mfa_0_ok() -> (fun_mfa_0())(). +mfa_0_ko() -> (fun_mfa_0())(1). +fun_mfa_0() -> fun ?MODULE:mf/0. +mf() -> ok. + +mfa_1_ok() -> (fun_mfa_1())(1). +mfa_1_ko() -> (fun_mfa_1())(). +fun_mfa_1() -> fun ?MODULE:mf/1. +mf(_) -> ok. + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is defined but not exported. + +mfa_ne_0_ok() -> (fun_mfa_ne_0())(). +mfa_ne_0_ko() -> (fun_mfa_ne_0())(1). +fun_mfa_ne_0() -> fun ?MODULE:mf_ne/0. +mf_ne() -> ok. + +mfa_ne_1_ok() -> (fun_mfa_ne_1())(1). +mfa_ne_1_ko() -> (fun_mfa_ne_1())(). +fun_mfa_ne_1() -> fun ?MODULE:mf_ne/1. +mf_ne(_) -> ok. + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is not defined. + +mfa_nd_0_ok() -> (fun_mfa_nd_0())(). +mfa_nd_0_ko() -> (fun_mfa_nd_0())(1). +fun_mfa_nd_0() -> fun ?MODULE:mf_nd/0. + +mfa_nd_1_ok() -> (fun_mfa_nd_1())(1). +mfa_nd_1_ko() -> (fun_mfa_nd_1())(). +fun_mfa_nd_1() -> fun ?MODULE:mf_nd/1. + +%% Funs like "fun M:F/A" when M is variable, F is literal atoms and A +%% is literal non-negative integer. + +'Mfa_0_ok'(M) -> ('fun_Mfa_0'(M))(). +'Mfa_0_ko'(M) -> ('fun_Mfa_0'(M))(1). +'fun_Mfa_0'(M) -> fun M:f/0. + +'Mfa_1_ok'(M) -> ('fun_Mfa_1'(M))(1). +'Mfa_1_ko'(M) -> ('fun_Mfa_1'(M))(). +'fun_Mfa_1'(M) -> fun M:f/1. + +%% Funs like "fun M:F/A" when M is literal atom, F is variable and A +%% is literal non-negative integer. + +'mFa_0_ok'(F) -> ('fun_mFa_0'(F))(). +'mFa_0_ko'(F) -> ('fun_mFa_0'(F))(1). +'fun_mFa_0'(F) -> fun ?MODULE:F/0. + +'mFa_1_ok'(F) -> ('fun_mFa_1'(F))(1). +'mFa_1_ko'(F) -> ('fun_mFa_1'(F))(). +'fun_mFa_1'(F) -> fun ?MODULE:F/1. + +%% Funs like "fun M:F/A" when M and F are variables and A is literal +%% non-negative integer. + +'MFa_0_ok'(M, F) -> ('fun_MFa_0'(M, F))(). +'MFa_0_ko'(M, F) -> ('fun_MFa_0'(M, F))(1). +'fun_MFa_0'(M, F) -> fun M:F/0. + +'MFa_1_ok'(M, F) -> ('fun_MFa_1'(M, F))(1). +'MFa_1_ko'(M, F) -> ('fun_MFa_1'(M, F))(). +'fun_MFa_1'(M, F) -> fun M:F/1. diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 41a6c731c9..9c3bd0a284 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -767,6 +767,18 @@ type(erlang, length, 1, Xs, Opaques) -> %% Guard bif, needs to be here. type(erlang, map_size, 1, Xs, Opaques) -> strict(erlang, map_size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); +type(erlang, make_fun, 3, Xs, Opaques) -> + strict(erlang, make_fun, 3, Xs, + fun ([_, _, Arity]) -> + case t_number_vals(Arity, Opaques) of + [N] -> + case is_integer(N) andalso 0 =< N andalso N =< 255 of + true -> t_fun(N, t_any()); + false -> t_none() + end; + _Other -> t_fun() + end + end, Opaques); type(erlang, make_tuple, 2, Xs, Opaques) -> strict(erlang, make_tuple, 2, Xs, fun ([Int, _]) -> @@ -2338,6 +2350,8 @@ arg_types(erlang, length, 1) -> %% Guard bif, needs to be here. arg_types(erlang, map_size, 1) -> [t_map()]; +arg_types(erlang, make_fun, 3) -> + [t_atom(), t_atom(), t_arity()]; arg_types(erlang, make_tuple, 2) -> [t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument arg_types(erlang, make_tuple, 3) -> -- cgit v1.2.3 From 97cf9d7e253f516417d5faa87a5de51118c8a272 Mon Sep 17 00:00:00 2001 From: Attila Gulyas Date: Tue, 14 Jul 2015 15:10:28 -0700 Subject: Fix function reference (no first/2 in ets) --- lib/stdlib/doc/src/ets.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index ab1a5900b9..03b995e4de 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -610,7 +610,7 @@ ets:is_compiled_ms(Broken).

Returns the last key Key according to Erlang term order in the table Tab of the ordered_set type. If the table is of any other type, the function is synonymous - to first/2. If the table is empty, + to first/1. If the table is empty, '$end_of_table' is returned.

Use prev/2 to find preceding keys in the table.

-- cgit v1.2.3 From 653bf1fe67615c68c627ae462fecf42c31d6ebb4 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Wed, 15 Jul 2015 10:45:01 +0200 Subject: leex: fix file/2 error tuple doc (Reported-by: Leo Liu) --- lib/parsetools/doc/src/leex.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/parsetools/doc/src/leex.xml b/lib/parsetools/doc/src/leex.xml index 7ee0633dac..85680f58a6 100644 --- a/lib/parsetools/doc/src/leex.xml +++ b/lib/parsetools/doc/src/leex.xml @@ -47,7 +47,7 @@ Token = tuple() LeexRet = {ok, Scannerfile} | {ok, Scannerfile, Warnings} | error - | {error, Warnings, Errors} + | {error, Errors, Warnings} Scannerfile = filename() Warnings = Errors = [{filename(), [ErrorInfo]}] ErrorInfo = {ErrorLine, module(), Reason} -- cgit v1.2.3 From add3f5ebead9e079f9652b48227586233b298799 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Wed, 15 Jul 2015 10:46:37 +0200 Subject: yecc: fix file/2 error tuple doc --- lib/parsetools/doc/src/yecc.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml index 8c356099e7..87fdfcdaef 100644 --- a/lib/parsetools/doc/src/yecc.xml +++ b/lib/parsetools/doc/src/yecc.xml @@ -52,7 +52,7 @@ Grammarfile = filename() Options = Option | [Option] Option = - see below - - YeccRet = {ok, Parserfile} | {ok, Parserfile, Warnings} | error | {error, Warnings, Errors} + YeccRet = {ok, Parserfile} | {ok, Parserfile, Warnings} | error | {error, Errors, Warnings} Parserfile = filename() Warnings = Errors = [{filename(), [ErrorInfo]}] ErrorInfo = {ErrorLine, module(), Reason} -- cgit v1.2.3 From 860dd9e5f5f009db0c249ebd3deeb219bec394d9 Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Wed, 1 Jul 2015 15:29:12 +0300 Subject: inets: cancel for handler with no requests httpc_handler should react properly to cancel requests even when the request to be cancelled was already finished but httpc_manager did not get notified about that yet --- lib/inets/src/http_client/httpc_handler.erl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 3f979de078..205348524a 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -421,6 +421,16 @@ handle_cast({cancel, RequestId}, {profile, ProfileName}, {canceled, Canceled}]), {noreply, State#state{canceled = [RequestId | Canceled]}}; +handle_cast({cancel, RequestId}, + #state{profile_name = ProfileName, + request = undefined, + canceled = Canceled} = State) -> + ?hcrv("cancel", [{request_id, RequestId}, + {curr_req_id, undefined}, + {profile, ProfileName}, + {canceled, Canceled}]), + {noreply, State}; + handle_cast(stream_next, #state{session = Session} = State) -> activate_once(Session), -- cgit v1.2.3 From a3d94569e38abe3faa08bc1b2305f7045470e510 Mon Sep 17 00:00:00 2001 From: Sean Charles Date: Thu, 30 Apr 2015 12:30:05 +0100 Subject: Increased left-nav width for readability It just makes it easier to read stuff. For example, gen_server functions are now totally visible, no more guessing. --- lib/erl_docgen/priv/css/otp_doc.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css index 0b531db701..347782eb1e 100644 --- a/lib/erl_docgen/priv/css/otp_doc.css +++ b/lib/erl_docgen/priv/css/otp_doc.css @@ -37,7 +37,7 @@ a:visited { color: blue; text-decoration: none } top: 0; bottom: 0; left: 0; - width: 200px; + width: 300px; overflow:auto; margin: 0; padding: 1px; @@ -45,7 +45,7 @@ a:visited { color: blue; text-decoration: none } } #content { - margin-left: 240px; /* set left value to WidthOfFrameDiv */ + margin-left: 340px; /* set left value to WidthOfFrameDiv */ } .frontpage -- cgit v1.2.3 From a3a8d25c8d884fe086d7d8ee3ebdcc732abb0abc Mon Sep 17 00:00:00 2001 From: Tom Szilagyi Date: Thu, 16 Jul 2015 13:17:30 +0200 Subject: Erlang shell: Support keys Del, Home and End Add support for the Delete, Home and End keys in the Erlang shell. These keys are ubiquitous on modern keyboards. Having them working as expected adds to the convenience of working in the shell, since they are much easier to use than the corresponding Ctrl-{D,A,E} keys. The implementation is in line with the existing framework of the line editor and is thus a natural (and minimal) extension. --- lib/stdlib/src/edlin.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/stdlib/src/edlin.erl b/lib/stdlib/src/edlin.erl index 8c7a984f1c..19444c0502 100644 --- a/lib/stdlib/src/edlin.erl +++ b/lib/stdlib/src/edlin.erl @@ -227,6 +227,8 @@ key_map($F, meta_o) -> end_of_line; key_map($\177, none) -> backward_delete_char; key_map($\177, meta) -> backward_kill_word; key_map($[, meta) -> meta_left_sq_bracket; +key_map($H, meta_left_sq_bracket) -> beginning_of_line; +key_map($F, meta_left_sq_bracket) -> end_of_line; key_map($D, meta_left_sq_bracket) -> backward_char; key_map($C, meta_left_sq_bracket) -> forward_char; % support a few + combinations... @@ -237,8 +239,10 @@ key_map($[, meta_meta) -> meta_csi; key_map($C, meta_csi) -> forward_word; key_map($D, meta_csi) -> backward_word; key_map($1, meta_left_sq_bracket) -> {csi, "1"}; +key_map($3, meta_left_sq_bracket) -> {csi, "3"}; key_map($5, meta_left_sq_bracket) -> {csi, "5"}; key_map($5, {csi, "1;"}) -> {csi, "1;5"}; +key_map($~, {csi, "3"}) -> forward_delete_char; key_map($C, {csi, "5"}) -> forward_word; key_map($C, {csi, "1;5"}) -> forward_word; key_map($D, {csi, "5"}) -> backward_word; -- cgit v1.2.3 From 60031d6b3b9b5a328eed3f972ab6550173006e8d Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sat, 18 Jul 2015 14:09:53 +0200 Subject: Add missing watchdog suite clause The suite pretends to be gen_tcp-ish in configuring itself to diameter_tcp. The function close/1 can be called as a result. --- lib/diameter/test/diameter_watchdog_SUITE.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl index f39e12686e..2520f3bc4c 100644 --- a/lib/diameter/test/diameter_watchdog_SUITE.erl +++ b/lib/diameter/test/diameter_watchdog_SUITE.erl @@ -48,7 +48,8 @@ accept/1, connect/3, send/2, - setopts/2]). + setopts/2, + close/1]). -include("diameter.hrl"). -include("diameter_ct.hrl"). @@ -420,7 +421,6 @@ suspect(TRef, false, SvcName, N) -> %% abuse/1 abuse(F) -> - [] = run([[abuse, F, T] || T <- [listen, connect]]). abuse(F, [_,_,_|_] = Args) -> @@ -545,6 +545,9 @@ setopts(Sock, Opts) -> send(Sock, Bin) -> send(getr(config), Sock, Bin). +close(Sock) -> + gen_tcp:close(Sock). + %% send/3 %% First outgoing message from a new transport process is CER/CEA. -- cgit v1.2.3 From 862af31d8a91b56711e3da554bb08247b7ee43cd Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sat, 18 Jul 2015 14:43:55 +0200 Subject: Remove unnecessary erlang:monitor/2 qualification The function has been auto-exported since R14B. --- lib/diameter/src/base/diameter_watchdog.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index de9c4bca33..9844f58ab2 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -93,7 +93,7 @@ start({_,_} = Type, T) -> Ack = make_ref(), {ok, Pid} = diameter_watchdog_sup:start_child({Ack, Type, self(), T}), try - {erlang:monitor(process, Pid), Pid} + {monitor(process, Pid), Pid} after send(Pid, Ack) end. @@ -120,7 +120,7 @@ i({Ack, T, Pid, {RecvData, #diameter_service{applications = Apps, capabilities = Caps} = Svc}}) -> - erlang:monitor(process, Pid), + monitor(process, Pid), wait(Ack, Pid), {_, Seed} = diameter_lib:seed(), random:seed(Seed), -- cgit v1.2.3 From 4f365c072b6df771004b388dd7e66f08e37ac5e7 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sat, 18 Jul 2015 14:04:28 +0200 Subject: Don't start watchdog timers unnecessarily In particular, restart the timer with each incoming Diameter message, only when the previous timer has expired. Doing so has been seen to result in high lock contention at load, as in the example below: (diameter@test)9> lcnt:conflicts([{print, [name, tries, ratio, time]}]). lock #tries collisions [%] time [us] ----- ------- --------------- ---------- bif_timers 7844528 99.4729 1394434884 db_tab 17240988 1.7947 6286664 timeofday 7358692 5.6729 1399624 proc_link 4814938 2.2736 482985 drv_ev_state 2324012 0.5951 98920 run_queue 21768213 0.2091 63516 pollset 1190174 1.7170 42499 pix_lock 1956 2.5562 39770 make_ref 4697067 0.3669 20211 proc_msgq 9475944 0.0295 5200 timer_wheel 5325966 0.0568 2654 proc_main 10005332 2.8190 1079 pollset_rm_list 59768 1.7752 480 --- lib/diameter/src/base/diameter_watchdog.erl | 41 +++++++++++++++++++---------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index 9844f58ab2..0607c72818 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -65,7 +65,10 @@ %% end PCB parent = self() :: pid(), %% service process transport :: pid() | undefined, %% peer_fsm process - tref :: reference(), %% reference for current watchdog timer + tref :: reference() %% reference for current watchdog timer + | integer() %% monotonic time + | tuple() %% now() + | undefined, dictionary :: module(), %% common dictionary receive_data :: term(), %% term passed into diameter_service with incoming message @@ -446,11 +449,12 @@ transition({recv, TPid, Name, Pkt}, #watchdog{transport = TPid} = S) -> %% Current watchdog has timed out. transition({timeout, TRef, tw}, #watchdog{tref = TRef} = S) -> - set_watchdog(timeout(S)); + set_watchdog(0, timeout(S)); -%% Timer was canceled after message was already sent. -transition({timeout, _, tw}, #watchdog{}) -> - ok; +%% Message has arrived since the timer was started: subtract time +%% already elapsed from new timer. +transition({timeout, _, tw}, #watchdog{tref = T0} = S) -> + set_watchdog(diameter_lib:micro_diff(T0) div 1000, S); %% State query. transition({state, Pid}, #watchdog{status = S}) -> @@ -526,18 +530,27 @@ role() -> %% set_watchdog/1 -set_watchdog(#watchdog{tw = TwInit, - tref = TRef} - = S) -> - cancel(TRef), - S#watchdog{tref = erlang:start_timer(tw(TwInit), self(), tw)}; +%% Timer not yet set. +set_watchdog(#watchdog{tref = undefined} = S) -> + set_watchdog(0, S); + +%% Timer already set: start at new one only at expiry. +set_watchdog(#watchdog{} = S) -> + S#watchdog{tref = diameter_lib:now()}; + set_watchdog(stop = No) -> No. -cancel(undefined) -> - ok; -cancel(TRef) -> - erlang:cancel_timer(TRef). +%% set_watchdog/2 + +set_watchdog(Ms, #watchdog{tw = TwInit} = S) -> + S#watchdog{tref = erlang:start_timer(tw(TwInit, Ms), self(), tw)}. + +%% A callback could return anything, so ensure the result isn't +%% negative. Don't prevent abuse, even though the smallest valid +%% timeout is 4000. +tw(TwInit, Ms) -> + max(tw(TwInit) - Ms, 0). tw(T) when is_integer(T), T >= 6000 -> -- cgit v1.2.3 From d9fd104e64eccbdca2a9d7d3efb801c8d85ecb18 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 8 Jun 2015 12:15:23 +0200 Subject: ssl: Do not crash on proprietary hash_sign algorithms TLS hash_sign algorithms may have proprietary values see http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml We should add callbacks to let applications handle them. But for now we do not want to crash if they are present and let other algorithms be negotiated. --- lib/ssl/src/ssl_cipher.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index bec0055353..c2af0f946a 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -1209,7 +1209,8 @@ hash_algorithm(?SHA) -> sha; hash_algorithm(?SHA224) -> sha224; hash_algorithm(?SHA256) -> sha256; hash_algorithm(?SHA384) -> sha384; -hash_algorithm(?SHA512) -> sha512. +hash_algorithm(?SHA512) -> sha512; +hash_algorithm(Other) when is_integer(Other) andalso ((Other >= 224) and (Other =< 255)) -> Other. sign_algorithm(anon) -> ?ANON; sign_algorithm(rsa) -> ?RSA; @@ -1218,7 +1219,8 @@ sign_algorithm(ecdsa) -> ?ECDSA; sign_algorithm(?ANON) -> anon; sign_algorithm(?RSA) -> rsa; sign_algorithm(?DSA) -> dsa; -sign_algorithm(?ECDSA) -> ecdsa. +sign_algorithm(?ECDSA) -> ecdsa; +sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 224) and (Other =< 255)) -> Other. hash_size(null) -> 0; -- cgit v1.2.3 From 67e156b0472b06a04fd5b1b8ab830efc22e4466d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 30 Jun 2015 22:33:27 +0200 Subject: ssh: Repair/add experimental diffie-hellman-group-exchange-sha1 support DO NOT USE IN PRODUCTION!!! This is a bug fixing of the previously partly impelmented kex algorithm. There are more things to do, for example genrate/select better g,p pair obeying the min||n||max request. It is not enabled by default, but may be enabled with the option {preferred_algorithms, [{kex, ['diffie-hellman-group-exchange-sha1']}]} --- lib/ssh/src/ssh_connection_handler.erl | 42 ++++-- lib/ssh/src/ssh_message.erl | 17 ++- lib/ssh/src/ssh_transport.erl | 247 ++++++++++++++++++++++----------- lib/ssh/test/ssh_basic_SUITE.erl | 51 +++++++ lib/ssh/test/ssh_sftp_SUITE.erl | 61 +++++--- 5 files changed, 303 insertions(+), 115 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index a9c60d0674..c059834b27 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -46,7 +46,9 @@ get_print_info/1]). %% gen_fsm callbacks --export([hello/2, kexinit/2, key_exchange/2, new_keys/2, +-export([hello/2, kexinit/2, key_exchange/2, + key_exchange_dh_gex_init/2, key_exchange_dh_gex_reply/2, + new_keys/2, userauth/2, connected/2, error/2]). @@ -417,26 +419,38 @@ key_exchange(#ssh_msg_kexdh_reply{} = Msg, send_msg(NewKeys, State), {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}; -key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg, +key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg, #state{ssh_params = #ssh{role = server} = Ssh0} = State) -> - {ok, NextKexMsg, Ssh1} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0), - send_msg(NextKexMsg, State), - {ok, NewKeys, Ssh} = ssh_transport:new_keys_message(Ssh1), - send_msg(NewKeys, State), - {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}; + {ok, GexGroup, Ssh} = ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0), + send_msg(GexGroup, State), + {next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})}; -key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg, +key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg, #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> - {ok, NextKexMsg, Ssh} = ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0), - send_msg(NextKexMsg, State), - {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}; + {ok, KexGexInit, Ssh} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0), + send_msg(KexGexInit, State), + {next_state, key_exchange_dh_gex_reply, next_packet(State#state{ssh_params = Ssh})}. -key_exchange(#ssh_msg_kex_dh_gex_reply{} = Msg, - #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> - {ok, NewKeys, Ssh} = ssh_transport:handle_kex_dh_gex_reply(Msg, Ssh0), +%%-------------------------------------------------------------------- +-spec key_exchange_dh_gex_init(#ssh_msg_kex_dh_gex_init{}, #state{}) -> gen_fsm_state_return(). +%%-------------------------------------------------------------------- +key_exchange_dh_gex_init(#ssh_msg_kex_dh_gex_init{} = Msg, + #state{ssh_params = #ssh{role = server} = Ssh0} = State) -> + {ok, KexGexReply, Ssh1} = ssh_transport:handle_kex_dh_gex_init(Msg, Ssh0), + send_msg(KexGexReply, State), + {ok, NewKeys, Ssh} = ssh_transport:new_keys_message(Ssh1), send_msg(NewKeys, State), {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}. +%%-------------------------------------------------------------------- +-spec key_exchange_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{}, #state{}) -> gen_fsm_state_return(). +%%-------------------------------------------------------------------- +key_exchange_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{} = Msg, + #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> + {ok, NewKeys, Ssh1} = ssh_transport:handle_kex_dh_gex_reply(Msg, Ssh0), + send_msg(NewKeys, State), + {next_state, new_keys, next_packet(State#state{ssh_params = Ssh1})}. + %%-------------------------------------------------------------------- -spec new_keys(#ssh_msg_newkeys{}, #state{}) -> gen_fsm_state_return(). %%-------------------------------------------------------------------- diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index 1f0f6fb15f..7b786b8fff 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -237,7 +237,7 @@ encode(#ssh_msg_kex_dh_gex_request{ max = Max }) -> ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST, Min, N, Max], - [byte, uint32, uint32, uint32, uint32]); + [byte, uint32, uint32, uint32]); encode(#ssh_msg_kex_dh_gex_request_old{n = N}) -> ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST_OLD, N], [byte, uint32]); @@ -257,7 +257,7 @@ encode(#ssh_msg_kex_dh_gex_reply{ }) -> EncKey = encode_host_key(Key), EncSign = encode_sign(Key, Signature), - ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); + ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); encode(#ssh_msg_ignore{data = Data}) -> ssh_bits:encode([?SSH_MSG_IGNORE, Data], [byte, string]); @@ -442,6 +442,19 @@ decode(<>) -> + #ssh_msg_kex_dh_gex_init{ + e = E + }; +decode(<>) -> + #ssh_msg_kex_dh_gex_reply{ + public_host_key = decode_host_key(Key), + f = F, + h_sig = decode_sign(Hashsign) + }; decode(<>) -> diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 2e7391e1f8..ce0762bf96 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -39,7 +39,7 @@ key_exchange_init_msg/1, key_init/3, new_keys_message/1, handle_kexinit_msg/3, handle_kexdh_init/2, - handle_kex_dh_gex_group/2, handle_kex_dh_gex_reply/2, + handle_kex_dh_gex_group/2, handle_kex_dh_gex_init/2, handle_kex_dh_gex_reply/2, handle_new_keys/2, handle_kex_dh_gex_request/2, handle_kexdh_reply/2, unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1, @@ -66,6 +66,8 @@ algo_classes() -> [kex, public_key, cipher, mac, compression]. default_algorithms(compression) -> %% Do not announce 'zlib@openssh.com' because there seem to be problems supported_algorithms(compression, same(['zlib@openssh.com'])); +default_algorithms(kex) -> + supported_algorithms(kex, ['diffie-hellman-group-exchange-sha1']); default_algorithms(Alg) -> supported_algorithms(Alg). @@ -73,7 +75,8 @@ default_algorithms(Alg) -> supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()]. supported_algorithms(kex) -> - ['diffie-hellman-group1-sha1']; + ['diffie-hellman-group1-sha1', + 'diffie-hellman-group-exchange-sha1']; supported_algorithms(public_key) -> ssh_auth:default_public_key_algorithms(); supported_algorithms(cipher) -> @@ -135,7 +138,7 @@ ssh_vsn() -> _:_ -> "" end. -random_id(Nlo, Nup) -> +random_id(Nlo, Nup) -> [crypto:rand_uniform($a,$z+1) || _<- lists:duplicate(crypto:rand_uniform(Nlo,Nup+1),x) ]. hello_version_msg(Data) -> @@ -144,7 +147,7 @@ hello_version_msg(Data) -> next_seqnum(SeqNum) -> (SeqNum + 1) band 16#ffffffff. -decrypt_first_block(Bin, #ssh{decrypt_block_size = BlockSize} = Ssh0) -> +decrypt_first_block(Bin, #ssh{decrypt_block_size = BlockSize} = Ssh0) -> <> = Bin, {Ssh, <> = DecData} = decrypt(Ssh0, EncBlock), @@ -282,9 +285,14 @@ verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) -> true; verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) -> true; verify_algorithm(_) -> false. +%%%---------------------------------------------------------------- +%%% +%%% Key exchange initialization +%%% key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) -> {G, P} = dh_group1(), {Private, Public} = dh_gen_key(G, P, 1024), + %% Public = G^Private mod P (def) {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0), {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}; @@ -295,13 +303,18 @@ key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) -> Max = ?DEFAULT_DH_GROUP_MAX, {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kex_dh_gex_request{min = Min, - n = NBits, max = Max}, + n = NBits, + max = Max}, Ssh0), {ok, SshPacket, Ssh1#ssh{keyex_info = {Min, Max, NBits}}}. - +%%%---------------------------------------------------------------- +%%% +%%% diffie-hellman-group1-sha1 +%%% handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) -> + %% server {G, P} = dh_group1(), if 1= @@ -314,101 +327,176 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) -> f = Public, h_sig = H_SIG }, Ssh0), - {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}, shared_secret = K, exchanged_hash = H, session_id = sid(Ssh1, H)}}; + true -> - Error = {error,bad_e_from_peer}, - Disconnect = #ssh_msg_disconnect{ - code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, - description = "Key exchange failed, 'f' out of bounds", - language = "en"}, - throw({Error, Disconnect}) + throw({{error,bad_e_from_peer}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed, 'e' out of bounds", + language = ""} + }) end. -handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) -> - {Private, Public} = dh_gen_key(G,P,1024), - {SshPacket, Ssh1} = - ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0), - {ok, SshPacket, - Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}. +handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, + f = F, + h_sig = H_SIG}, + #ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) -> + %% client + if + 1= + K = ssh_math:ipow(F, Private, P), + H = kex_h(Ssh0, HostKey, Public, F, K), + + case verify_host_key(Ssh0, HostKey, H, H_SIG) of + ok -> + {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), + {ok, SshPacket, Ssh#ssh{shared_secret = K, + exchanged_hash = H, + session_id = sid(Ssh, H)}}; + Error -> + throw({Error, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed", + language = "en"} + }) + end; -handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> - try install_alg(Ssh0) of - #ssh{} = Ssh -> - {ok, Ssh} - catch - error:_Error -> %% TODO: Throw earlier .... - throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "Install alg failed", - language = "en"}) - end. + true -> + throw({{error,bad_f_from_peer}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed, 'f' out of bounds", + language = ""} + }) + end. -%% %% Select algorithms -handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F, - h_sig = H_SIG}, - #ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) when 1= - K = ssh_math:ipow(F, Private, P), - H = kex_h(Ssh0, HostKey, Public, F, K), - - case verify_host_key(Ssh0, HostKey, H, H_SIG) of - ok -> - {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), - {ok, SshPacket, Ssh#ssh{shared_secret = K, - exchanged_hash = H, - session_id = sid(Ssh, H)}}; - Error -> - Disconnect = #ssh_msg_disconnect{ - code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, - description = "Key exchange failed", - language = "en"}, - throw({Error, Disconnect}) - end; -handle_kexdh_reply(#ssh_msg_kexdh_reply{}, _SSH) -> - Error = {error,bad_f_from_peer}, - Disconnect = #ssh_msg_disconnect{ - code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, - description = "Key exchange failed, 'f' out of bounds", - language = "en"}, - throw({Error, Disconnect}). - - -handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = _Min, - n = _NBits, - max = _Max}, Ssh0) -> +%%%---------------------------------------------------------------- +%%% +%%% diffie-hellman-group-exchange-sha1 +%%% +handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, + n = NBits, + max = Max}, Ssh0) -> + %% server {G,P} = dh_group1(), %% TODO real imp this seems to be a hack?! {Private, Public} = dh_gen_key(G, P, 1024), {SshPacket, Ssh} = ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), {ok, SshPacket, - Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}}}. + Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, + keyex_info = {Min, Max, NBits} + }}. + +handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) -> + %% client + {Private, Public} = dh_gen_key(G, P, 1024), + {SshPacket, Ssh1} = + ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0), % Pub = G^Priv mod P (def) + + {ok, SshPacket, + Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}. + +handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, + #ssh{keyex_key = {{Private, Public}, {G, P}}, + keyex_info = {Min, Max, NBits}} = + Ssh0) -> + %% server + if + 1= + K = ssh_math:ipow(E, Private, P), + if + 1 + HostKey = get_host_key(Ssh0), + H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, E, Public, K), + H_SIG = sign_host_key(Ssh0, HostKey, H), + {SshPacket, Ssh} = + ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, + f = Public, + h_sig = H_SIG}, Ssh0), + {ok, SshPacket, Ssh#ssh{shared_secret = K, + exchanged_hash = H, + session_id = sid(Ssh, H) + }}; + true -> + throw({{error,bad_K}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed, 'K' out of bounds", + language = ""} + }) + end; + true -> + throw({{error,bad_e_from_peer}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed, 'e' out of bounds", + language = ""} + }) + end. handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, f = F, h_sig = H_SIG}, #ssh{keyex_key = {{Private, Public}, {G, P}}, keyex_info = {Min, Max, NBits}} = - Ssh0) -> - K = ssh_math:ipow(F, Private, P), - H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K), - - case verify_host_key(Ssh0, HostKey, H, H_SIG) of - ok -> - {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), - {ok, SshPacket, Ssh#ssh{shared_secret = K, - exchanged_hash = H, - session_id = sid(Ssh, H)}}; - _Error -> - Disconnect = #ssh_msg_disconnect{ - code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, - description = "Key exchange failed", - language = "en"}, - throw(Disconnect) + Ssh0) -> + %% client + if + 1= + K = ssh_math:ipow(F, Private, P), + if + 1 + H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K), + + case verify_host_key(Ssh0, HostKey, H, H_SIG) of + ok -> + {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), + {ok, SshPacket, Ssh#ssh{shared_secret = K, + exchanged_hash = H, + session_id = sid(Ssh, H)}}; + _Error -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed", + language = ""} + ) + end; + + true -> + throw({{error,bad_K}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed, 'K' out of bounds", + language = ""} + }) + end; + true -> + throw({{error,bad_f_from_peer}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed, 'f' out of bounds", + language = ""} + }) end. +%%%---------------------------------------------------------------- +handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> + try install_alg(Ssh0) of + #ssh{} = Ssh -> + {ok, Ssh} + catch + error:_Error -> %% TODO: Throw earlier .... + throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Install alg failed", + language = "en"}) + end. + %% select session id sid(#ssh{session_id = undefined}, H) -> H; @@ -511,7 +599,6 @@ select_algorithm(Role, Client, Server) -> decompress = Decompression, c_lng = C_Lng, s_lng = S_Lng}, -%%ct:pal("~p~n Client=~p~n Server=~p~n Alg=~p~n",[Role,Client,Server,Alg]), {ok, Alg}. select_encrypt_decrypt(client, Client, Server) -> @@ -1001,7 +1088,7 @@ recv_mac_init(SSH) -> recv_mac_final(SSH) -> {ok, SSH#ssh { recv_mac = none, recv_mac_key = undefined }}. -mac(none, _ , _, _) -> +mac(none, _ , _, _) -> <<>>; mac('hmac-sha1', Key, SeqNum, Data) -> crypto:hmac(sha, Key, [<>, Data]); diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index bf9fe54c57..c71463db30 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -42,6 +42,7 @@ suite() -> all() -> [app_test, appup_test, + {group, 'diffie-hellman-group-exchange-sha1'}, {group, dsa_key}, {group, rsa_key}, {group, dsa_pass_key}, @@ -92,6 +93,8 @@ groups() -> max_sessions_sftp_start_channel_parallel, max_sessions_sftp_start_channel_sequential ]}, + {'diffie-hellman-group-exchange-sha1', [], ['diffie-hellman-group-exchange-sha1' + ]}, {dir_options, [], [user_dir_option, system_dir_option]} ]. @@ -146,6 +149,17 @@ init_per_group(internal_error, Config) -> ssh_test_lib:setup_dsa(DataDir, PrivDir), file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")), Config; +init_per_group('diffie-hellman-group-exchange-sha1', Config) -> + case lists:member('diffie-hellman-group-exchange-sha1', + ssh_transport:supported_algorithms(kex)) of + true -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_rsa(DataDir, PrivDir), + Config; + false -> + {skip,"diffie-hellman-group-exchange-sha1 is not supported"} + end; init_per_group(dir_options, Config) -> PrivDir = ?config(priv_dir, Config), %% Make unreadable dir: @@ -817,6 +831,43 @@ ssh_msg_debug_fun_option_client(Config) -> {fail,timeout} end. +%%-------------------------------------------------------------------- +'diffie-hellman-group-exchange-sha1'(Config) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{"foo", "bar"}]}, + {preferred_algorithms, + [{kex, ['diffie-hellman-group-exchange-sha1']}]}, + {failfun, fun ssh_test_lib:failfun/2}]), + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "bar"}, + {user_dir, UserDir}, + {preferred_algorithms, + [{kex, ['diffie-hellman-group-exchange-sha1']}]}, + {user_interaction, false}]), + check(ConnectionRef, Pid). + +check(ConnectionRef, Pid) -> + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "1+1.", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ok; + Other -> + ct:fail(Other) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + ssh:stop_daemon(Pid). + %%-------------------------------------------------------------------- connectfun_disconnectfun_server(Config) -> PrivDir = ?config(priv_dir, Config), diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 6c631e6f6e..86ab503c20 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -64,12 +64,16 @@ end_per_suite(Config) -> groups() -> [{not_unicode, [], [{group,erlang_server}, {group,openssh_server}, + {group,'diffie-hellman-group-exchange-sha1'}, sftp_nonexistent_subsystem]}, {unicode, [], [{group,erlang_server}, {group,openssh_server}, sftp_nonexistent_subsystem]}, + {'diffie-hellman-group-exchange-sha1', [], [{group,erlang_server}, + {group,openssh_server}]}, + {erlang_server, [], [{group,write_read_tests}, version_option, {group,remote_tar}]}, @@ -142,22 +146,26 @@ init_per_group(erlang_server, Config) -> User = ?config(user, Config), Passwd = ?config(passwd, Config), Sftpd = {_, HostX, PortX} = - ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, PrivDir}, - {user_passwords, - [{User, Passwd}]}]), + ssh_test_lib:daemon(extra_opts(Config) ++ + [{system_dir, SysDir}, + {user_dir, PrivDir}, + {user_passwords, + [{User, Passwd}]}]), [{peer, {fmt_host(HostX),PortX}}, {group, erlang_server}, {sftpd, Sftpd} | Config]; init_per_group(openssh_server, Config) -> ct:comment("Begin ~p",[grps(Config)]), Host = ssh_test_lib:hostname(), - case (catch ssh_sftp:start_channel(Host, - [{user_interaction, false}, - {silently_accept_hosts, true}])) of + case (catch ssh_sftp:start_channel(Host, + extra_opts(Config) ++ + [{user_interaction, false}, + {silently_accept_hosts, true}])) of {ok, _ChannelPid, Connection} -> [{peer, {_HostName,{IPx,Portx}}}] = ssh:connection_info(Connection,[peer]), ssh:close(Connection), [{peer, {fmt_host(IPx),Portx}}, {group, openssh_server} | Config]; + {error,"Key exchange failed"} -> + {skip, "openssh server lacks 'diffie-hellman-group-exchange-sha1'"}; _ -> {skip, "No openssh server"} end; @@ -172,10 +180,11 @@ init_per_group(remote_tar, Config) -> case ?config(group, Config) of erlang_server -> ssh:connect(Host, Port, - [{user, User}, - {password, Passwd}, - {user_interaction, false}, - {silently_accept_hosts, true}]); + extra_opts(Config) ++ + [{user, User}, + {password, Passwd}, + {user_interaction, false}, + {silently_accept_hosts, true}]); openssh_server -> ssh:connect(Host, Port, [{user_interaction, false}, @@ -184,6 +193,17 @@ init_per_group(remote_tar, Config) -> [{remote_tar, true}, {connection, Connection} | Config]; +init_per_group('diffie-hellman-group-exchange-sha1', Config) -> + case lists:member('diffie-hellman-group-exchange-sha1', + ssh_transport:supported_algorithms(kex)) of + true -> + [{extra_opts, [{preferred_algorithms, [{kex,['diffie-hellman-group-exchange-sha1']}]}]} + | Config]; + + false -> + {skip,"'diffie-hellman-group-exchange-sha1' not supported by this version of erlang ssh"} + end; + init_per_group(write_read_tests, Config) -> ct:comment("Begin ~p",[grps(Config)]), Config. @@ -194,7 +214,6 @@ grps(Config) -> lists:flatten([proplists:get_value(tc_group_properties,Config,[]), proplists:get_value(tc_group_path,Config,[])])). - end_per_group(erlang_server, Config) -> ct:comment("End ~p",[grps(Config)]), Config; @@ -249,10 +268,12 @@ init_per_testcase(Case, Config0) -> {_,Host, Port} = ?config(sftpd, Config2), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, Port, - [{user, User}, - {password, Passwd}, - {user_interaction, false}, - {silently_accept_hosts, true}]), + extra_opts(Config2) ++ + [{user, User}, + {password, Passwd}, + {user_interaction, false}, + {silently_accept_hosts, true}] + ), Sftp = {ChannelPid, Connection}, [{sftp, Sftp}, {watchdog, Dog} | Config2]; openssh_server when Case == links -> @@ -261,8 +282,9 @@ init_per_testcase(Case, Config0) -> Host = ssh_test_lib:hostname(), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, - [{user_interaction, false}, - {silently_accept_hosts, true}]), + extra_opts(Config2) ++ + [{user_interaction, false}, + {silently_accept_hosts, true}]), Sftp = {ChannelPid, Connection}, [{sftp, Sftp}, {watchdog, Dog} | Config2] end, @@ -910,7 +932,8 @@ prep(Config) -> ok = file:write_file_info(TestFile, FileInfo#file_info{mode = Mode}). - +extra_opts(Config) -> + proplists:get_value(extra_opts, Config, []). chk_tar(Items, Config) -> chk_tar(Items, Config, []). -- cgit v1.2.3 From 2a9f5054f89ca02c1a35dcb96c3ad747663afd51 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 2 Jul 2015 12:49:17 +0200 Subject: ssh: Add experimental 'diffie-hellman-group-exchange-sha256 support DO NOT USE IN PRODUCTION!!! It is not enabled by default, but may be enabled with the option {preferred_algorithms, [{kex, ['diffie-hellman-group-exchange-sha256']}]} --- lib/ssh/src/ssh_transport.erl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index ce0762bf96..a0714ac97c 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -67,7 +67,10 @@ default_algorithms(compression) -> %% Do not announce 'zlib@openssh.com' because there seem to be problems supported_algorithms(compression, same(['zlib@openssh.com'])); default_algorithms(kex) -> - supported_algorithms(kex, ['diffie-hellman-group-exchange-sha1']); + %% Do not announce the experimental 'diffie-hellman-group-exchange-sha*' yet + supported_algorithms(kex, ['diffie-hellman-group-exchange-sha1', + 'diffie-hellman-group-exchange-sha256' + ]); default_algorithms(Alg) -> supported_algorithms(Alg). @@ -76,7 +79,9 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()]. supported_algorithms(kex) -> ['diffie-hellman-group1-sha1', - 'diffie-hellman-group-exchange-sha1']; + 'diffie-hellman-group-exchange-sha1', + 'diffie-hellman-group-exchange-sha256' + ]; supported_algorithms(public_key) -> ssh_auth:default_public_key_algorithms(); supported_algorithms(cipher) -> @@ -283,6 +288,7 @@ verify_algorithm(#alg{decompress = undefined}) -> false; verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) -> true; verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) -> true; +verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha256'}) -> true; verify_algorithm(_) -> false. %%%---------------------------------------------------------------- @@ -297,7 +303,8 @@ key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) -> {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}; -key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) -> +key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group-exchange-sha1' ; + Kex == 'diffie-hellman-group-exchange-sha256' -> Min = ?DEFAULT_DH_GROUP_MIN, NBits = ?DEFAULT_DH_GROUP_NBITS, Max = ?DEFAULT_DH_GROUP_MAX, @@ -1109,6 +1116,8 @@ hash(SSH, Char, Bits) -> fun(Data) -> crypto:hash(sha, Data) end; 'diffie-hellman-group-exchange-sha1' -> fun(Data) -> crypto:hash(sha, Data) end; + 'diffie-hellman-group-exchange-sha256' -> + fun(Data) -> crypto:hash(sha256, Data) end; _ -> exit({bad_algorithm,SSH#ssh.kex}) end, @@ -1158,8 +1167,11 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> ssh_message:encode_host_key(Key), Min, NBits, Max, Prime, Gen, E,F,K], Ts) end, - crypto:hash(sha,L). + crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). +sha('diffie-hellman-group-exchange-sha1') -> sha; +sha('diffie-hellman-group-exchange-sha256') -> sha256. + mac_key_size('hmac-sha1') -> 20*8; mac_key_size('hmac-sha1-96') -> 20*8; mac_key_size('hmac-md5') -> 16*8; -- cgit v1.2.3 From b87115416297a57f8e303c6bc75483f943ea4954 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 2 Jul 2015 12:56:59 +0200 Subject: ssh: add test group --- lib/ssh/test/ssh_sftp_SUITE.erl | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 86ab503c20..a95e16a0b3 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -65,6 +65,7 @@ groups() -> [{not_unicode, [], [{group,erlang_server}, {group,openssh_server}, {group,'diffie-hellman-group-exchange-sha1'}, + {group,'diffie-hellman-group-exchange-sha256'}, sftp_nonexistent_subsystem]}, {unicode, [], [{group,erlang_server}, @@ -74,6 +75,9 @@ groups() -> {'diffie-hellman-group-exchange-sha1', [], [{group,erlang_server}, {group,openssh_server}]}, + {'diffie-hellman-group-exchange-sha256', [], [{group,erlang_server}, + {group,openssh_server}]}, + {erlang_server, [], [{group,write_read_tests}, version_option, {group,remote_tar}]}, @@ -165,7 +169,7 @@ init_per_group(openssh_server, Config) -> ssh:close(Connection), [{peer, {fmt_host(IPx),Portx}}, {group, openssh_server} | Config]; {error,"Key exchange failed"} -> - {skip, "openssh server lacks 'diffie-hellman-group-exchange-sha1'"}; + {skip, "openssh server doesn't support the tested kex algorithm"}; _ -> {skip, "No openssh server"} end; @@ -204,6 +208,17 @@ init_per_group('diffie-hellman-group-exchange-sha1', Config) -> {skip,"'diffie-hellman-group-exchange-sha1' not supported by this version of erlang ssh"} end; +init_per_group('diffie-hellman-group-exchange-sha256', Config) -> + case lists:member('diffie-hellman-group-exchange-sha256', + ssh_transport:supported_algorithms(kex)) of + true -> + [{extra_opts, [{preferred_algorithms, [{kex,['diffie-hellman-group-exchange-sha256']}]}]} + | Config]; + + false -> + {skip,"'diffie-hellman-group-exchange-sha256' not supported by this version of erlang ssh"} + end; + init_per_group(write_read_tests, Config) -> ct:comment("Begin ~p",[grps(Config)]), Config. @@ -246,11 +261,12 @@ init_per_testcase(version_option, Config) -> Passwd = ?config(passwd, Config), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, Port, - [{sftp_vsn, 3}, - {user, User}, - {password, Passwd}, - {user_interaction, false}, - {silently_accept_hosts, true}]), + extra_opts(Config) ++ + [{sftp_vsn, 3}, + {user, User}, + {password, Passwd}, + {user_interaction, false}, + {silently_accept_hosts, true}]), Sftp = {ChannelPid, Connection}, [{sftp,Sftp}, {watchdog, Dog} | TmpConfig]; -- cgit v1.2.3 From d964a7bfb9b87bf69f8a131aea517f4f0bfdfdd1 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 3 Jul 2015 12:47:19 +0200 Subject: ssh: filter algs unknown to crypto (except pk) --- lib/ssh/src/ssh_transport.erl | 44 ++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index a0714ac97c..a0a0217fe2 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -78,26 +78,28 @@ default_algorithms(Alg) -> supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()]. supported_algorithms(kex) -> - ['diffie-hellman-group1-sha1', - 'diffie-hellman-group-exchange-sha1', - 'diffie-hellman-group-exchange-sha256' - ]; + select_crypto_supported( + [{'diffie-hellman-group1-sha1', [{hashs,sha}]}, + {'diffie-hellman-group-exchange-sha1', [{hashs,sha}]}, + {'diffie-hellman-group-exchange-sha256', [{hashs,sha256}]} + ]); supported_algorithms(public_key) -> ssh_auth:default_public_key_algorithms(); supported_algorithms(cipher) -> - Supports = crypto:supports(), - CipherAlgos = [{aes_ctr, 'aes128-ctr'}, {aes_cbc128, 'aes128-cbc'}, {des3_cbc, '3des-cbc'}], - Algs = [SshAlgo || - {CryptoAlgo, SshAlgo} <- CipherAlgos, - lists:member(CryptoAlgo, proplists:get_value(ciphers, Supports, []))], - same(Algs); + same( + select_crypto_supported( + [{'aes128-ctr', [{ciphers,aes_ctr}]}, + {'aes128-cbc', [{ciphers,aes_cbc128}]}, + {'3des-cbc', [{ciphers,des3_cbc}]} + ] + )); supported_algorithms(mac) -> - Supports = crypto:supports(), - HashAlgos = [{sha256, 'hmac-sha2-256'}, {sha, 'hmac-sha1'}], - Algs = [SshAlgo || - {CryptoAlgo, SshAlgo} <- HashAlgos, - lists:member(CryptoAlgo, proplists:get_value(hashs, Supports, []))], - same(Algs); + same( + select_crypto_supported( + [{'hmac-sha2-256', [{hashs,sha256}]}, + {'hmac-sha1', [{hashs,sha}]} + ] + )); supported_algorithms(compression) -> same(['none','zlib','zlib@openssh.com']). @@ -108,7 +110,15 @@ supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> supported_algorithms(Key, BlackList) -> supported_algorithms(Key) -- BlackList. - +select_crypto_supported(L) -> + Sup = crypto:supports(), + [Name || {Name,CryptoRequires} <- L, + crypto_supported(CryptoRequires, Sup)]. + +crypto_supported(Conditions, Supported) -> + lists:all(fun({Tag,CryptoName}) -> + lists:member(CryptoName, proplists:get_value(Tag,Supported,[])) + end, Conditions). same(Algs) -> [{client2server,Algs}, {server2client,Algs}]. -- cgit v1.2.3 From ec0da994d1c223cc7b1fde18061464a6c44cdf0b Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 3 Aug 2015 16:50:53 +0200 Subject: ssh: rm ssh_math and use crypto:compute_key instead --- lib/ssh/src/Makefile | 1 - lib/ssh/src/ssh.app.src | 1 - lib/ssh/src/ssh_math.erl | 42 ------------------------------------------ lib/ssh/src/ssh_transport.erl | 15 ++++++++++----- 4 files changed, 10 insertions(+), 49 deletions(-) delete mode 100644 lib/ssh/src/ssh_math.erl (limited to 'lib') diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile index 61d71d2cf7..98fb90d7c4 100644 --- a/lib/ssh/src/Makefile +++ b/lib/ssh/src/Makefile @@ -67,7 +67,6 @@ MODULES= \ ssh_file \ ssh_io \ ssh_info \ - ssh_math \ ssh_message \ ssh_no_io \ ssh_sftp \ diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src index bc01c539e0..4a76fd9cd3 100644 --- a/lib/ssh/src/ssh.app.src +++ b/lib/ssh/src/ssh.app.src @@ -24,7 +24,6 @@ ssh_file, ssh_io, ssh_info, - ssh_math, ssh_no_io, ssh_server_key_api, ssh_sftp, diff --git a/lib/ssh/src/ssh_math.erl b/lib/ssh/src/ssh_math.erl deleted file mode 100644 index cace85bc93..0000000000 --- a/lib/ssh/src/ssh_math.erl +++ /dev/null @@ -1,42 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% - -%%% Description: SSH math utilities - --module(ssh_math). - --export([ipow/3]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% INTEGER utils -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% calculate A^B mod M -ipow(A, B, M) when M > 0, B >= 0 -> - crypto:bytes_to_integer(crypto:mod_pow(A, B, M)). - - - - - diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index a0a0217fe2..74e25e1641 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -336,7 +336,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) -> if 1= {Private, Public} = dh_gen_key(G, P, 1024), - K = ssh_math:ipow(E, Private, P), + K = dh_compute_key(G, P, E, Private), Key = get_host_key(Ssh0), H = kex_h(Ssh0, Key, E, Public, K), H_SIG = sign_host_key(Ssh0, Key, H), @@ -361,11 +361,11 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) -> handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F, h_sig = H_SIG}, - #ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) -> + #ssh{keyex_key = {{Private, Public}, {G, P}}} = Ssh0) -> %% client if 1= - K = ssh_math:ipow(F, Private, P), + K = dh_compute_key(G, P, F, Private), H = kex_h(Ssh0, HostKey, Public, F, K), case verify_host_key(Ssh0, HostKey, H, H_SIG) of @@ -426,7 +426,7 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, %% server if 1= - K = ssh_math:ipow(E, Private, P), + K = dh_compute_key(G, P, E, Private), if 1 HostKey = get_host_key(Ssh0), @@ -466,7 +466,7 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, %% client if 1= - K = ssh_math:ipow(F, Private, P), + K = dh_compute_key(G, P, F, Private), if 1 H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K), @@ -1212,6 +1212,11 @@ dh_gen_key(G, P, _) -> {Public, Private} = crypto:generate_key(dh, [P, G]), {crypto:bytes_to_integer(Private), crypto:bytes_to_integer(Public)}. +dh_compute_key(G, P, OthersPublic, MyPrivate) -> + crypto:bytes_to_integer( + crypto:compute_key(dh, OthersPublic, MyPrivate, [P,G]) + ). + trim_tail(Str) -> lists:reverse(trim_head(lists:reverse(Str))). -- cgit v1.2.3 From 481eb2c445eeb350cd370aa4880e7c72c5173cfc Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 3 Aug 2015 18:08:41 +0200 Subject: ssh: added more groups for gex --- lib/ssh/src/ssh_transport.erl | 41 ++++++++++++++++++++++++++++++++++++--- lib/ssh/src/ssh_transport.hrl | 45 ------------------------------------------- 2 files changed, 38 insertions(+), 48 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 74e25e1641..9be8e45aed 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -399,16 +399,23 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, %%% handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, n = NBits, - max = Max}, Ssh0) -> + max = Max}, Ssh0) when Min= %% server - {G,P} = dh_group1(), %% TODO real imp this seems to be a hack?! + {G, P} = dh_gex_group(Min, NBits, Max), {Private, Public} = dh_gen_key(G, P, 1024), {SshPacket, Ssh} = ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), {ok, SshPacket, Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, keyex_info = {Min, Max, NBits} - }}. + }}; +handle_kex_dh_gex_request(_, _) -> + throw({{error,bad_ssh_msg_kex_dh_gex_request}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed, bad values in ssh_msg_kex_dh_gex_request", + language = ""} + }). handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) -> %% client @@ -1205,9 +1212,35 @@ peer_name({Host, _}) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% rfc 2489, ch 6.2 dh_group1() -> {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}. +%%% rfc 3526, ch3 +dh_group14() -> + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}. + +%%% rfc 3526, ch4 +dh_group15() -> + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}. + +%%% rfc 3526, ch5 +dh_group16() -> + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}. + + +%%% First try exact match: +dh_gex_group(_Min, N, _Max) when N==1024 -> dh_group1(); +dh_gex_group(_Min, N, _Max) when N==2048 -> dh_group14(); +dh_gex_group(_Min, N, _Max) when N==3072 -> dh_group15(); +dh_gex_group(_Min, N, _Max) when N==4096 -> dh_group16(); +%%% If not an exact match, select the largest possible: +dh_gex_group(Min, _N, Max) when Min=<4096, 4096= dh_group16(); +dh_gex_group(Min, _N, Max) when Min=<3072, 3072= dh_group15(); +dh_gex_group(Min, _N, Max) when Min=<2048, 2048= dh_group14(); +dh_gex_group(Min, _N, Max) when Min=<1024, 1024= dh_group1(). + + dh_gen_key(G, P, _) -> {Public, Private} = crypto:generate_key(dh, [P, G]), {crypto:bytes_to_integer(Private), crypto:bytes_to_integer(Public)}. @@ -1217,6 +1250,8 @@ dh_compute_key(G, P, OthersPublic, MyPrivate) -> crypto:compute_key(dh, OthersPublic, MyPrivate, [P,G]) ). + + trim_tail(Str) -> lists:reverse(trim_head(lists:reverse(Str))). diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 2faf8a9316..ab59742b96 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -188,49 +188,4 @@ -define(SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, 14). -define(SSH_DISCONNECT_ILLEGAL_USER_NAME, 15). - -%%%---------------------------------------------------------------------- -%%% # DH_14_xxx -%%% Description: Oakley group 14 prime numbers and generator. Used in -%%% diffie-hellman-group1-sha1 key exchange method. -%%%---------------------------------------------------------------------- -%%%---------------------------------------------------------------------- -%%% # DH_14_P -%%% Description: Prime for this group -%%%---------------------------------------------------------------------- - --define(DH_14_P, - <<000,000,000,129,000,255,255,255,255,255,255,255,255,201,015,218, - 162,033,104,194,052,196,198,098,139,128,220,028,209,041,002,078, - 008,138,103,204,116,002,011,190,166,059,019,155,034,081,074,008, - 121,142,052,004,221,239,149,025,179,205,058,067,027,048,043,010, - 109,242,095,020,055,079,225,053,109,109,081,194,069,228,133,181, - 118,098,094,126,198,244,076,066,233,166,055,237,107,011,255,092, - 182,244,006,183,237,238,056,107,251,090,137,159,165,174,159,036, - 017,124,075,031,230,073,040,102,081,236,230,083,129,255,255,255, - 255,255,255,255,255>>). - -%%%---------------------------------------------------------------------- -%%% # DH_14_G -%%% Description: Generator for DH_14_P. -%%%---------------------------------------------------------------------- - --define(DH_14_G, <<0,0,0,1,2>>). - -%%%---------------------------------------------------------------------- -%%% # DH_14_Q -%%% Description: Group order (DH_14_P - 1) / 2. -%%%---------------------------------------------------------------------- - --define(DH_14_Q, - <<000,000,000,128,127,255,255,255,255,255,255,255,228,135,237,081, - 016,180,097,026,098,099,049,069,192,110,014,104,148,129,039,004, - 069,051,230,058,001,005,223,083,029,137,205,145,040,165,004,060, - 199,026,002,110,247,202,140,217,230,157,033,141,152,021,133,054, - 249,047,138,027,167,240,154,182,182,168,225,034,242,066,218,187, - 049,047,063,099,122,038,033,116,211,027,246,181,133,255,174,091, - 122,003,091,246,247,028,053,253,173,068,207,210,215,079,146,008, - 190,037,143,243,036,148,051,040,246,115,041,192,255,255,255,255, - 255,255,255,255>>). - -endif. % -ifdef(ssh_transport). -- cgit v1.2.3 From e6e64a36fbc26e30b97df3bc1105eceef104f318 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Wed, 22 Jul 2015 00:31:53 +0200 Subject: Set ets {write_concurrency, true} on diameter_stats lcnt:inspect/1 recently showed this: lock id #tries collisions [%] time [us] ----- --- ------- --------------- ---------- db_tab diameter_stats 932920 92.9326 330332554 --- lib/diameter/src/base/diameter_stats.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_stats.erl b/lib/diameter/src/base/diameter_stats.erl index 64ea082be0..d2c760317a 100644 --- a/lib/diameter/src/base/diameter_stats.erl +++ b/lib/diameter/src/base/diameter_stats.erl @@ -220,7 +220,10 @@ uptime() -> %% ---------------------------------------------------------- init([]) -> - ets:new(?TABLE, [named_table, ordered_set, public]), + ets:new(?TABLE, [named_table, + ordered_set, + public, + {write_concurrency, true}]), {ok, #state{}}. %% ---------------------------------------------------------- -- cgit v1.2.3 From 4c1e79bf4582e19cd7b4225fb867b4f088895294 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Wed, 8 Jul 2015 13:42:37 +0200 Subject: Truncate potentially large terms passed to diameter_lib:log/4 Last visited in commit 00584303. --- lib/diameter/src/base/diameter_peer_fsm.erl | 7 ++++++- lib/diameter/src/base/diameter_watchdog.erl | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl index 2255d0a76b..a9ee4940a3 100644 --- a/lib/diameter/src/base/diameter_peer_fsm.erl +++ b/lib/diameter/src/base/diameter_peer_fsm.erl @@ -319,7 +319,7 @@ handle_info(T, #state{} = State) -> ?LOG(stop, Reason), {stop, {shutdown, Reason}, State}; stop -> - ?LOG(stop, T), + ?LOG(stop, truncate(T)), {stop, {shutdown, T}, State} catch exit: {diameter_codec, encode, T} = Reason -> @@ -355,6 +355,11 @@ code_change(_, State, _) -> %% --------------------------------------------------------------------------- %% --------------------------------------------------------------------------- +truncate({'DOWN' = T, _, process, Pid, _}) -> + {T, Pid}; +truncate(T) -> + T. + putr(Key, Val) -> put({?MODULE, Key}, Val). diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index de9c4bca33..55c303dec2 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -245,11 +245,16 @@ handle_info(T, #watchdog{} = State) -> event(T, State, S), %% before 'watchdog' {noreply, S}; stop -> - ?LOG(stop, T), + ?LOG(stop, truncate(T)), event(T, State, State#watchdog{status = down}), {stop, {shutdown, T}, State} end. +truncate({'DOWN' = T, _, process, Pid, _}) -> + {T, Pid}; +truncate(T) -> + T. + close({'DOWN', _, process, TPid, {shutdown, Reason}}, #watchdog{transport = TPid, parent = Pid}) -> -- cgit v1.2.3 From 80420620b67216b67e90affc5fe35505207254a3 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Wed, 8 Jul 2015 15:07:15 +0200 Subject: Correct inaccurate doc The warning report was removed in commit 00584303. --- lib/diameter/doc/src/diameter.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index ea175a58b8..cb628f9529 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -1231,9 +1231,7 @@ is not the length of the message in question, as received over the transport interface documented in &man_transport;.

-If exit then a warning report is emitted and the parent of the -transport process in question exits, which causes the transport -process itself to exit as described in &man_transport;. +If exit then the transport process in question exits. If handle then the message is processed as usual, a resulting &app_handle_request; or &app_handle_answer; callback (if one takes place) indicating the 5015 error (DIAMETER_INVALID_MESSAGE_LENGTH). -- cgit v1.2.3 From abd6c7494f973eb91c6a582f3370e9896d28992b Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Mon, 29 Jun 2015 09:09:13 +0200 Subject: Don't flag AVP as missing as a consequence of decode error The decode of an incoming Diameter message uses the record representation to determine whether or not an AVP has been received with the expected arity, the number of AVPs in each field following decode being compared with the arity specified in the message grammar. The problem with this is that decode failure isn't reflected in the record representation, so that an AVP can be appended to the errors field of a diameter_packet record despite an entry for the same AVP already existing. This isn't a fault as much as a misleading error indication, but now only append AVPs that aren't already represented. --- lib/diameter/include/diameter_gen.hrl | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl index e8ffe7f92c..0b36389088 100644 --- a/lib/diameter/include/diameter_gen.hrl +++ b/lib/diameter/include/diameter_gen.hrl @@ -185,9 +185,10 @@ decode_avps(Name, Recs) -> = lists:foldl(fun(T,A) -> decode(Name, T, A) end, {[], {newrec(Name), []}}, Recs), - {Rec, Avps, Failed ++ missing(Rec, Name)}. -%% Append 5005 errors so that a 5014 for the same AVP will take -%% precedence in a Result-Code/Failed-AVP setting. + {Rec, Avps, Failed ++ missing(Rec, Name, Failed)}. +%% Append 5005 errors so that errors are reported in the order +%% encountered. Failed-AVP should typically contain the first +%% encountered error accordg to the RFC. newrec(Name) -> '#new-'(name2rec(Name)). @@ -202,10 +203,18 @@ newrec(Name) -> %% Vendor-Id if applicable. The value field of the missing AVP %% should be of correct minimum length and contain zeroes. +missing(Rec, Name, Failed) -> + [{5005, A} || #diameter_avp{code = MC, vendor_id = MV} = A + <- missing(Rec, Name), + lists:all(fun({_, #diameter_avp{code = C, vendor_id = V}}) -> + MC /= C orelse MV /= V + end, + Failed)]. + missing(Rec, Name) -> - [{5005, empty_avp(F)} || F <- '#info-'(element(1, Rec), fields), - A <- [avp_arity(Name, F)], - false <- [have_arity(A, '#get-'(F, Rec))]]. + [empty_avp(F) || F <- '#info-'(element(1, Rec), fields), + A <- [avp_arity(Name, F)], + not have_arity(A, '#get-'(F, Rec))]. %% Maximum arities have already been checked in building the record. -- cgit v1.2.3 From 16aaa29b7ce40596520d563b6f4a8e0aeba7b085 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 7 Jul 2015 09:58:21 +0200 Subject: Don't traverse errors list unnecessarily when detecting missing AVPs Since the list can potentially be long. --- lib/diameter/include/diameter_gen.hrl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl index 0b36389088..79b8e6ecde 100644 --- a/lib/diameter/include/diameter_gen.hrl +++ b/lib/diameter/include/diameter_gen.hrl @@ -201,20 +201,19 @@ newrec(Name) -> %% Failed-AVP AVP SHOULD be included in the message. The Failed-AVP %% AVP MUST contain an example of the missing AVP complete with the %% Vendor-Id if applicable. The value field of the missing AVP -%% should be of correct minimum length and contain zeroes. +%% should be of correct minimum length and contain zeros. missing(Rec, Name, Failed) -> - [{5005, A} || #diameter_avp{code = MC, vendor_id = MV} = A - <- missing(Rec, Name), - lists:all(fun({_, #diameter_avp{code = C, vendor_id = V}}) -> - MC /= C orelse MV /= V - end, - Failed)]. - -missing(Rec, Name) -> - [empty_avp(F) || F <- '#info-'(element(1, Rec), fields), - A <- [avp_arity(Name, F)], - not have_arity(A, '#get-'(F, Rec))]. + Avps = lists:foldl(fun({_, #diameter_avp{code = C, vendor_id = V}}, A) -> + sets:add_element({C,V}, A) + end, + sets:new(), + Failed), + [{5005, A} || F <- '#info-'(element(1, Rec), fields), + not have_arity(avp_arity(Name, F), '#get-'(F, Rec)), + #diameter_avp{code = C, vendor_id = V} + = A <- [empty_avp(F)], + not sets:is_element({C,V}, Avps)]. %% Maximum arities have already been checked in building the record. -- cgit v1.2.3 From 9ab5d8afedc6d2f56997276e3f016ec1c6dac6a5 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 7 Jul 2015 13:34:57 +0200 Subject: Don't compute AVP list length unnecessarily at AVP decode This has had a hugely negative impact on performance when decoding messages containing many AVP: each decode of an AVP having variable arity computed the length of the list of previously decoded AVPs when checking that the allowed arity was not exceeded, even if the allowed arity was infinite, making for O(n^2) cost. Here are some execution times, for diameter_codec:decode/2 on a representative message with n integer AVPs in the Common application (on the host at hand): Before After ------- --------- n = 1K 5 ms 2 ms n = 10K 500 ms 25 ms n = 100K 75 sec 225 ms n = 1M 2.6 sec Note the nearly linear increase following the change. Remove the dire documentation warning for incoming_maxlen as a consequence. It can still be useful to set, but not doing so won't have the same consequences as previously. --- lib/diameter/doc/src/diameter.xml | 8 -------- lib/diameter/include/diameter_gen.hrl | 32 ++++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index cb628f9529..854bc5b432 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -794,14 +794,6 @@ Messages larger than the specified number of bytes are discarded.

Defaults to 16777215, the maximum value of the 24-bit Message Length field in a Diameter Header.

- -

-This option should be set to as low a value as is sufficient for the -Diameter applications and peers in question, since decoding incoming -messages from a malicious peer can otherwise generate significant -load.

-
- {restrict_connections, false diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl index 79b8e6ecde..ebe9e6363d 100644 --- a/lib/diameter/include/diameter_gen.hrl +++ b/lib/diameter/include/diameter_gen.hrl @@ -210,18 +210,27 @@ missing(Rec, Name, Failed) -> sets:new(), Failed), [{5005, A} || F <- '#info-'(element(1, Rec), fields), - not have_arity(avp_arity(Name, F), '#get-'(F, Rec)), + not has_arity(avp_arity(Name, F), '#get-'(F, Rec)), #diameter_avp{code = C, vendor_id = V} = A <- [empty_avp(F)], not sets:is_element({C,V}, Avps)]. %% Maximum arities have already been checked in building the record. -have_arity({Min, _}, L) -> - Min =< length(L); -have_arity(N, V) -> +has_arity({Min, _}, L) -> + has_prefix(Min, L); +has_arity(N, V) -> N /= 1 orelse V /= undefined. +%% Compare a non-negative integer and the length of a list without +%% computing the length. +has_prefix(0, _) -> + true; +has_prefix(_, []) -> + false; +has_prefix(N, L) -> + has_prefix(N-1, tl(L)). + %% empty_avp/1 empty_avp(Name) -> @@ -589,14 +598,17 @@ pack(undefined, 1, FieldName, Avp, Acc) -> %% AVP MUST be included and contain a copy of the first instance of %% the offending AVP that exceeded the maximum number of occurrences %% + pack(_, 1, _, Avp, {Rec, Failed}) -> {Rec, [{5009, Avp} | Failed]}; -pack(L, {_, Max}, _, Avp, {Rec, Failed}) - when length(L) == Max -> - {Rec, [{5009, Avp} | Failed]}; - -pack(L, _, FieldName, Avp, Acc) -> - p(FieldName, fun(V) -> [V|L] end, Avp, Acc). +pack(L, {_, Max}, FieldName, Avp, Acc) -> + case '*' /= Max andalso has_prefix(Max, L) of + true -> + {Rec, Failed} = Acc, + {Rec, [{5009, Avp} | Failed]}; + false -> + p(FieldName, fun(V) -> [V|L] end, Avp, Acc) + end. %% p/4 -- cgit v1.2.3 From 1a90f86927dba2f22cff6e3703c76415da05d667 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Fri, 10 Jul 2015 16:44:03 +0200 Subject: Replace calls to module inet_parse to equivalents in inet Commits b563c796 (R16B) and 0fad6449 (R16B02) added parse_address/1 and ntoa/1 to module inet, providing documented alternatives to address/1 and ntoa/1 in the undocumented (save comments in inet(3)) inet_parse. --- lib/diameter/src/base/diameter_lib.erl | 2 +- lib/diameter/src/base/diameter_peer.erl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl index 3f327f3653..b9b3e21788 100644 --- a/lib/diameter/src/base/diameter_lib.erl +++ b/lib/diameter/src/base/diameter_lib.erl @@ -321,7 +321,7 @@ ip(T) %% Or not: convert from '.'/':'-separated decimal/hex. ip(Addr) -> - {ok, A} = inet_parse:address(Addr), %% documented in inet(3) + {ok, A} = inet:parse_address(Addr), A. %% --------------------------------------------------------------------------- diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl index 89b63c8a92..95c0c65029 100644 --- a/lib/diameter/src/base/diameter_peer.erl +++ b/lib/diameter/src/base/diameter_peer.erl @@ -201,10 +201,10 @@ match1(Addr, Match) -> match(Addr, {ok, A}, _) -> Addr == A; match(Addr, {error, _}, RE) -> - match == re:run(inet_parse:ntoa(Addr), RE, [{capture, none}]). + match == re:run(inet:ntoa(Addr), RE, [{capture, none}]). addr([_|_] = A) -> - inet_parse:address(A); + inet:parse_address(A); addr(A) -> {ok, A}. -- cgit v1.2.3 From f60bc6ad8852e7d97d509ced084c137f55bd4aad Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Fri, 10 Jul 2015 16:36:57 +0200 Subject: Match allowable peer addresses case insensitively Both diameter_tcp and diameter_sctp can be configured with one or more IP addresses from which connections should be accepted (an 'accept' tuple), specified either as a tuple-valued address or as a regular expression. In the latter case, peer addresses are mapped to string using inet:ntoa/1 and the result matched against the regexp. Since (ipv6) addresses are case insensitive, this should also be the case with the match, but was not. --- lib/diameter/src/base/diameter_peer.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl index 95c0c65029..96b6d404e0 100644 --- a/lib/diameter/src/base/diameter_peer.erl +++ b/lib/diameter/src/base/diameter_peer.erl @@ -201,7 +201,7 @@ match1(Addr, Match) -> match(Addr, {ok, A}, _) -> Addr == A; match(Addr, {error, _}, RE) -> - match == re:run(inet:ntoa(Addr), RE, [{capture, none}]). + match == re:run(inet:ntoa(Addr), RE, [{capture, none}, caseless]). addr([_|_] = A) -> inet:parse_address(A); -- cgit v1.2.3 From f8e1d4c5fe8bc67cac092e5cb45457d223172f2a Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Wed, 24 Jun 2015 13:45:19 +0200 Subject: Fix relay encode of decoded diameter_avp lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit c74b593a fixed the problem that a decoded deep diameter_avp list couldn't be encoded, but did so in the wrong way: there's no need to reencode component AVPs since the Grouped AVP itself already contains the encoded binary. The blunder caused diameter_codec:pack_avp/1 to fail if the first element of the AVP list to be encoded was itself a list. Thanks to Andrzej Trawiński for reporting the problem. --- lib/diameter/src/base/diameter_codec.erl | 21 +++++++++----- lib/diameter/test/diameter_relay_SUITE.erl | 44 +++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl index bf2fe8e7ca..2ad971a422 100644 --- a/lib/diameter/src/base/diameter_codec.erl +++ b/lib/diameter/src/base/diameter_codec.erl @@ -655,16 +655,23 @@ split_data(Bin, Len) -> %% The normal case here is data as an #diameter_avp{} list or an %% iolist, which are the cases that generated codec modules use. The -%% other case is as a convenience in the relay case in which the +%% other cases are a convenience in the relay case in which the %% dictionary doesn't know about specific AVP's. -%% Grouped AVP whose components need packing ... -pack_avp([#diameter_avp{} = A | Avps]) -> - pack_avp(A#diameter_avp{data = Avps}); -pack_avp(#diameter_avp{data = [#diameter_avp{} | _] = Avps} = A) -> - pack_avp(A#diameter_avp{data = encode_avps(Avps)}); +%% Decoded Grouped AVP with decoded components: ignore components +%% since they're already encoded in the Grouped AVP. +pack_avp([#diameter_avp{} = Grouped | _Components]) -> + pack_avp(Grouped); -%% ... data as a type/value tuple ... +%% Grouped AVP whose components need packing. It's intentional that +%% this isn't equivalent to [Grouped | Components]: here the +%% components need to be encoded before wrapping with the Grouped AVP, +%% and the list is flat, nesting being accomplished in the data +%% fields. +pack_avp(#diameter_avp{data = [#diameter_avp{} | _] = Components} = Grouped) -> + pack_avp(Grouped#diameter_avp{data = encode_avps(Components)}); + +%% Data as a type/value tuple ... pack_avp(#diameter_avp{data = {Type, Value}} = A) when is_atom(Type) -> pack_avp(A#diameter_avp{data = diameter_types:Type(encode, Value)}); diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl index 7142239bbb..5f7837e879 100644 --- a/lib/diameter/test/diameter_relay_SUITE.erl +++ b/lib/diameter/test/diameter_relay_SUITE.erl @@ -333,13 +333,39 @@ realm(Host) -> call(Server) -> Realm = realm(Server), + %% Include some arbitrary AVPs to exercise encode/decode, that + %% are received back in the STA. + Avps = [#diameter_avp{code = 111, + data = [#diameter_avp{code = 222, + data = <<222:24>>}, + #diameter_avp{code = 333, + data = <<333:16>>}]}, + #diameter_avp{code = 444, + data = <<444:24>>}, + #diameter_avp{code = 555, + data = [#diameter_avp{code = 666, + data = [#diameter_avp + {code = 777, + data = <<7>>}]}, + #diameter_avp{code = 888, + data = <<8>>}, + #diameter_avp{code = 999, + data = <<9>>}]}], + Req = ['STR', {'Destination-Realm', Realm}, {'Destination-Host', [Server]}, {'Termination-Cause', ?LOGOUT}, - {'Auth-Application-Id', ?APP_ID}], + {'Auth-Application-Id', ?APP_ID}, + {'AVP', Avps}], + #diameter_base_STA{'Result-Code' = ?SUCCESS, 'Origin-Host' = Server, - 'Origin-Realm' = Realm} + 'Origin-Realm' = Realm, + %% Unknown AVPs can't be decoded as Grouped since + %% types aren't known. + 'AVP' = [#diameter_avp{code = 111}, + #diameter_avp{code = 444}, + #diameter_avp{code = 555}]} = call(Req, [{filter, realm}]). call(Req, Opts) -> @@ -433,9 +459,18 @@ request(_Pkt, #diameter_caps{origin_host = {OH, _}}) request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId, 'Origin-Host' = Host, 'Origin-Realm' = Realm, - 'Route-Record' = Route}}, + 'Route-Record' = Route, + 'AVP' = Avps}}, #diameter_caps{origin_host = {OH, _}, origin_realm = {OR, _}}) -> + + %% Payloads of unknown AVPs aren't decoded, so we don't know that + %% some types here are Grouped. + [#diameter_avp{code = 111, vendor_id = undefined}, + #diameter_avp{code = 444, vendor_id = undefined, data = <<444:24>>}, + #diameter_avp{code = 555, vendor_id = undefined}] + = Avps, + %% The request should have the Origin-Host/Realm of the original %% sender. R = realm(?CLIENT), @@ -446,4 +481,5 @@ request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId, {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS, 'Session-Id' = SId, 'Origin-Host' = OH, - 'Origin-Realm' = OR}}. + 'Origin-Realm' = OR, + 'AVP' = Avps}}. -- cgit v1.2.3 From 84004d4f99271e8324f7d1e3fb8a3cd68109d456 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 4 Aug 2015 23:51:45 +0200 Subject: Remove unnecessary redefinition of erlang:max/2 The function already operates on arbitrary terms. --- lib/diameter/src/info/diameter_info.erl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/info/diameter_info.erl b/lib/diameter/src/info/diameter_info.erl index 10972f3231..5ecce2206f 100644 --- a/lib/diameter/src/info/diameter_info.erl +++ b/lib/diameter/src/info/diameter_info.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2014. All Rights Reserved. +%% Copyright Ericsson AB 2010-2015. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -51,8 +51,6 @@ p/1, p/3]). --compile({no_auto_import,[max/2]}). - -export([collect/2]). -define(LONG_TIMEOUT, 30000). @@ -683,9 +681,6 @@ pt(T) -> recsplit(SFun, Rec) -> fun(Fs,Vs) -> SFun(element(1, Rec), Fs, Vs) end. -max(A, B) -> - if A > B -> A; true -> B end. - keyfetch(Key, List) -> {Key,V} = lists:keyfind(Key, 1, List), V. -- cgit v1.2.3 From 82c15a915981842a7013375d2e62d00d775078e1 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Fri, 19 Jun 2015 15:12:19 +0200 Subject: Log discarded answers To diameter_lib:log/4, which was last motivated in commit 39acfdb0. --- lib/diameter/src/base/diameter_traffic.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index eb4bbae931..230a05fa11 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -261,7 +261,8 @@ recv(false, #request{ref = Ref, handler = Pid} = Req, _, Pkt, Dict0, _) -> %% any others are discarded. %% ... or not. -recv(false, false, TPid, _, _, _) -> +recv(false, false, TPid, Pkt, _, _) -> + ?LOG(discarded, Pkt#diameter_packet.header), incr(TPid, {{unknown, 0}, recv, discarded}), ok. -- cgit v1.2.3 From 780ea64fff1bae552510ed419ec2bb011923a5cc Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sun, 21 Jun 2015 09:55:17 +0200 Subject: Fix start order of alternate transports A transport configured with diameter:add_transport/2 can be passed multiple transport_module/transport_config tuples in order to specify alternate configuration, modules being attempted in order until one succeeds. This is primarily for the connecting case, to allow a transport to be configured to first attempt connection over SCTP, and then TCP in case SCTP fails, with configuration like that documented: {transport_module, diameter_sctp}, {transport_config, [...], 5000}, {transport_module, diameter_tcp}, {transport_config, [...]} If the options are the same in both cases, another possibility would be configuration like this, which attaches the same transport_config to both modules: {transport_module, diameter_sctp}, {transport_module, diameter_tcp}, {transport_config, [...], 5000}, However, in this case the start order was reversed relative to the documented order: first tcp, then sctp. This commit restores the intended order. --- lib/diameter/src/base/diameter_peer.erl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl index 89b63c8a92..a814e52f29 100644 --- a/lib/diameter/src/base/diameter_peer.erl +++ b/lib/diameter/src/base/diameter_peer.erl @@ -121,7 +121,7 @@ pair([{transport_module, M} | Rest], Mods, Acc) -> pair([{transport_config = T, C} | Rest], Mods, Acc) -> pair([{T, C, ?DEFAULT_TTMO} | Rest], Mods, Acc); pair([{transport_config, C, Tmo} | Rest], Mods, Acc) -> - pair(Rest, [], acc({Mods, C, Tmo}, Acc)); + pair(Rest, [], acc({lists:reverse(Mods), C, Tmo}, Acc)); pair([_ | Rest], Mods, Acc) -> pair(Rest, Mods, Acc); @@ -130,13 +130,16 @@ pair([_ | Rest], Mods, Acc) -> pair([], [], []) -> [{[?DEFAULT_TMOD], ?DEFAULT_TCFG, ?DEFAULT_TTMO}]; -%% One transport_module, one transport_config. -pair([], [M], [{[], Cfg, Tmo}]) -> - [{[M], Cfg, Tmo}]; +%% One transport_module, one transport_config: ignore option order. +%% That is, interpret [{transport_config, _}, {transport_module, _}] +%% as if the order was reversed, not as config with default module and +%% module with default config. +pair([], [_] = Mods, [{[], Cfg, Tmo}]) -> + [{Mods, Cfg, Tmo}]; %% Trailing transport_module: default transport_config. pair([], [_|_] = Mods, Acc) -> - lists:reverse(acc({Mods, ?DEFAULT_TCFG, ?DEFAULT_TTMO}, Acc)); + pair([{transport_config, ?DEFAULT_TCFG}], Mods, Acc); pair([], [], Acc) -> lists:reverse(def(Acc)). -- cgit v1.2.3 From 5a339bcb0e073afae4b403b29d64870cdc8ea28b Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 4 Aug 2015 22:38:20 +0200 Subject: Update appup for 17.5.6.3 OTP-12871: 5005 decode OTP-12791: decode performance OTP-12879: grouped decode OTP-12902: caseless address match OTP-12912: fewer timers OTP-12926: pre-18 time diameter_lib must be loaded after modules calling its time-related functions (that have been removed). --- lib/diameter/src/diameter.appup.src | 96 +++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index b89859ed24..adb3f960ff 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -36,43 +36,45 @@ {"1.4.4", [{restart_application, diameter}]}, {"1.5", [{restart_application, diameter}]}, %% R16B03 {"1.6", [{restart_application, diameter}]}, %% 17.0 - {"1.7", [{restart_application, diameter}]}, %% 17.[12] - {<<"^1\\.(7\\.1|8)$">>, %% 17.[34] - [{load_module, diameter_lib}, - {load_module, diameter_peer}, - {load_module, diameter_reg}, - {load_module, diameter_session}, - {load_module, diameter_stats}, - {load_module, diameter_sync}, - {load_module, diameter_capx}, - {load_module, diameter_codec}, - {load_module, diameter_types}, + {<<"1\\.(7(\\.1)?|8)$">>, %% 17.[134] + [{restart_application, diameter}]}, + {<<"^1.9(\\.1)?$">>, %% 17.5(.3)? + [{load_module, diameter_codec}, {load_module, diameter_traffic}, - {load_module, diameter_service}, + {load_module, diameter_sctp}, {load_module, diameter_peer_fsm}, {load_module, diameter_watchdog}, - {load_module, diameter_tcp}, - {load_module, diameter_sctp}, + {load_module, diameter_stats}, {load_module, diameter_config}, - {load_module, diameter}, + {load_module, diameter_lib}, + {load_module, diameter_peer}, + {load_module, diameter_reg}, + {load_module, diameter_service}, + {load_module, diameter_session}, + {load_module, diameter_sync}, {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_base_accounting}, - {load_module, diameter_gen_relay}, - {update, diameter_transport_sup, supervisor}, - {update, diameter_service_sup, supervisor}, - {update, diameter_sup, supervisor}]}, - {"1.9", [{load_module, diameter_codec}, %% 17.5 + {load_module, diameter_gen_relay}]}, + {"1.9.2", [{load_module, diameter_peer_fsm}, %% 17.5.5 + {load_module, diameter_watchdog}, + {load_module, diameter_stats}, + {load_module, diameter_config}, + {load_module, diameter_codec}, + {load_module, diameter_lib}, + {load_module, diameter_peer}, + {load_module, diameter_reg}, + {load_module, diameter_service}, + {load_module, diameter_session}, + {load_module, diameter_sync}, {load_module, diameter_traffic}, {load_module, diameter_sctp}, {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_base_accounting}, - {load_module, diameter_gen_relay}]}, - {"1.9.1", [{load_module, diameter_traffic}, %% 17.5.3 - {load_module, diameter_sctp}]} + {load_module, diameter_gen_relay}]} ], [ {"0.9", [{restart_application, diameter}]}, @@ -91,42 +93,44 @@ {"1.4.4", [{restart_application, diameter}]}, {"1.5", [{restart_application, diameter}]}, {"1.6", [{restart_application, diameter}]}, - {"1.7", [{restart_application, diameter}]}, - {<<"^1\\.(7\\.1|8)$">>, - [{update, diameter_sup, supervisor}, - {update, diameter_service_sup, supervisor}, - {update, diameter_transport_sup, supervisor}, - {load_module, diameter_gen_relay}, + {<<"1\\.(7(\\.1)?|8)$">>, + [{restart_application, diameter}]}, + {<<"^1.9(\\.1)?$">>, + [{load_module, diameter_gen_relay}, {load_module, diameter_gen_base_accounting}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc6733}, - {load_module, diameter}, - {load_module, diameter_config}, - {load_module, diameter_sctp}, - {load_module, diameter_tcp}, - {load_module, diameter_watchdog}, - {load_module, diameter_peer_fsm}, - {load_module, diameter_service}, - {load_module, diameter_traffic}, - {load_module, diameter_types}, - {load_module, diameter_codec}, - {load_module, diameter_capx}, {load_module, diameter_sync}, - {load_module, diameter_stats}, {load_module, diameter_session}, + {load_module, diameter_service}, {load_module, diameter_reg}, {load_module, diameter_peer}, - {load_module, diameter_lib}]}, - {"1.9", [{load_module, diameter_gen_relay}, + {load_module, diameter_lib}, + {load_module, diameter_config}, + {load_module, diameter_stats}, + {load_module, diameter_watchdog}, + {load_module, diameter_peer_fsm}, + {load_module, diameter_sctp}, + {load_module, diameter_traffic}, + {load_module, diameter_codec}]}, + {"1.9.2", [{load_module, diameter_gen_relay}, {load_module, diameter_gen_base_accounting}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_sctp}, {load_module, diameter_traffic}, - {load_module, diameter_codec}]}, - {"1.9.1", [{load_module, diameter_sctp}, - {load_module, diameter_traffic}]} + {load_module, diameter_sync}, + {load_module, diameter_session}, + {load_module, diameter_service}, + {load_module, diameter_reg}, + {load_module, diameter_peer}, + {load_module, diameter_lib}, + {load_module, diameter_codec}, + {load_module, diameter_config}, + {load_module, diameter_stats}, + {load_module, diameter_watchdog}, + {load_module, diameter_peer_fsm}]} ] }. -- cgit v1.2.3 From d6e8e9186996ac75ffa6f00a50f407d94b0e8181 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 4 Aug 2015 23:00:38 +0200 Subject: vsn -> 1.9.2.1 --- lib/diameter/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk index c278e74dca..a16b8d712c 100644 --- a/lib/diameter/vsn.mk +++ b/lib/diameter/vsn.mk @@ -16,5 +16,5 @@ # %CopyrightEnd% APPLICATION = diameter -DIAMETER_VSN = 1.9.2 +DIAMETER_VSN = 1.9.2.1 APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN) -- cgit v1.2.3 From 9c0f2f2ce3ed040b3963d5b00cad0276c276d590 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 4 Aug 2015 10:14:44 +0200 Subject: Remove use of monotonic time in pre-18 code This has been seen to be a bottleneck at high load: each undef results in a loop out to the code server. Originally implemented as suggested in the erts user's guide, in commits e6d19a18 and d4386254. --- lib/diameter/src/base/diameter_lib.erl | 40 +++++------------------------ lib/diameter/src/base/diameter_watchdog.erl | 1 - 2 files changed, 6 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl index 3f327f3653..6a94e32b0e 100644 --- a/lib/diameter/src/base/diameter_lib.erl +++ b/lib/diameter/src/base/diameter_lib.erl @@ -102,8 +102,7 @@ fmt(T) -> %% --------------------------------------------------------------------------- -type timestamp() :: {non_neg_integer(), 0..999999, 0..999999}. --type now() :: integer() %% monotonic time - | timestamp(). +-type now() :: timestamp(). -spec now() -> now(). @@ -112,11 +111,7 @@ fmt(T) -> %% otherwise. now() -> - try - erlang:monotonic_time() - catch - error: undef -> erlang:now() - end. + erlang:now(). %% --------------------------------------------------------------------------- %% # timestamp/1 @@ -126,15 +121,7 @@ now() -> -> timestamp(). timestamp({_,_,_} = T) -> %% erlang:now() - T; - -timestamp(MonoT) -> %% monotonic time - MicroSecs = monotonic_to_microseconds(MonoT + erlang:time_offset()), - Secs = MicroSecs div 1000000, - {Secs div 1000000, Secs rem 1000000, MicroSecs rem 1000000}. - -monotonic_to_microseconds(MonoT) -> - erlang:convert_time_unit(MonoT, native, micro_seconds). + T. %% --------------------------------------------------------------------------- %% # now_diff/1 @@ -162,10 +149,7 @@ now_diff(Time) -> when MicroSecs :: non_neg_integer(). micro_diff({_,_,_} = T0) -> - timer:now_diff(erlang:now(), T0); - -micro_diff(T0) -> %% monotonic time - monotonic_to_microseconds(erlang:monotonic_time() - T0). + timer:now_diff(erlang:now(), T0). %% --------------------------------------------------------------------------- %% # micro_diff/2 @@ -175,12 +159,8 @@ micro_diff(T0) -> %% monotonic time -> MicroSecs when MicroSecs :: non_neg_integer(). -micro_diff(T1, T0) - when is_integer(T1), is_integer(T0) -> %% monotonic time - monotonic_to_microseconds(T1 - T0); - micro_diff(T1, T0) -> %% at least one erlang:now() - timer:now_diff(timestamp(T1), timestamp(T0)). + timer:now_diff(T1, T0). %% --------------------------------------------------------------------------- %% # time/1 @@ -219,15 +199,7 @@ time(Micro) -> %% elapsed time seed() -> T = now(), - {timestamp(T), seed(T)}. - -%% seed/1 - -seed({_,_,_} = T) -> - T; - -seed(T) -> %% monotonic time - {erlang:phash2(node()), T, erlang:unique_integer()}. + {T, T}. %% --------------------------------------------------------------------------- %% # eval/1 diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index 0607c72818..66781d7b06 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -66,7 +66,6 @@ parent = self() :: pid(), %% service process transport :: pid() | undefined, %% peer_fsm process tref :: reference() %% reference for current watchdog timer - | integer() %% monotonic time | tuple() %% now() | undefined, dictionary :: module(), %% common dictionary -- cgit v1.2.3 From 96d63dca845e18f86488db9d8dfb33eb76ad0467 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 4 Aug 2015 23:46:29 +0200 Subject: Simplify time manipulation By doing away with more wrapping that the parent commit started to remove. --- lib/diameter/src/base/diameter_config.erl | 3 +- lib/diameter/src/base/diameter_lib.erl | 73 ++------------------------ lib/diameter/src/base/diameter_peer.erl | 3 -- lib/diameter/src/base/diameter_reg.erl | 3 +- lib/diameter/src/base/diameter_service.erl | 5 +- lib/diameter/src/base/diameter_session.erl | 4 +- lib/diameter/src/base/diameter_stats.erl | 3 -- lib/diameter/src/base/diameter_sync.erl | 3 -- lib/diameter/src/base/diameter_watchdog.erl | 7 ++- lib/diameter/src/transport/diameter_sctp.erl | 3 -- lib/diameter/test/diameter_codec_test.erl | 4 +- lib/diameter/test/diameter_config_SUITE.erl | 2 +- lib/diameter/test/diameter_ct.erl | 4 +- lib/diameter/test/diameter_event_SUITE.erl | 6 +-- lib/diameter/test/diameter_examples_SUITE.erl | 8 +-- lib/diameter/test/diameter_gen_sctp_SUITE.erl | 10 ++-- lib/diameter/test/diameter_traffic_SUITE.erl | 8 ++- lib/diameter/test/diameter_transport_SUITE.erl | 6 +-- lib/diameter/test/diameter_util.erl | 19 +------ 19 files changed, 36 insertions(+), 138 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl index 8ac3b9d6ca..89b26707ad 100644 --- a/lib/diameter/src/base/diameter_config.erl +++ b/lib/diameter/src/base/diameter_config.erl @@ -37,8 +37,7 @@ -module(diameter_config). -behaviour(gen_server). --compile({no_auto_import, [monitor/2, now/0]}). --import(diameter_lib, [now/0]). +-compile({no_auto_import, [monitor/2]}). -export([start_service/2, stop_service/1, diff --git a/lib/diameter/src/base/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl index 6a94e32b0e..e8009c6a14 100644 --- a/lib/diameter/src/base/diameter_lib.erl +++ b/lib/diameter/src/base/diameter_lib.erl @@ -18,18 +18,12 @@ %% -module(diameter_lib). --compile({no_auto_import, [now/0]}). -export([info_report/2, error_report/2, warning_report/2, - now/0, - timestamp/1, now_diff/1, - micro_diff/1, - micro_diff/2, time/1, - seed/0, eval/1, eval_name/1, get_stacktrace/0, @@ -97,37 +91,11 @@ fmt(T) -> "p" end. -%% --------------------------------------------------------------------------- -%% # now/0 -%% --------------------------------------------------------------------------- - --type timestamp() :: {non_neg_integer(), 0..999999, 0..999999}. --type now() :: timestamp(). - --spec now() - -> now(). - -%% Use monotonic time if it exists, fall back to erlang:now() -%% otherwise. - -now() -> - erlang:now(). - -%% --------------------------------------------------------------------------- -%% # timestamp/1 -%% --------------------------------------------------------------------------- - --spec timestamp(NowT :: now()) - -> timestamp(). - -timestamp({_,_,_} = T) -> %% erlang:now() - T. - %% --------------------------------------------------------------------------- %% # now_diff/1 %% --------------------------------------------------------------------------- --spec now_diff(NowT :: now()) +-spec now_diff(NowT :: erlang:timestamp()) -> {Hours, Mins, Secs, MicroSecs} when Hours :: non_neg_integer(), Mins :: 0..59, @@ -138,29 +106,7 @@ timestamp({_,_,_} = T) -> %% erlang:now() %% instead of as integer microseconds. now_diff(Time) -> - time(micro_diff(Time)). - -%% --------------------------------------------------------------------------- -%% # micro_diff/1 -%% --------------------------------------------------------------------------- - --spec micro_diff(NowT :: now()) - -> MicroSecs - when MicroSecs :: non_neg_integer(). - -micro_diff({_,_,_} = T0) -> - timer:now_diff(erlang:now(), T0). - -%% --------------------------------------------------------------------------- -%% # micro_diff/2 -%% --------------------------------------------------------------------------- - --spec micro_diff(T1 :: now(), T0 :: now()) - -> MicroSecs - when MicroSecs :: non_neg_integer(). - -micro_diff(T1, T0) -> %% at least one erlang:now() - timer:now_diff(T1, T0). + time(timer:now_diff(now(), Time)). %% --------------------------------------------------------------------------- %% # time/1 @@ -170,7 +116,7 @@ micro_diff(T1, T0) -> %% at least one erlang:now() -spec time(NowT | Diff) -> {Hours, Mins, Secs, MicroSecs} - when NowT :: timestamp(), + when NowT :: erlang:timestamp(), Diff :: non_neg_integer(), Hours :: non_neg_integer(), Mins :: 0..59, @@ -188,19 +134,6 @@ time(Micro) -> %% elapsed time S = Seconds rem 60, {H, M, S, Micro rem 1000000}. -%% --------------------------------------------------------------------------- -%% # seed/0 -%% --------------------------------------------------------------------------- - --spec seed() - -> {timestamp(), {integer(), integer(), integer()}}. - -%% Return an argument for random:seed/1. - -seed() -> - T = now(), - {T, T}. - %% --------------------------------------------------------------------------- %% # eval/1 %% diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl index 89b63c8a92..356383dbab 100644 --- a/lib/diameter/src/base/diameter_peer.erl +++ b/lib/diameter/src/base/diameter_peer.erl @@ -20,9 +20,6 @@ -module(diameter_peer). -behaviour(gen_server). --compile({no_auto_import, [now/0]}). --import(diameter_lib, [now/0]). - %% Interface towards transport modules ... -export([recv/2, up/1, diff --git a/lib/diameter/src/base/diameter_reg.erl b/lib/diameter/src/base/diameter_reg.erl index f785777874..6bb4710e63 100644 --- a/lib/diameter/src/base/diameter_reg.erl +++ b/lib/diameter/src/base/diameter_reg.erl @@ -24,8 +24,7 @@ -module(diameter_reg). -behaviour(gen_server). --compile({no_auto_import, [monitor/2, now/0]}). --import(diameter_lib, [now/0]). +-compile({no_auto_import, [monitor/2]}). -export([add/1, add_new/1, diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 86e744dfbe..a31cef2c8c 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -24,9 +24,6 @@ -module(diameter_service). -behaviour(gen_server). --compile({no_auto_import, [now/0]}). --import(diameter_lib, [now/0]). - %% towards diameter_service_sup -export([start_link/1]). @@ -1218,7 +1215,7 @@ connect_timer(Opts, Def0) -> %% continuous restarted in case of faulty config or other problems. tc(Time, Tc) -> choose(Tc > ?RESTART_TC - orelse diameter_lib:micro_diff(Time) > 1000*?RESTART_TC, + orelse timer:now_diff(now(), Time) > 1000*?RESTART_TC, Tc, ?RESTART_TC). diff --git a/lib/diameter/src/base/diameter_session.erl b/lib/diameter/src/base/diameter_session.erl index c5ea0428b5..3b236f109a 100644 --- a/lib/diameter/src/base/diameter_session.erl +++ b/lib/diameter/src/base/diameter_session.erl @@ -157,8 +157,8 @@ session_id(Host) -> %% --------------------------------------------------------------------------- init() -> - {Now, Seed} = diameter_lib:seed(), - random:seed(Seed), + Now = now(), + random:seed(Now), Time = time32(Now), Seq = (?INT32 band (Time bsl 20)) bor (random:uniform(1 bsl 20) - 1), ets:insert(diameter_sequence, [{origin_state_id, Time}, diff --git a/lib/diameter/src/base/diameter_stats.erl b/lib/diameter/src/base/diameter_stats.erl index d2c760317a..5eb8fa1cba 100644 --- a/lib/diameter/src/base/diameter_stats.erl +++ b/lib/diameter/src/base/diameter_stats.erl @@ -24,9 +24,6 @@ -module(diameter_stats). -behaviour(gen_server). --compile({no_auto_import, [now/0]}). --import(diameter_lib, [now/0]). - -export([reg/2, reg/1, incr/3, incr/1, read/1, diff --git a/lib/diameter/src/base/diameter_sync.erl b/lib/diameter/src/base/diameter_sync.erl index 90eabece3d..cee06b9e96 100644 --- a/lib/diameter/src/base/diameter_sync.erl +++ b/lib/diameter/src/base/diameter_sync.erl @@ -27,9 +27,6 @@ -module(diameter_sync). -behaviour(gen_server). --compile({no_auto_import, [now/0]}). --import(diameter_lib, [now/0]). - -export([call/4, call/5, cast/4, cast/5, carp/1, carp/2]). diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index 66781d7b06..009a766e43 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -124,8 +124,7 @@ i({Ack, T, Pid, {RecvData, = Svc}}) -> monitor(process, Pid), wait(Ack, Pid), - {_, Seed} = diameter_lib:seed(), - random:seed(Seed), + random:seed(now()), putr(restart, {T, Opts, Svc, SvcOpts}), %% save seeing it in trace putr(dwr, dwr(Caps)), %% {_,_} = Mask = proplists:get_value(sequence, SvcOpts), @@ -453,7 +452,7 @@ transition({timeout, TRef, tw}, #watchdog{tref = TRef} = S) -> %% Message has arrived since the timer was started: subtract time %% already elapsed from new timer. transition({timeout, _, tw}, #watchdog{tref = T0} = S) -> - set_watchdog(diameter_lib:micro_diff(T0) div 1000, S); + set_watchdog(timer:now_diff(now(), T0) div 1000, S); %% State query. transition({state, Pid}, #watchdog{status = S}) -> @@ -535,7 +534,7 @@ set_watchdog(#watchdog{tref = undefined} = S) -> %% Timer already set: start at new one only at expiry. set_watchdog(#watchdog{} = S) -> - S#watchdog{tref = diameter_lib:now()}; + S#watchdog{tref = now()}; set_watchdog(stop = No) -> No. diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index f80de0a816..e9c52c9de5 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -20,9 +20,6 @@ -module(diameter_sctp). -behaviour(gen_server). --compile({no_auto_import, [now/0]}). --import(diameter_lib, [now/0]). - %% interface -export([start/3]). diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl index 5f1dbfbd61..17f5833101 100644 --- a/lib/diameter/test/diameter_codec_test.erl +++ b/lib/diameter/test/diameter_codec_test.erl @@ -229,7 +229,7 @@ v(Max, Ord, E) when Ord =< Max -> diameter_enum:to_list(E); v(Max, Ord, E) -> - random:seed(diameter_util:seed()), + random:seed(now()), v(Max, Ord, E, []). v(0, _, _, Acc) -> @@ -522,7 +522,7 @@ random(Mn,Mx) -> seed(undefined) -> put({?MODULE, seed}, true), - random:seed(diameter_util:seed()); + random:seed(now()); seed(true) -> ok. diff --git a/lib/diameter/test/diameter_config_SUITE.erl b/lib/diameter/test/diameter_config_SUITE.erl index 4bcaa8119f..bbdf672291 100644 --- a/lib/diameter/test/diameter_config_SUITE.erl +++ b/lib/diameter/test/diameter_config_SUITE.erl @@ -50,7 +50,7 @@ {request_errors, RE}, {call_mutates_state, C}]] || D <- [diameter_gen_base_rfc3588, diameter_gen_base_rfc6733], - M <- [?MODULE, [?MODULE, diameter_lib:now()]], + M <- [?MODULE, [?MODULE, now()]], A <- [0, common, make_ref()], S <- [[], make_ref()], AE <- [report, callback, discard], diff --git a/lib/diameter/test/diameter_ct.erl b/lib/diameter/test/diameter_ct.erl index 85c502ea7f..788cbbbe3e 100644 --- a/lib/diameter/test/diameter_ct.erl +++ b/lib/diameter/test/diameter_ct.erl @@ -43,7 +43,7 @@ ct_run(Opts) -> info(Start , info()). info() -> - [{time, diameter_lib:now()}, + [{time, now()}, {process_count, erlang:system_info(process_count)} | erlang:memory()]. @@ -56,6 +56,6 @@ info(L0, L1) -> io:format("INFO: ~p~n", [Diff]). diff(time, T0, T1) -> - diameter_lib:micro_diff(T1, T0); + timer:now_diff(T1, T0); diff(_, N0, N1) -> N1 - N0. diff --git a/lib/diameter/test/diameter_event_SUITE.erl b/lib/diameter/test/diameter_event_SUITE.erl index bfe160203c..8ede8a51a8 100644 --- a/lib/diameter/test/diameter_event_SUITE.erl +++ b/lib/diameter/test/diameter_event_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-15. All Rights Reserved. +%% Copyright Ericsson AB 2013-2015. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -174,9 +174,9 @@ event(Name) -> receive #diameter_event{service = Name, info = T} -> T end. event(Name, TL, TH) -> - T0 = diameter_lib:now(), + T0 = now(), Event = event(Name), - DT = diameter_lib:micro_diff(T0) div 1000, + DT = timer:now_diff(now(), T0) div 1000, {true, true, DT, Event} = {TL < DT, DT < TH, DT, Event}, Event. diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl index ef8e459175..dc0b466b59 100644 --- a/lib/diameter/test/diameter_examples_SUITE.erl +++ b/lib/diameter/test/diameter_examples_SUITE.erl @@ -295,15 +295,15 @@ slave() -> [{timetrap, {minutes, 10}}]. slave(_) -> - T0 = diameter_lib:now(), + T0 = now(), {ok, Node} = ct_slave:start(?MODULE, ?TIMEOUTS), - T1 = diameter_lib:now(), + T1 = now(), T2 = rpc:call(Node, erlang, now, []), {ok, Node} = ct_slave:stop(?MODULE), - now_diff([T0, T1, T2, diameter_lib:now()]). + now_diff([T0, T1, T2, now()]). now_diff([T1,T2|_] = Ts) -> - [diameter_lib:micro_diff(T2,T1) | now_diff(tl(Ts))]; + [timer:now_diff(T2,T1) | now_diff(tl(Ts))]; now_diff(_) -> []. diff --git a/lib/diameter/test/diameter_gen_sctp_SUITE.erl b/lib/diameter/test/diameter_gen_sctp_SUITE.erl index 4ea5e80095..ced897c714 100644 --- a/lib/diameter/test/diameter_gen_sctp_SUITE.erl +++ b/lib/diameter/test/diameter_gen_sctp_SUITE.erl @@ -296,12 +296,12 @@ connect2(Pid, PortNr, Bin) -> %% T2 = time after listening process received our message %% T3 = time after reply is received - T1 = diameter_util:timestamp(), + T1 = now(), ok = send(Sock, Id, Bin), T2 = unmark(recv(Sock, Id)), - T3 = diameter_util:timestamp(), - {diameter_lib:micro_diff(T2, T1), %% Outbound - diameter_lib:micro_diff(T3, T2)}. %% Inbound + T3 = now(), + {timer:now_diff(T2, T1), %% Outbound + timer:now_diff(T3, T2)}. %% Inbound %% recv/2 @@ -326,7 +326,7 @@ send(Sock, Id, Bin) -> %% mark/1 mark(Bin) -> - Info = term_to_binary(diameter_util:timestamp()), + Info = term_to_binary(now()), <>. %% unmark/1 diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl index 17faf30a9b..4669fb6720 100644 --- a/lib/diameter/test/diameter_traffic_SUITE.erl +++ b/lib/diameter/test/diameter_traffic_SUITE.erl @@ -874,7 +874,7 @@ call(Config, Req, Opts) -> diameter:call(CN, dict(Req, Dict0), msg(Req, ReqEncoding, Dict0), - [{extra, [{Name, Group}, diameter_lib:now()]} | Opts]). + [{extra, [{Name, Group}, now()]} | Opts]). origin({A,C}) -> 2*codec(A) + container(C); @@ -1200,10 +1200,8 @@ app(Req, _, Dict0) -> %% handle_error/6 handle_error(timeout = Reason, _Req, [$C|_], _Peer, _, Time) -> - Now = diameter_lib:now(), - {Reason, {diameter_lib:timestamp(Time), - diameter_lib:timestamp(Now), - diameter_lib:micro_diff(Now, Time)}}; + Now = now(), + {Reason, {Time, Now, timer:now_diff(Now, Time)}}; handle_error(Reason, _Req, [$C|_], _Peer, _, _Time) -> {error, Reason}. diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl index 78bddbd1cf..40f713a550 100644 --- a/lib/diameter/test/diameter_transport_SUITE.erl +++ b/lib/diameter/test/diameter_transport_SUITE.erl @@ -53,7 +53,7 @@ %% Receive a message. -define(RECV(Pat, Ret), receive Pat -> Ret end). --define(RECV(Pat), ?RECV(Pat, diameter_util:timestamp())). +-define(RECV(Pat), ?RECV(Pat, now())). %% Sockets are opened on the loopback address. -define(ADDR, {127,0,0,1}). @@ -335,7 +335,7 @@ make_msg() -> %% crypto:rand_bytes/1 isn't available on all platforms (since openssl %% isn't) so roll our own. rand_bytes(N) -> - random:seed(diameter_util:seed()), + random:seed(now()), rand_bytes(N, <<>>). rand_bytes(0, Bin) -> @@ -416,7 +416,7 @@ gen_accept(tcp, LSock) -> gen_send(sctp, Sock, Bin) -> {OS, _IS, Id} = getr(assoc), - {_, _, Us} = diameter_util:timestamp(), + {_, _, Us} = now(), gen_sctp:send(Sock, Id, Us rem OS, Bin); gen_send(tcp, Sock, Bin) -> gen_tcp:send(Sock, Bin). diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl index df7d268429..e8fab18a45 100644 --- a/lib/diameter/test/diameter_util.erl +++ b/lib/diameter/test/diameter_util.erl @@ -30,8 +30,6 @@ fold/3, foldl/3, scramble/1, - timestamp/0, - seed/0, unique_string/0, have_sctp/0]). @@ -178,7 +176,7 @@ scramble(L) -> [[fun s/1, L]]). s(L) -> - random:seed(seed()), + random:seed(now()), s([], L). s(Acc, []) -> @@ -187,19 +185,6 @@ s(Acc, L) -> {H, [T|Rest]} = lists:split(random:uniform(length(L)) - 1, L), s([T|Acc], H ++ Rest). -%% --------------------------------------------------------------------------- -%% timestamp/0 - -timestamp() -> - diameter_lib:timestamp(diameter_lib:now()). - -%% --------------------------------------------------------------------------- -%% seed/0 - -seed() -> - {_,T} = diameter_lib:seed(), - T. - %% --------------------------------------------------------------------------- %% unique_string/0 @@ -209,7 +194,7 @@ unique_string() -> integer_to_list(N) catch error: undef -> %% OTP < 18 - {M,S,U} = timestamp(), + {M,S,U} = now(), tl(lists:append(["-" ++ integer_to_list(N) || N <- [M,S,U]])) end. -- cgit v1.2.3 From 277bbb049662cb0b15489097d066bdb09366e538 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 4 Aug 2015 15:05:17 +0200 Subject: ssh: diffie-hellman-group14-sha1 --- lib/ssh/src/ssh_transport.erl | 32 +++++++--- lib/ssh/test/ssh_basic_SUITE.erl | 107 +++++++++++++++++-------------- lib/ssh/test/ssh_to_openssh_SUITE.erl | 116 +++++++++++++++++++++++++++++++++- 3 files changed, 200 insertions(+), 55 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 9be8e45aed..69ba797faf 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -79,9 +79,10 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()]. supported_algorithms(kex) -> select_crypto_supported( - [{'diffie-hellman-group1-sha1', [{hashs,sha}]}, - {'diffie-hellman-group-exchange-sha1', [{hashs,sha}]}, - {'diffie-hellman-group-exchange-sha256', [{hashs,sha256}]} + [{'diffie-hellman-group14-sha1', [{hashs,sha}]}, + {'diffie-hellman-group1-sha1', [{hashs,sha}]}, + {'diffie-hellman-group-exchange-sha256', [{hashs,sha256}]}, + {'diffie-hellman-group-exchange-sha1', [{hashs,sha}]} ]); supported_algorithms(public_key) -> ssh_auth:default_public_key_algorithms(); @@ -297,6 +298,7 @@ verify_algorithm(#alg{compress = undefined}) -> false; verify_algorithm(#alg{decompress = undefined}) -> false; verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) -> true; +verify_algorithm(#alg{kex = 'diffie-hellman-group14-sha1'}) -> true; verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) -> true; verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha256'}) -> true; verify_algorithm(_) -> false. @@ -305,8 +307,9 @@ verify_algorithm(_) -> false. %%% %%% Key exchange initialization %%% -key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) -> - {G, P} = dh_group1(), +key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group1-sha1' ; + Kex == 'diffie-hellman-group14-sha1' -> + {G, P} = dh_group(Kex), {Private, Public} = dh_gen_key(G, P, 1024), %% Public = G^Private mod P (def) {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0), @@ -329,10 +332,12 @@ key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group-exchange-sha %%%---------------------------------------------------------------- %%% %%% diffie-hellman-group1-sha1 +%%% diffie-hellman-group14-sha1 %%% -handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) -> +handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, + Ssh0 = #ssh{algorithms = #alg{kex=Kex}}) -> %% server - {G, P} = dh_group1(), + {G, P} = dh_group(Kex), if 1= {Private, Public} = dh_gen_key(G, P, 1024), @@ -817,6 +822,7 @@ verify(PlainText, Hash, Sig, Key) -> %% key exchange %% %% diffie-hellman-group1-sha1 REQUIRED +%% diffie-hellman-group14-sha1 REQUIRED %% %% @@ -1131,6 +1137,8 @@ hash(SSH, Char, Bits) -> case SSH#ssh.kex of 'diffie-hellman-group1-sha1' -> fun(Data) -> crypto:hash(sha, Data) end; + 'diffie-hellman-group14-sha1' -> + fun(Data) -> crypto:hash(sha, Data) end; 'diffie-hellman-group-exchange-sha1' -> fun(Data) -> crypto:hash(sha, Data) end; 'diffie-hellman-group-exchange-sha256' -> @@ -1229,6 +1237,10 @@ dh_group16() -> {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}. +dh_group('diffie-hellman-group1-sha1') -> dh_group1(); +dh_group('diffie-hellman-group14-sha1') -> dh_group14(). + + %%% First try exact match: dh_gex_group(_Min, N, _Max) when N==1024 -> dh_group1(); dh_gex_group(_Min, N, _Max) when N==2048 -> dh_group14(); @@ -1250,7 +1262,11 @@ dh_compute_key(G, P, OthersPublic, MyPrivate) -> crypto:compute_key(dh, OthersPublic, MyPrivate, [P,G]) ). - +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Other utils +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% trim_tail(Str) -> lists:reverse(trim_head(lists:reverse(Str))). diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index c71463db30..39ea2c9609 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -42,7 +42,7 @@ suite() -> all() -> [app_test, appup_test, - {group, 'diffie-hellman-group-exchange-sha1'}, + {group, key_exchange}, {group, dsa_key}, {group, rsa_key}, {group, dsa_pass_key}, @@ -93,8 +93,11 @@ groups() -> max_sessions_sftp_start_channel_parallel, max_sessions_sftp_start_channel_sequential ]}, - {'diffie-hellman-group-exchange-sha1', [], ['diffie-hellman-group-exchange-sha1' - ]}, + {key_exchange, [], ['diffie-hellman-group-exchange-sha1', + 'diffie-hellman-group-exchange-sha256', + 'diffie-hellman-group1-sha1', + 'diffie-hellman-group14-sha1' + ]}, {dir_options, [], [user_dir_option, system_dir_option]} ]. @@ -149,17 +152,11 @@ init_per_group(internal_error, Config) -> ssh_test_lib:setup_dsa(DataDir, PrivDir), file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")), Config; -init_per_group('diffie-hellman-group-exchange-sha1', Config) -> - case lists:member('diffie-hellman-group-exchange-sha1', - ssh_transport:supported_algorithms(kex)) of - true -> - DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - ssh_test_lib:setup_rsa(DataDir, PrivDir), - Config; - false -> - {skip,"diffie-hellman-group-exchange-sha1 is not supported"} - end; +init_per_group(key_exchange, Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_rsa(DataDir, PrivDir), + Config; init_per_group(dir_options, Config) -> PrivDir = ?config(priv_dir, Config), %% Make unreadable dir: @@ -207,6 +204,8 @@ init_per_group(_, Config) -> end_per_group(hardening_tests, Config) -> end_per_group(dsa_key, Config); +end_per_group(key_exchange, Config) -> + end_per_group(rsa_key, Config); end_per_group(dsa_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:clean_dsa(PrivDir), @@ -833,40 +832,56 @@ ssh_msg_debug_fun_option_client(Config) -> %%-------------------------------------------------------------------- 'diffie-hellman-group-exchange-sha1'(Config) -> - process_flag(trap_exit, true), - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), + kextest('diffie-hellman-group-exchange-sha1',Config). - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {user_passwords, [{"foo", "bar"}]}, - {preferred_algorithms, - [{kex, ['diffie-hellman-group-exchange-sha1']}]}, - {failfun, fun ssh_test_lib:failfun/2}]), - - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "bar"}, - {user_dir, UserDir}, - {preferred_algorithms, - [{kex, ['diffie-hellman-group-exchange-sha1']}]}, - {user_interaction, false}]), - check(ConnectionRef, Pid). +'diffie-hellman-group-exchange-sha256'(Config) -> + kextest('diffie-hellman-group-exchange-sha256',Config). -check(ConnectionRef, Pid) -> - {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId, - "1+1.", infinity), - Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, - case ssh_test_lib:receive_exec_result(Data) of - expected -> - ok; - Other -> - ct:fail(Other) - end, - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), - ssh:stop_daemon(Pid). +'diffie-hellman-group1-sha1'(Config) -> + kextest('diffie-hellman-group1-sha1',Config). + +'diffie-hellman-group14-sha1'(Config) -> + kextest('diffie-hellman-group14-sha1',Config). + + +kextest(Kex, Config) -> + case lists:member(Kex, ssh_transport:supported_algorithms(kex)) of + true -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{"foo", "bar"}]}, + {preferred_algorithms, + [{kex, [Kex]}]}, + {failfun, fun ssh_test_lib:failfun/2}]), + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "bar"}, + {user_dir, UserDir}, + {preferred_algorithms, + [{kex, [Kex]}]}, + {user_interaction, false}]), + + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "1+1.", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ok; + Other -> + ct:fail(Other) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + ssh:stop_daemon(Pid); + false -> + {skip, lists:concat([Kex, " is not supported"])} + end. %%-------------------------------------------------------------------- connectfun_disconnectfun_server(Config) -> diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index b7283202a3..fb1c6a1b61 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -51,13 +51,15 @@ groups() -> erlang_client_openssh_server_publickey_rsa, erlang_client_openssh_server_publickey_dsa, erlang_client_openssh_server_password, + erlang_client_openssh_server_kexs, erlang_client_openssh_server_nonexistent_subsystem ]}, {erlang_server, [], [erlang_server_openssh_client_exec, erlang_server_openssh_client_exec_compressed, erlang_server_openssh_client_pulic_key_dsa, erlang_server_openssh_client_cipher_suites, - erlang_server_openssh_client_macs]} + erlang_server_openssh_client_macs, + erlang_server_openssh_client_kexs]} ]. init_per_suite(Config) -> @@ -99,6 +101,12 @@ init_per_testcase(erlang_server_openssh_client_cipher_suites, Config) -> init_per_testcase(erlang_server_openssh_client_macs, Config) -> check_ssh_client_support(Config); +init_per_testcase(erlang_server_openssh_client_kexs, Config) -> + check_ssh_client_support(Config); + +init_per_testcase(erlang_client_openssh_server_kexs, Config) -> + check_ssh_client_support(Config); + init_per_testcase(_TestCase, Config) -> ssh:start(), Config. @@ -188,6 +196,48 @@ erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) -> ct:fail(Other) end. +%%-------------------------------------------------------------------- +erlang_client_openssh_server_kexs() -> + [{doc, "Test that we can connect with different KEXs."}]. + +erlang_client_openssh_server_kexs(Config) when is_list(Config) -> + Success = + lists:foldl( + fun(Kex, Acc) -> + ConnectionRef = + ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}, + {preferred_algorithms, + [{kex,[Kex]}]}]), + + {ok, ChannelId} = + ssh_connection:session_channel(ConnectionRef, infinity), + success = + ssh_connection:exec(ConnectionRef, ChannelId, + "echo testing", infinity), + + ExpectedData = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, + case ssh_test_lib:receive_exec_result(ExpectedData) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + Acc; + {unexpected_msg,{ssh_cm, ConnectionRef, + {exit_status, ChannelId, 0}} = ExitStatus} -> + ct:pal("0: Collected data ~p", [ExitStatus]), + ssh_test_lib:receive_exec_result(ExpectedData, ConnectionRef, ChannelId), + Acc; + Other -> + ct:pal("~p failed: ~p",[Kex,Other]), + false + end + end, true, ssh_transport:supported_algorithms(kex)), + case Success of + true -> + ok; + false -> + {fail, "Kex failed for one or more algos"} + end. + %%-------------------------------------------------------------------- erlang_server_openssh_client_exec() -> [{doc, "Test that exec command works."}]. @@ -321,6 +371,70 @@ erlang_server_openssh_client_macs(Config) when is_list(Config) -> ssh:stop_daemon(Pid). +%%-------------------------------------------------------------------- +erlang_server_openssh_client_kexs() -> + [{doc, "Test that we can connect with different KEXs."}]. + +erlang_server_openssh_client_kexs(Config) when is_list(Config) -> + SystemDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + KnownHosts = filename:join(PrivDir, "known_hosts"), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2}, + {preferred_algorithms, + [{kex,ssh_transport:supported_algorithms(kex)}]} + ]), + ct:sleep(500), + + ErlKexs = lists:map(fun erlang:atom_to_list/1, + ssh_transport:supported_algorithms(kex)), + OpenSshKexs = string:tokens(os:cmd("ssh -Q kex"), "\n"), + + Kexs = [{OpenSshKex,lists:member(OpenSshKex,ErlKexs)} + || OpenSshKex <- OpenSshKexs], + + Success = + lists:foldl( + fun({Kex, Expect}, Acc) -> + Cmd = "ssh -p " ++ integer_to_list(Port) ++ + " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++ + " -o KexAlgorithms=" ++ Kex ++ " 1+1.", + + ct:pal("Cmd: ~p~n", [Cmd]), + + SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), + + case Expect of + true -> + receive + {SshPort,{data, <<"2\n">>}} -> + Acc + after ?TIMEOUT -> + ct:pal("Did not receive answer for ~p",[Kex]), + false + end; + false -> + receive + {SshPort,{data, <<"Unable to negotiate a key exchange method", _/binary>>}} -> + Acc + after ?TIMEOUT -> + ct:pal("Did not receive no matching kex message for ~p",[Kex]), + false + end + end + end, true, Kexs), + + ssh:stop_daemon(Pid), + + case Success of + true -> + ok; + false -> + {fail, "Kex failed for one or more algos"} + end. + + %%-------------------------------------------------------------------- erlang_server_openssh_client_exec_compressed() -> [{doc, "Test that exec command works."}]. -- cgit v1.2.3 From 3e8d8f4595182d0e695cc166d5c6cf4490d17e75 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 4 Aug 2015 16:46:46 +0200 Subject: ssh: options 'dh_gex_groups' and 'dh_gex_limits' --- lib/ssh/src/ssh.erl | 31 +++++++++++++++++++++++++ lib/ssh/src/ssh_transport.erl | 54 ++++++++++++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 370f086600..cc2c591735 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -373,6 +373,10 @@ handle_option([{auth_method_kb_interactive_data, _} = Opt | Rest], SocketOptions handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{preferred_algorithms,_} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{dh_gex_groups,_} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{dh_gex_limits,_} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{quiet_mode, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{idle_time, _} = Opt | Rest], SocketOptions, SshOptions) -> @@ -411,6 +415,33 @@ handle_ssh_option({user_interaction, Value} = Opt) when is_boolean(Value) -> Opt; handle_ssh_option({preferred_algorithms,[_|_]} = Opt) -> handle_pref_algs(Opt); +handle_ssh_option({dh_gex_groups,L=[{I1,I2,I3}|_]}) when is_integer(I1), I1>0, + is_integer(I2), I2>0, + is_integer(I3), I3>0 -> + {dh_gex_groups, [{N,{G,P}} || {N,P,G} <- L]}; +handle_ssh_option({dh_gex_groups,{file,File=[C|_]}}=Opt) when is_integer(C), C>0 -> + %% A string, (file name) + case file:consult(File) of + {ok, List} -> + case lists:all(fun({I1,I2,I3}) when is_integer(I1), I1>0, + is_integer(I2), I2>0, + is_integer(I3), I3>0 -> + true; + (_) -> + false + end, List) of + true -> + handle_ssh_option({dh_gex_groups,List}); + false -> + throw({error, {{eoptions, Opt}, "Bad format in file "++File}}) + end; + Error -> + throw({error, {{eoptions, Opt},{"Error reading file",Error}}}) + end; +handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0, + is_integer(I), I>0, + is_integer(Max), Max>0 -> + Opt; handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; handle_ssh_option({max_sessions, Value} = Opt) when is_integer(Value), Value>0 -> diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 69ba797faf..dda9192284 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -404,9 +404,10 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, %%% handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, n = NBits, - max = Max}, Ssh0) when Min= + max = Max}, + Ssh0=#ssh{opts=Opts}) when Min= %% server - {G, P} = dh_gex_group(Min, NBits, Max), + {G, P} = dh_gex_group(Min, NBits, Max, proplists:get_value(dh_gex_groups,Opts)), {Private, Public} = dh_gen_key(G, P, 1024), {SshPacket, Ssh} = ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), @@ -1236,21 +1237,46 @@ dh_group15() -> dh_group16() -> {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}. - dh_group('diffie-hellman-group1-sha1') -> dh_group1(); dh_group('diffie-hellman-group14-sha1') -> dh_group14(). - -%%% First try exact match: -dh_gex_group(_Min, N, _Max) when N==1024 -> dh_group1(); -dh_gex_group(_Min, N, _Max) when N==2048 -> dh_group14(); -dh_gex_group(_Min, N, _Max) when N==3072 -> dh_group15(); -dh_gex_group(_Min, N, _Max) when N==4096 -> dh_group16(); -%%% If not an exact match, select the largest possible: -dh_gex_group(Min, _N, Max) when Min=<4096, 4096= dh_group16(); -dh_gex_group(Min, _N, Max) when Min=<3072, 3072= dh_group15(); -dh_gex_group(Min, _N, Max) when Min=<2048, 2048= dh_group14(); -dh_gex_group(Min, _N, Max) when Min=<1024, 1024= dh_group1(). +dh_gex_default_groups() -> + [{1024, dh_group1() }, + {2048, dh_group14()}, + {3072, dh_group15()}, + {4096, dh_group16()}]. + + +dh_gex_group(Min, N, Max, undefined) -> + dh_gex_group(Min, N, Max, dh_gex_default_groups()); +dh_gex_group(Min, N, Max, Groups) -> + %% First try to find an exact match. If not an exact match, select the largest possible. + {_,Group} = + lists:foldl( + fun(_, {I,G}) when I==N -> + %% If we have an exact match already: use that one + {I,G}; + ({I,G}, _) when I==N -> + %% If we now found an exact match: use that very one + {I,G}; + ({I,G}, {Imax,_Gmax}) when Min=Imax -> % b) {I,G} is larger than current max + %% A group within the limits and better than the one we have + {I,G}; + (_, IGmax) -> + %% Keep the one we have + IGmax + end, {-1,undefined}, Groups), + + case Group of + undefined -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "No possible diffie-hellman-group-exchange group found", + language = ""}); + _ -> + Group + end. dh_gen_key(G, P, _) -> -- cgit v1.2.3 From 99825046c9e17510d5e627f9d2cb61b5e5eb7110 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 5 Aug 2015 13:10:14 +0200 Subject: ssh: more dh_gex test cases --- lib/ssh/src/ssh.erl | 23 +++--- lib/ssh/src/ssh_transport.erl | 28 ++------ lib/ssh/src/ssh_transport.hrl | 20 ++++++ lib/ssh/test/ssh_protocol_SUITE.erl | 82 +++++++++++++++++++--- lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test | 3 + 5 files changed, 112 insertions(+), 44 deletions(-) create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index cc2c591735..5b2e0a988c 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -418,29 +418,24 @@ handle_ssh_option({preferred_algorithms,[_|_]} = Opt) -> handle_ssh_option({dh_gex_groups,L=[{I1,I2,I3}|_]}) when is_integer(I1), I1>0, is_integer(I2), I2>0, is_integer(I3), I3>0 -> - {dh_gex_groups, [{N,{G,P}} || {N,P,G} <- L]}; + {dh_gex_groups, lists:map(fun({N,G,P}) -> {N,{G,P}} end, L)}; handle_ssh_option({dh_gex_groups,{file,File=[C|_]}}=Opt) when is_integer(C), C>0 -> %% A string, (file name) case file:consult(File) of {ok, List} -> - case lists:all(fun({I1,I2,I3}) when is_integer(I1), I1>0, - is_integer(I2), I2>0, - is_integer(I3), I3>0 -> - true; - (_) -> - false - end, List) of - true -> - handle_ssh_option({dh_gex_groups,List}); - false -> - throw({error, {{eoptions, Opt}, "Bad format in file "++File}}) + try handle_ssh_option({dh_gex_groups,List}) of + {dh_gex_groups,_} = NewOpt -> + NewOpt + catch + _:_ -> + throw({error, {{eoptions, Opt}, "Bad format in file"}}) end; Error -> throw({error, {{eoptions, Opt},{"Error reading file",Error}}}) end; handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0, - is_integer(I), I>0, - is_integer(Max), Max>0 -> + is_integer(I), I>=Min, + is_integer(Max), Max>=I -> Opt; handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index dda9192284..d9dc7df73d 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1221,30 +1221,14 @@ peer_name({Host, _}) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% rfc 2489, ch 6.2 -dh_group1() -> - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}. +dh_group('diffie-hellman-group1-sha1') -> ?dh_group1; +dh_group('diffie-hellman-group14-sha1') -> ?dh_group14. -%%% rfc 3526, ch3 -dh_group14() -> - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}. - -%%% rfc 3526, ch4 -dh_group15() -> - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}. - -%%% rfc 3526, ch5 -dh_group16() -> - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}. - -dh_group('diffie-hellman-group1-sha1') -> dh_group1(); -dh_group('diffie-hellman-group14-sha1') -> dh_group14(). - dh_gex_default_groups() -> - [{1024, dh_group1() }, - {2048, dh_group14()}, - {3072, dh_group15()}, - {4096, dh_group16()}]. + [{1024, ?dh_group1 }, + {2048, ?dh_group14}, + {3072, ?dh_group15}, + {4096, ?dh_group16}]. dh_gex_group(Min, N, Max, undefined) -> diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index ab59742b96..9e1de171c2 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -188,4 +188,24 @@ -define(SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, 14). -define(SSH_DISCONNECT_ILLEGAL_USER_NAME, 15). +%% groups + +%%% rfc 2489, ch 6.2 +-define(dh_group1, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}). + +%%% rfc 3526, ch3 +-define(dh_group14, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}). + +%%% rfc 3526, ch4 +-define(dh_group15, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}). + +%%% rfc 3526, ch5 +-define(dh_group16, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}). + + + -endif. % -ifdef(ssh_transport). diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index d82cdaf2c7..246e3d4898 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -56,7 +56,11 @@ groups() -> lib_no_match ]}, {kex, [], [no_common_alg_server_disconnects, - no_common_alg_client_disconnects + no_common_alg_client_disconnects, + gex_client_init_default_noexact, + gex_client_init_default_exact, + gex_client_init_option_groups, + gex_client_init_option_groups_file ]} ]. @@ -68,9 +72,32 @@ end_per_suite(Config) -> stop_apps(Config). + +init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; + TC == gex_client_init_default_exact ; + TC == gex_client_init_option_groups ; + TC == gex_client_init_option_groups_file -> + Opts = case TC of + gex_client_init_option_groups -> + [{dh_gex_groups, [{2345, 3, 41}]}]; + gex_client_init_option_groups_file -> + DataDir = ?config(data_dir, Config), + F = filename:join(DataDir, "dh_group_test"), + [{dh_gex_groups, {file,F}}]; + _ -> + [] + end, + start_std_daemon(Config, + [{preferred_algorithms, ssh_transport:supported_algorithms()} + | Opts]); init_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). +end_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; + TC == gex_client_init_default_exact ; + TC == gex_client_init_option_groups ; + TC == gex_client_init_option_groups_file -> + stop_std_daemon(Config); end_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). @@ -293,6 +320,48 @@ no_common_alg_client_disconnects(Config) -> X -> ct:fail(X) end. +%%%-------------------------------------------------------------------- +gex_client_init_default_noexact(Config) -> + do_gex_client_init(Config, {2000, 3000, 4000}, + %% Warning, app knowledege: + ?dh_group15). + + +gex_client_init_default_exact(Config) -> + do_gex_client_init(Config, {2000, 2048, 4000}, + %% Warning, app knowledege: + ?dh_group14). + + +gex_client_init_option_groups(Config) -> + do_gex_client_init(Config, {2000, 2048, 4000}, {3,41}). + + +gex_client_init_option_groups_file(Config) -> + do_gex_client_init(Config, {2000, 2048, 4000}, {5,61}). + +do_gex_client_init(Config, {Min,N,Max}, {G,P}) -> + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {connect, + server_host(Config),server_port(Config), + [{silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}, + {preferred_algorithms,[{kex,['diffie-hellman-group-exchange-sha1']}]} + ]}, + receive_hello, + {send, hello}, + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, #ssh_msg_kex_dh_gex_request{min = Min, + n = N, + max = Max}}, + {match, #ssh_msg_kex_dh_gex_group{p=P, g=G, _='_'}, receive_msg} + ] + ). + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ @@ -353,6 +422,7 @@ stop_std_daemon(Config) -> ct:log("Std server ~p at ~p:~p stopped", [server_pid(Config), server_host(Config), server_port(Config)]), lists:keydelete(server, 1, Config). + check_std_daemon_works(Config, Line) -> case std_connect(Config) of {ok,C} -> @@ -362,13 +432,9 @@ check_std_daemon_works(Config, Line) -> ok = ssh:close(C), Config; Error = {error,_} -> - {fail, - lists:flatten( - io_lib:format("Standard server ~p:~p ~p is ill at line ~p: ~p", - [server_host(Config), server_port(Config), - server_pid(Config), Line, Error]) - ) - } + ct:fail("Standard server ~p:~p ~p is ill at line ~p: ~p", + [server_host(Config), server_port(Config), + server_pid(Config), Line, Error]) end. server_pid(Config) -> element(1,?v(server,Config)). diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test b/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test new file mode 100644 index 0000000000..2887bb4b60 --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test @@ -0,0 +1,3 @@ +{2222, 5, 61}. +{1111, 7, 91}. + -- cgit v1.2.3 From 25db64119ec6369156129a77330c64753a6706eb Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 5 Aug 2015 13:41:35 +0200 Subject: ssh: document new options in doc/ssh.xml --- lib/ssh/doc/src/ssh.xml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index d24025ca4d..cf5e8f1aff 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -43,7 +43,7 @@ Supported public key algorithms: ssh-rsa and ssh-dss. Supported MAC algorithms: hmac-sha2-256 and hmac-sha1. Supported encryption algorithms: aes128-ctr, aes128-cb and 3des-cbc. - Supported key exchange algorithms: diffie-hellman-group1-sha1. + Supported key exchange algorithms: diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256. Supported compression algorithms: none, zlib, zlib@openssh.com, Supports unicode filenames if the emulator and the underlaying OS support it. See section DESCRIPTION in the @@ -240,6 +240,13 @@ kex is implicit but public_key is set explicitly.

+ + +

Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group. + See RFC 4419 for the function of thoose. The default value is {512, 1024, 4096}. +

+
+

Sets a time-out on the transport layer @@ -449,6 +456,15 @@ kex is implicit but public_key is set explicitly.

+ + +

Sets the groups that the server may choose among when diffie-hellman-group-exchange is negotiated. + See RFC 4419 for details. +

+

If the parameter is {file,filename()}, the file must exist and have one or more three-tuples terminated by a dot. The interpretation is as if the tuples had been given directly in the option. The file is read when the daemon starts. +

+
+ boolean()}]]>

Provides a function for password validation. This function is called -- cgit v1.2.3 From b2e9955be035d1dce8ef118b341a79cc05339f44 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 5 Aug 2015 14:02:17 +0200 Subject: ssh: announce dh-group-exchange --- lib/ssh/src/ssh_transport.erl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index d9dc7df73d..38a0b7ec7c 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -67,10 +67,7 @@ default_algorithms(compression) -> %% Do not announce 'zlib@openssh.com' because there seem to be problems supported_algorithms(compression, same(['zlib@openssh.com'])); default_algorithms(kex) -> - %% Do not announce the experimental 'diffie-hellman-group-exchange-sha*' yet - supported_algorithms(kex, ['diffie-hellman-group-exchange-sha1', - 'diffie-hellman-group-exchange-sha256' - ]); + supported_algorithms(kex, []); default_algorithms(Alg) -> supported_algorithms(Alg). -- cgit v1.2.3 From b4030b60b58a681b2dea5453fbc36f7f4cc41bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 7 Jul 2015 15:21:30 +0200 Subject: Teach the compiler the 'da' and 'dz' options Add the 'da' option to create a list after the beam_a pass. Seeing how the code looks after beam_a, but before the blocks have been established, is sometimes useful. For symmetry, add the 'dz' option, even though it is just a synonym for 'S'. --- lib/compiler/src/compile.erl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index e0a29fe9b1..cf79fdc9f9 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -671,6 +671,7 @@ asm_passes() -> %% Assembly level optimisations. [{delay, [{pass,beam_a}, + {iff,da,{listing,"a"}}, {unless,no_postopt, [{pass,beam_block}, {iff,dblk,{listing,"block"}}, @@ -703,6 +704,7 @@ asm_passes() -> {iff,no_postopt,[{pass,beam_clean}]}, {pass,beam_z}, + {iff,dz,{listing,"z"}}, {iff,dopt,{listing,"optimize"}}, {iff,'S',{listing,"S"}}, {iff,'to_asm',{done,"S"}}]}, -- cgit v1.2.3 From 9b09b6473e85c1753e9a915d44b7df679a79cd8f Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Fri, 7 Aug 2015 08:57:18 +0200 Subject: Remove unnecessary sorting in stats suite The ordering of (ets) diameter_stats (also unnecessary) ensures the sorting. --- lib/diameter/test/diameter_stats_SUITE.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl index 76ff764671..b08d7a05d2 100644 --- a/lib/diameter/test/diameter_stats_SUITE.erl +++ b/lib/diameter/test/diameter_stats_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2015. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -95,7 +95,7 @@ read(_) -> 7 = ?stat:incr(C1, Ref, 7), Self = self(), [{Ref, [{C1,7}]}, {Self, [{C1,2}, {C2,1}]}] - = lists:sort(?stat:read([self(), Ref, make_ref()])), + = ?stat:read([self(), Ref, make_ref()]), [] = ?stat:read([]), [] = ?stat:read([make_ref()]), ?stat:flush([self(), Ref, make_ref()]). @@ -115,7 +115,7 @@ sum(_) -> [{Self, [{C1,1}, {C2,2}]}] = ?stat:sum([self()]), [{Ref, [{C1,7}]}, {Self, [{C1,1}, {C2,2}]}] - = lists:sort(?stat:flush([self(), Ref])). + = ?stat:flush([self(), Ref]). flush(_) -> Ref = make_ref(), -- cgit v1.2.3 From faf86cb3cee3b241faf82b4dc347b0d2b0c58201 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Wed, 22 Jul 2015 00:43:35 +0200 Subject: Make ets diameter_stats a set There's no need for it to be ordered, and the ordering has been seen to have an unexpectedly negative impact on performance in some cases. Order when retrieving statistics instead, so as not to change the presentation in diameter:service_info/2. --- lib/diameter/src/base/diameter_stats.erl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_stats.erl b/lib/diameter/src/base/diameter_stats.erl index d2c760317a..79a5c7b947 100644 --- a/lib/diameter/src/base/diameter_stats.erl +++ b/lib/diameter/src/base/diameter_stats.erl @@ -142,9 +142,14 @@ read(Refs, B) -> L. to_refdict(L) -> - lists:foldl(fun({{C,R}, N}, D) -> orddict:append(R, {C,N}, D) end, - orddict:new(), - L). + lists:foldl(fun append/2, orddict:new(), L). + +%% Order both references and counters in the returned list. +append({{Ctr, Ref}, N}, Dict) -> + orddict:update(Ref, + fun(D) -> orddict:store(Ctr, N, D) end, + [{Ctr, N}], + Dict). %% --------------------------------------------------------------------------- %% # sum(Refs) @@ -220,10 +225,7 @@ uptime() -> %% ---------------------------------------------------------- init([]) -> - ets:new(?TABLE, [named_table, - ordered_set, - public, - {write_concurrency, true}]), + ets:new(?TABLE, [named_table, set, public, {write_concurrency, true}]), {ok, #state{}}. %% ---------------------------------------------------------- -- cgit v1.2.3 From e2024d8830892fb8822c30d7c1140e3c54d0c84d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 3 Aug 2015 12:45:46 +0200 Subject: ssh: Unicode test improvments --- lib/ssh/test/ssh_sftp_SUITE.erl | 90 +++++++++++++++++----- .../f3.txt" | 1 + .../g\345\233\233.txt" | 1 + 3 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 "lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f3.txt" create mode 100644 "lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/g\345\233\233.txt" (limited to 'lib') diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index a95e16a0b3..c3de063c17 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -85,7 +85,12 @@ groups() -> {openssh_server, [], [{group,write_read_tests}, {group,remote_tar}]}, - {remote_tar, [], [create_empty_tar, files_to_tar, big_file_to_tar, files_chunked_to_tar, + {remote_tar, [], [create_empty_tar, + ascii_filename_ascii_contents_to_tar, + ascii_filename_unicode_contents_to_tar, + unicode_filename_ascii_contents_to_tar, + files_to_tar, + big_file_to_tar, files_chunked_to_tar, directory_to_tar, binaries_to_tar, null_crypto_tar, simple_crypto_tar_small, simple_crypto_tar_big, read_tar, read_null_crypto_tar, read_crypto_tar, @@ -121,23 +126,35 @@ init_per_group(unicode, Config) -> ct:comment("Begin ~p",[grps(Config)]), DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), - [{user, "åke高兴"}, - {passwd, "ärlig日本じん"}, - {data, <<"foobar å 一二三四いちにさんち">>}, - {filename, filename:join(PrivDir, "sftp瑞点.txt")}, - {testfile, filename:join(PrivDir, "testハンス.txt")}, - {linktest, filename:join(PrivDir, "link_test語.txt")}, - {tar_filename, filename:join(PrivDir, "sftp_tar_test一二三.tar")}, - {tar_F1_txt, "F一.txt"}, - {datadir_tar, filename:join(DataDir,"sftp_tar_test_data_高兴")} - | lists:foldl(fun(K,Cf) -> lists:keydelete(K,1,Cf) end, - Config, - [user, passwd, data, - filename, testfile, linktest, - tar_filename, tar_F1_txt, datadir_tar - ] - ) - ]; + NewConfig = + [{user, "åke高兴"}, + {passwd, "ärlig日本じん"}, + {data, <<"foobar å 一二三四いちにさんち">>}, + {filename, filename:join(PrivDir, "sftp瑞点.txt")}, + {testfile, filename:join(PrivDir, "testハンス.txt")}, + {linktest, filename:join(PrivDir, "link_test語.txt")}, + {tar_filename, filename:join(PrivDir, "sftp_tar_test一二三.tar")}, + {tar_F1_txt, "F一.txt"}, + {tar_F3_txt, "f3.txt"}, + {tar_F4_txt, "g四.txt"}, + {datadir_tar, filename:join(DataDir,"sftp_tar_test_data_高兴")} + | lists:foldl(fun(K,Cf) -> lists:keydelete(K,1,Cf) end, + Config, + [user, passwd, data, + filename, testfile, linktest, + tar_filename, tar_F1_txt, datadir_tar + ] + ) + ], + FN = fn(?config(tar_F1_txt,NewConfig), NewConfig), + case catch file:read_file(FN) of + {ok,FN_contents} -> + ct:log("Readable file:read_file(~tp) ->~n~tp",[FN,FN_contents]), + NewConfig; + Other -> + ct:log("Unreadable file:read_file(~tp) ->~n~p",[FN,Other]), + {skip, "Not unicode file reading"} + end; _ -> {skip, "Not unicode file encoding"} @@ -685,6 +702,43 @@ files_to_tar(Config) -> ok = erl_tar:close(Handle), chk_tar([F1, "f2.txt"], Config). +%%-------------------------------------------------------------------- +ascii_filename_ascii_contents_to_tar(Config) -> + ChPid2 = ?config(channel_pid2, Config), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), + ok = erl_tar:add(Handle, fn("f2.txt",Config), "f2.txt", [verbose]), + ok = erl_tar:close(Handle), + chk_tar(["f2.txt"], Config). + +%%-------------------------------------------------------------------- +ascii_filename_unicode_contents_to_tar(Config) -> + case ?config(tar_F3_txt, Config) of + undefined -> + {skip, "Unicode test"}; + Fn -> + ChPid2 = ?config(channel_pid2, Config), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), + ok = erl_tar:add(Handle, fn(Fn,Config), Fn, [verbose]), + ok = erl_tar:close(Handle), + chk_tar([Fn], Config) + end. + +%%-------------------------------------------------------------------- +unicode_filename_ascii_contents_to_tar(Config) -> + case ?config(tar_F4_txt, Config) of + undefined -> + {skip, "Unicode test"}; + Fn -> + ChPid2 = ?config(channel_pid2, Config), + TarFileName = ?config(tar_filename, Config), + {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]), + ok = erl_tar:add(Handle, fn(Fn,Config), Fn, [verbose]), + ok = erl_tar:close(Handle), + chk_tar([Fn], Config) + end. + %%-------------------------------------------------------------------- big_file_to_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), diff --git "a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f3.txt" "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f3.txt" new file mode 100644 index 0000000000..e6076a05b5 --- /dev/null +++ "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/f3.txt" @@ -0,0 +1 @@ +你好 diff --git "a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/g\345\233\233.txt" "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/g\345\233\233.txt" new file mode 100644 index 0000000000..d18c6b11fc --- /dev/null +++ "b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_\351\253\230\345\205\264/g\345\233\233.txt" @@ -0,0 +1 @@ +How are you? -- cgit v1.2.3 From 9d1cf458e616c93779d783820a59d04d3c628a3e Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 6 Aug 2015 17:46:27 +0200 Subject: ssh: ssh_trpt_test_lib improvments - negotiation state - better printouts --- lib/ssh/test/ssh_protocol_SUITE.erl | 18 ++--- lib/ssh/test/ssh_trpt_test_lib.erl | 129 ++++++++++++++++++++++++------------ 2 files changed, 96 insertions(+), 51 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 246e3d4898..732892ae37 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -240,7 +240,7 @@ lib_no_match(_Config) -> no_common_alg_server_disconnects(Config) -> {ok,_} = ssh_trpt_test_lib:exec( - [{set_options, [print_ops, print_seqnums, print_messages]}, + [{set_options, [print_ops, {print_messages,detail}]}, {connect, server_host(Config),server_port(Config), [{silently_accept_hosts, true}, @@ -251,7 +251,7 @@ no_common_alg_server_disconnects(Config) -> receive_hello, {send, hello}, {match, #ssh_msg_kexinit{_='_'}, receive_msg}, - {send, ssh_msg_kexinit}, + {send, ssh_msg_kexinit}, % with server unsupported 'ssh-dss' ! {match, {'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, tcp_closed]}, @@ -275,17 +275,16 @@ no_common_alg_client_disconnects(Config) -> Parent ! {result,self(), ssh_trpt_test_lib:exec( - [{set_options, [print_ops, print_messages]}, + [{set_options, [print_ops, {print_messages,detail}]}, {accept, [{system_dir, system_dir(Config)}, {user_dir, user_dir(Config)}]}, receive_hello, {send, hello}, - {match, #ssh_msg_kexinit{_='_'}, receive_msg}, - {send, #ssh_msg_kexinit{ + {send, #ssh_msg_kexinit{ % with unsupported "SOME-UNSUPPORTED" cookie = 247381486335508958743193106082599558706, kex_algorithms = ["diffie-hellman-group1-sha1"], - server_host_key_algorithms = ["some-unknown"], + server_host_key_algorithms = ["SOME-UNSUPPORTED"], % SIC! encryption_algorithms_client_to_server = ["aes128-ctr"], encryption_algorithms_server_to_client = ["aes128-ctr"], mac_algorithms_client_to_server = ["hmac-sha2-256"], @@ -306,7 +305,8 @@ no_common_alg_client_disconnects(Config) -> } end), - %% and finally connect to it with a regular Erlang SSH client: + %% and finally connect to it with a regular Erlang SSH client + %% which of course does not support SOME-UNSUPPORTED as pub key algo: Result = std_connect(HostPort, Config, [{preferred_algorithms,[{public_key,['ssh-dss']}]}]), ct:log("Result of connect is ~p",[Result]), @@ -317,7 +317,9 @@ no_common_alg_client_disconnects(Config) -> ct:pal("ERROR!~nOp = ~p~nExecResult = ~p~nState =~n~s", [Op,ExecResult,ssh_trpt_test_lib:format_msg(S)]), {fail, ExecResult}; - X -> ct:fail(X) + X -> + ct:pal("¤¤¤¤¤"), + ct:fail(X) end. %%%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 75f495b6d7..38b2789742 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -42,8 +42,8 @@ seen_hello = false, enc = <<>>, ssh = #ssh{}, % #ssh{} - own_kexinit, - peer_kexinit, + alg_neg = {undefined,undefined}, % {own_kexinit, peer_kexinit} + alg, % #alg{} vars = dict:new(), reply = [], % Some repy msgs are generated hidden in ssh_transport :[ prints = [], @@ -140,7 +140,10 @@ op(receive_hello, S0) when S0#s.seen_hello =/= true -> op(receive_msg, S) when S#s.seen_hello == true -> try recv(S) catch - {tcp,Exc} -> S#s{return_value=Exc} + {tcp,Exc} -> + S1 = opt(print_messages, S, + fun(X) when X==true;X==detail -> {"Recv~n~p~n",[Exc]} end), + S1#s{return_value=Exc} end; @@ -206,6 +209,9 @@ op_val(E, S0) -> end. +fail(Reason, {Fmt,Args}, S) when is_list(Fmt), is_list(Args) -> + fail(Reason, save_prints({Fmt,Args}, S)). + fail(Reason, S) -> throw({fail, Reason, S}). @@ -312,38 +318,51 @@ send(S=#s{ssh=C}, hello) -> send(S, list_to_binary(Hello)); send(S0, ssh_msg_kexinit) -> - {Msg, Bytes, C0} = ssh_transport:key_exchange_init_msg(S0#s.ssh), - S1 = opt(print_messages, S0, - fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), - S = case ?role(S1) of - server when is_record(S1#s.peer_kexinit, ssh_msg_kexinit) -> - {ok, C} = - ssh_transport:handle_kexinit_msg(S1#s.peer_kexinit, Msg, C0), - S1#s{peer_kexinit = used, - own_kexinit = used, - ssh = C}; - _ -> - S1#s{ssh = C0, - own_kexinit = Msg} - end, - send_bytes(Bytes, S#s{return_value = Msg}); + {Msg, _Bytes, _C0} = ssh_transport:key_exchange_init_msg(S0#s.ssh), + send(S0, Msg); -send(S0, ssh_msg_kexdh_init) when ?role(S0) == client, - is_record(S0#s.peer_kexinit, ssh_msg_kexinit), - is_record(S0#s.own_kexinit, ssh_msg_kexinit) -> +send(S0=#s{alg_neg={undefined,PeerMsg}}, Msg=#ssh_msg_kexinit{}) -> + S1 = opt(print_messages, S0, + fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), + S2 = case PeerMsg of + #ssh_msg_kexinit{} -> + try ssh_transport:handle_kexinit_msg(PeerMsg, Msg, S1#s.ssh) of + {ok,Cx} when ?role(S1) == server -> + S1#s{alg = Cx#ssh.algorithms}; + {ok,_NextKexMsgBin,Cx} when ?role(S1) == client -> + S1#s{alg = Cx#ssh.algorithms} + catch + Class:Exc -> + save_prints({"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n", + [?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(Msg)]}, + S1) + end; + undefined -> + S1 + end, + {Bytes, C} = ssh_transport:ssh_packet(Msg, S2#s.ssh), + send_bytes(Bytes, S2#s{return_value = Msg, + alg_neg = {Msg,PeerMsg}, + ssh = C}); + +send(S0, ssh_msg_kexdh_init) when ?role(S0) == client -> + {OwnMsg, PeerMsg} = S0#s.alg_neg, {ok, NextKexMsgBin, C} = - ssh_transport:handle_kexinit_msg(S0#s.peer_kexinit, S0#s.own_kexinit, S0#s.ssh), - + try ssh_transport:handle_kexinit_msg(PeerMsg, OwnMsg, S0#s.ssh) + catch + Class:Exc -> + fail("Algoritm negotiation failed!", + {"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s", + [?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(OwnMsg)]}, + S0) + end, S = opt(print_messages, S0, fun(X) when X==true;X==detail -> #ssh{keyex_key = {{_Private, Public}, {_G, _P}}} = C, Msg = #ssh_msg_kexdh_init{e = Public}, {"Send (reconstructed)~n~s~n",[format_msg(Msg)]} end), - - send_bytes(NextKexMsgBin, S#s{ssh = C, - peer_kexinit = used, - own_kexinit = used}); + send_bytes(NextKexMsgBin, S#s{ssh = C}); send(S0, ssh_msg_kexdh_reply) -> Bytes = proplists:get_value(ssh_msg_kexdh_reply, S0#s.reply), @@ -389,26 +408,42 @@ recv(S0 = #s{}) -> true -> %% Has seen hello, therefore no more crlf-messages are alowed. S = receive_binary_msg(S1), - case M=S#s.return_value of - #ssh_msg_kexinit{} when ?role(S) == server, - S#s.own_kexinit =/= undefined -> - {ok, C} = - ssh_transport:handle_kexinit_msg(M, S#s.own_kexinit, S#s.ssh), - S#s{peer_kexinit = used, - own_kexinit = used, - ssh = C}; - #ssh_msg_kexinit{} -> - S#s{peer_kexinit = M}; + case PeerMsg = S#s.return_value of + #ssh_msg_kexinit{} -> + case S#s.alg_neg of + {undefined,undefined} -> + S#s{alg_neg = {undefined,PeerMsg}}; + + {undefined,_} -> + fail("2 kexint received!!", S); + + {OwnMsg, _} -> + try ssh_transport:handle_kexinit_msg(PeerMsg, OwnMsg, S#s.ssh) of + {ok,C} when ?role(S) == server -> + S#s{alg_neg = {OwnMsg, PeerMsg}, + alg = C#ssh.algorithms, + ssh = C}; + {ok,_NextKexMsgBin,C} when ?role(S) == client -> + S#s{alg_neg = {OwnMsg, PeerMsg}, + alg = C#ssh.algorithms} + catch + Class:Exc -> + save_prints({"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n", + [?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(OwnMsg)]}, + S#s{alg_neg = {OwnMsg, PeerMsg}}) + end + end; + #ssh_msg_kexdh_init{} -> % Always the server - {ok, Reply, C} = ssh_transport:handle_kexdh_init(M, S#s.ssh), + {ok, Reply, C} = ssh_transport:handle_kexdh_init(PeerMsg, S#s.ssh), S#s{ssh = C, reply = [{ssh_msg_kexdh_reply,Reply} | S#s.reply] }; #ssh_msg_kexdh_reply{} -> - {ok, _NewKeys, C} = ssh_transport:handle_kexdh_reply(M, S#s.ssh), + {ok, _NewKeys, C} = ssh_transport:handle_kexdh_reply(PeerMsg, S#s.ssh), S#s{ssh=C#ssh{send_sequence=S#s.ssh#ssh.send_sequence}}; % Back the number #ssh_msg_newkeys{} -> - {ok, C} = ssh_transport:handle_new_keys(M, S#s.ssh), + {ok, C} = ssh_transport:handle_new_keys(PeerMsg, S#s.ssh), S#s{ssh=C}; _ -> S @@ -682,10 +717,18 @@ seqnum_trace(S) -> print_traces(S) when S#s.prints == [] -> S; print_traces(S) -> + Len = length(S#s.prints), ct:log("~s", - [lists:foldl(fun({Fmt,Args}, Acc) -> - [io_lib:format(Fmt,Args) | Acc] - end, "", S#s.prints)] + [lists:foldl( + fun({Fmt,Args}, Acc) -> + [case Len-length(Acc)-1 of + 0 -> + io_lib:format(Fmt,Args); + N -> + io_lib:format(lists:concat(['~p --------~n',Fmt]), + [Len-length(Acc)-1|Args]) + end | Acc] + end, "", S#s.prints)] ). opt(Flag, S, Fun) when is_function(Fun,1) -> -- cgit v1.2.3 From 1edbcc648f87ad66b047fbc73654764b618c37ae Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 7 Aug 2015 13:48:46 +0200 Subject: ssh: ct:pal -> ct:log in lib/ssh/test --- lib/ssh/test/ssh_basic_SUITE.erl | 66 +++++++++++++++--------------- lib/ssh/test/ssh_connection_SUITE.erl | 14 +++---- lib/ssh/test/ssh_protocol_SUITE.erl | 4 +- lib/ssh/test/ssh_sftp_SUITE.erl | 12 +++--- lib/ssh/test/ssh_sftpd_SUITE.erl | 14 +++---- lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl | 6 +-- lib/ssh/test/ssh_test_lib.erl | 22 +++++----- lib/ssh/test/ssh_to_openssh_SUITE.erl | 46 ++++++++++----------- lib/ssh/test/ssh_upgrade_SUITE.erl | 10 ++--- 9 files changed, 97 insertions(+), 97 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 39ea2c9609..f30e86f193 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -245,8 +245,8 @@ init_per_testcase(TC, Config) when TC==shell_no_unicode ; Shell = ssh_test_lib:start_shell(Port, IO, UserDir, [{silently_accept_hosts, true}, {user,"foo"},{password,"bar"}]), - ct:pal("IO=~p, Shell=~p, self()=~p",[IO,Shell,self()]), - ct:pal("file:native_name_encoding() = ~p,~nio:getopts() = ~p", + ct:log("IO=~p, Shell=~p, self()=~p",[IO,Shell,self()]), + ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p", [file:native_name_encoding(),io:getopts()]), wait_for_erlang_first_line([{io,IO}, {shell,Shell}, {sftpd, Sftpd} | Config]); init_per_testcase(_TestCase, Config) -> @@ -620,7 +620,7 @@ shell(Config) when is_list(Config) -> {'EXIT', _, _} -> ct:fail(no_ssh_connection); ErlShellStart -> - ct:pal("Erlang shell start: ~p~n", [ErlShellStart]), + ct:log("Erlang shell start: ~p~n", [ErlShellStart]), do_shell(IO, Shell) end. @@ -704,7 +704,7 @@ server_password_option(Config) when is_list(Config) -> {user_interaction, false}, {user_dir, UserDir}]), - ct:pal("Test of wrong password: Error msg: ~p ~n", [Reason]), + ct:log("Test of wrong password: Error msg: ~p ~n", [Reason]), ssh:close(ConnectionRef), ssh:stop_daemon(Pid). @@ -1259,13 +1259,13 @@ peername_sockname(Config) when is_list(Config) -> ssh:connection_info(ConnectionRef, [peer]), [{sockname, {HostSockClient,PortSockClient} = ClientSock}] = ssh:connection_info(ConnectionRef, [sockname]), - ct:pal("Client: ~p ~p", [ClientPeer, ClientSock]), + ct:log("Client: ~p ~p", [ClientPeer, ClientSock]), receive {ssh_cm, ConnectionRef, {data, ChannelId, _, Response}} -> {PeerNameSrv,SockNameSrv} = binary_to_term(Response), {HostPeerSrv,PortPeerSrv} = PeerNameSrv, {HostSockSrv,PortSockSrv} = SockNameSrv, - ct:pal("Server: ~p ~p", [PeerNameSrv, SockNameSrv]), + ct:log("Server: ~p ~p", [PeerNameSrv, SockNameSrv]), host_equal(HostPeerSrv, HostSockClient), PortPeerSrv = PortSockClient, host_equal(HostSockSrv, HostPeerClient), @@ -1443,7 +1443,7 @@ packet_size_zero(Config) -> receive {ssh_cm,Conn,{data,Chan,_Type,_Msg1}} = M -> - ct:pal("Got ~p",[M]), + ct:log("Got ~p",[M]), ct:fail(doesnt_obey_max_packet_size_0) after 5000 -> ok @@ -1520,7 +1520,7 @@ chan_exec(ConnectionRef, Cmnd, Expected) -> ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0); {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} = ExitStatus0} -> - ct:pal("0: Collected data ~p", [ExitStatus0]), + ct:log("0: Collected data ~p", [ExitStatus0]), ssh_test_lib:receive_exec_result(Data0, ConnectionRef, ChannelId0); Other0 -> @@ -1612,7 +1612,7 @@ ssh_connect_negtimeout(Config, Parallel) -> {ok,Socket} = gen_tcp:connect(Host, Port, []), Factor = 2, - ct:pal("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), + ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), ct:sleep(round(Factor * NegTimeOut)), case inet:sockname(Socket) of @@ -1643,22 +1643,22 @@ ssh_connect_nonegtimeout_connected(Config, Parallel) -> {parallel_login, Parallel}, {negotiation_timeout, NegTimeOut}, {failfun, fun ssh_test_lib:failfun/2}]), - ct:pal("~p Listen ~p:~p",[_Pid,_Host,Port]), + ct:log("~p Listen ~p:~p",[_Pid,_Host,Port]), ct:sleep(500), IO = ssh_test_lib:start_io_server(), Shell = ssh_test_lib:start_shell(Port, IO, UserDir), receive Error = {'EXIT', _, _} -> - ct:pal("~p",[Error]), + ct:log("~p",[Error]), ct:fail(no_ssh_connection); ErlShellStart -> - ct:pal("---Erlang shell start: ~p~n", [ErlShellStart]), + ct:log("---Erlang shell start: ~p~n", [ErlShellStart]), one_shell_op(IO, NegTimeOut), one_shell_op(IO, NegTimeOut), Factor = 2, - ct:pal("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), + ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), ct:sleep(round(Factor * NegTimeOut)), one_shell_op(IO, NegTimeOut) @@ -1667,7 +1667,7 @@ ssh_connect_nonegtimeout_connected(Config, Parallel) -> one_shell_op(IO, TimeOut) -> - ct:pal("One shell op: Waiting for prompter"), + ct:log("One shell op: Waiting for prompter"), receive ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0]) after TimeOut -> ct:fail("Timeout waiting for promter") @@ -1770,7 +1770,7 @@ connect_fun(ssh_sftp__start_channel, _Config) -> max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> Connect = fun(Host,Port) -> R = Connect0(Host,Port), - ct:pal("Connect(~p,~p) -> ~p",[Host,Port,R]), + ct:log("Connect(~p,~p) -> ~p",[Host,Port,R]), R end, SystemDir = filename:join(?config(priv_dir, Config), system), @@ -1783,7 +1783,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> {parallel_login, ParallelLogin}, {max_sessions, MaxSessions} ]), - ct:pal("~p Listen ~p:~p for max ~p sessions",[Pid,Host,Port,MaxSessions]), + ct:log("~p Listen ~p:~p for max ~p sessions",[Pid,Host,Port,MaxSessions]), try [Connect(Host,Port) || _ <- lists:seq(1,MaxSessions)] of Connections -> @@ -1792,7 +1792,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> [_|_] = Connections, %% Now try one more than alowed: - ct:pal("Info Report might come here...",[]), + ct:log("Info Report might come here...",[]), try Connect(Host,Port) of _ConnectionRef1 -> @@ -1921,12 +1921,12 @@ basic_test(Config) -> do_shell(IO, Shell) -> receive ErlPrompt0 -> - ct:pal("Erlang prompt: ~p~n", [ErlPrompt0]) + ct:log("Erlang prompt: ~p~n", [ErlPrompt0]) end, IO ! {input, self(), "1+1.\r\n"}, receive Echo0 -> - ct:pal("Echo: ~p ~n", [Echo0]) + ct:log("Echo: ~p ~n", [Echo0]) end, receive ?NEWLINE -> @@ -1934,7 +1934,7 @@ do_shell(IO, Shell) -> end, receive Result0 = <<"2">> -> - ct:pal("Result: ~p~n", [Result0]) + ct:log("Result: ~p~n", [Result0]) end, receive ?NEWLINE -> @@ -1942,7 +1942,7 @@ do_shell(IO, Shell) -> end, receive ErlPrompt1 -> - ct:pal("Erlang prompt: ~p~n", [ErlPrompt1]) + ct:log("Erlang prompt: ~p~n", [ErlPrompt1]) end, exit(Shell, kill). %%Does not seem to work in the testserver! @@ -1953,7 +1953,7 @@ do_shell(IO, Shell) -> %% end, %% receive %% Echo1 -> - %% ct:pal("Echo: ~p ~n", [Echo1]) + %% ct:log("Echo: ~p ~n", [Echo1]) %% end, %% receive %% ?NEWLINE -> @@ -1961,7 +1961,7 @@ do_shell(IO, Shell) -> %% end, %% receive %% Result1 -> - %% ct:pal("Result: ~p~n", [Result1]) + %% ct:log("Result: ~p~n", [Result1]) %% end, %% receive %% {'EXIT', Shell, killed} -> @@ -1975,13 +1975,13 @@ wait_for_erlang_first_line(Config) -> {'EXIT', _, _} -> {fail,no_ssh_connection}; <<"Eshell ",_/binary>> = _ErlShellStart -> - ct:pal("Erlang shell start: ~p~n", [_ErlShellStart]), + ct:log("Erlang shell start: ~p~n", [_ErlShellStart]), Config; Other -> - ct:pal("Unexpected answer from ssh server: ~p",[Other]), + ct:log("Unexpected answer from ssh server: ~p",[Other]), {fail,unexpected_answer} after 10000 -> - ct:pal("No answer from ssh-server"), + ct:log("No answer from ssh-server"), {fail,timeout} end. @@ -1997,7 +1997,7 @@ new_do_shell(IO, N, Ops=[{Order,Arg}|More]) -> PfxSize = size(Pfx), receive _X = <<"\r\n">> -> - ct:pal("Skip newline ~p",[_X]), + ct:log("Skip newline ~p",[_X]), new_do_shell(IO, N, Ops); < ">> when (P1-$0)==N -> @@ -2013,15 +2013,15 @@ new_do_shell(IO, N, Ops=[{Order,Arg}|More]) -> ct:fail("new_do_shell error: ~p~n",[Err]); RecBin when Order==expect ; Order==expect_echo -> - ct:pal("received ~p",[RecBin]), + ct:log("received ~p",[RecBin]), RecStr = string:strip(unicode:characters_to_list(RecBin)), ExpStr = string:strip(Arg), case lists:prefix(ExpStr, RecStr) of true when Order==expect -> - ct:pal("Matched ~ts",[RecStr]), + ct:log("Matched ~ts",[RecStr]), new_do_shell(IO, N, More); true when Order==expect_echo -> - ct:pal("Matched echo ~ts",[RecStr]), + ct:log("Matched echo ~ts",[RecStr]), new_do_shell(IO, N, More); false -> ct:fail("*** Expected ~p, but got ~p",[string:strip(ExpStr),RecStr]) @@ -2047,12 +2047,12 @@ prompt_prefix() -> new_do_shell_prompt(IO, N, type, Str, More) -> - ct:pal("Matched prompt ~p to trigger sending of next line to server",[N]), + ct:log("Matched prompt ~p to trigger sending of next line to server",[N]), IO ! {input, self(), Str++"\r\n"}, - ct:pal("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]), + ct:log("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]), new_do_shell(IO, N, [{expect_echo,Str}|More]); % expect echo of the sent line new_do_shell_prompt(IO, N, Op, Str, More) -> - ct:pal("Matched prompt ~p",[N]), + ct:log("Matched prompt ~p",[N]), new_do_shell(IO, N, [{Op,Str}|More]). %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index eb7c641d8a..fbcf06290a 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -186,7 +186,7 @@ big_cat(Config) when is_list(Config) -> %% pre-adjust receive window so the other end doesn't block ssh_connection:adjust_window(ConnectionRef, ChannelId0, size(Data)), - ct:pal("sending ~p byte binary~n",[size(Data)]), + ct:log("sending ~p byte binary~n",[size(Data)]), ok = ssh_connection:send(ConnectionRef, ChannelId0, Data, 10000), ok = ssh_connection:send_eof(ConnectionRef, ChannelId0), @@ -197,10 +197,10 @@ big_cat(Config) when is_list(Config) -> {ok, Other} -> case size(Data) =:= size(Other) of true -> - ct:pal("received and sent data are same" + ct:log("received and sent data are same" "size but do not match~n",[]); false -> - ct:pal("sent ~p but only received ~p~n", + ct:log("sent ~p but only received ~p~n", [size(Data), size(Other)]) end, ct:fail(receive_data_mismatch); @@ -450,7 +450,7 @@ gracefull_invalid_version(Config) when is_list(Config) -> ok = gen_tcp:send(S, ["SSH-8.-1","\r\n"]), receive Verstring -> - ct:pal("Server version: ~p~n", [Verstring]), + ct:log("Server version: ~p~n", [Verstring]), receive {tcp_closed, S} -> ok @@ -470,7 +470,7 @@ gracefull_invalid_start(Config) when is_list(Config) -> ok = gen_tcp:send(S, ["foobar","\r\n"]), receive Verstring -> - ct:pal("Server version: ~p~n", [Verstring]), + ct:log("Server version: ~p~n", [Verstring]), receive {tcp_closed, S} -> ok @@ -490,7 +490,7 @@ gracefull_invalid_long_start(Config) when is_list(Config) -> ok = gen_tcp:send(S, [lists:duplicate(257, $a), "\r\n"]), receive Verstring -> - ct:pal("Server version: ~p~n", [Verstring]), + ct:log("Server version: ~p~n", [Verstring]), receive {tcp_closed, S} -> ok @@ -511,7 +511,7 @@ gracefull_invalid_long_start_no_nl(Config) when is_list(Config) -> ok = gen_tcp:send(S, [lists:duplicate(257, $a), "\r\n"]), receive Verstring -> - ct:pal("Server version: ~p~n", [Verstring]), + ct:log("Server version: ~p~n", [Verstring]), receive {tcp_closed, S} -> ok diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 732892ae37..dc02b940d7 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -314,11 +314,11 @@ no_common_alg_client_disconnects(Config) -> {result,Pid,{ok,_}} -> ok; {result,Pid,{error,{Op,ExecResult,S}}} -> - ct:pal("ERROR!~nOp = ~p~nExecResult = ~p~nState =~n~s", + ct:log("ERROR!~nOp = ~p~nExecResult = ~p~nState =~n~s", [Op,ExecResult,ssh_trpt_test_lib:format_msg(S)]), {fail, ExecResult}; X -> - ct:pal("¤¤¤¤¤"), + ct:log("¤¤¤¤¤"), ct:fail(X) end. diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index c3de063c17..bab5bf9fe9 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -47,7 +47,7 @@ init_per_suite(Config) -> catch crypto:stop(), case (catch crypto:start()) of ok -> - ct:pal("file:native_name_encoding() = ~p,~nio:getopts() = ~p", + ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p", [file:native_name_encoding(),io:getopts()]), ssh:start(), Config; @@ -397,7 +397,7 @@ read_dir(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), {Sftp, _} = ?config(sftp, Config), {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), - ct:pal("sftp list dir: ~p~n", [Files]). + ct:log("sftp list dir: ~p~n", [Files]). %%-------------------------------------------------------------------- write_file() -> @@ -478,12 +478,12 @@ rename_file(Config) when is_list(Config) -> {Sftp, _} = ?config(sftp, Config), {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir), - ct:pal("FileName: ~p, Files: ~p~n", [FileName, Files]), + ct:log("FileName: ~p, Files: ~p~n", [FileName, Files]), true = lists:member(filename:basename(FileName), Files), false = lists:member(filename:basename(NewFileName), Files), ok = ssh_sftp:rename(Sftp, FileName, NewFileName), {ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir), - ct:pal("FileName: ~p, Files: ~p~n", [FileName, NewFiles]), + ct:log("FileName: ~p, Files: ~p~n", [FileName, NewFiles]), false = lists:member(filename:basename(FileName), NewFiles), true = lists:member(filename:basename(NewFileName), NewFiles). @@ -529,7 +529,7 @@ retrieve_attributes(Config) when is_list(Config) -> {ok, NewFileInfo} = file:read_file_info(FileName), %% TODO comparison. There are some differences now is that ok? - ct:pal("SFTP: ~p FILE: ~p~n", [FileInfo, NewFileInfo]). + ct:log("SFTP: ~p FILE: ~p~n", [FileInfo, NewFileInfo]). %%-------------------------------------------------------------------- set_attributes() -> @@ -558,7 +558,7 @@ async_read(Config) when is_list(Config) -> receive {async_reply, Ref, {ok, Data}} -> - ct:pal("Data: ~p~n", [Data]), + ct:log("Data: ~p~n", [Data]), ok; Msg -> ct:fail(Msg) diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index f38fcc5521..94a54ec9db 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -152,7 +152,7 @@ init_per_testcase(TestCase, Config) -> {ok, <>, _} = reply(Cm, Channel), - ct:pal("Client: ~p Server ~p~n", [ProtocolVer, Version]), + ct:log("Client: ~p Server ~p~n", [ProtocolVer, Version]), [{sftp, {Cm, Channel}}, {sftpd, Sftpd }| Config]. @@ -418,7 +418,7 @@ real_path(Config) when is_list(Config) -> RealPath = filename:absname(binary_to_list(Path)), AbsPrivDir = filename:absname(PrivDir), - ct:pal("Path: ~p PrivDir: ~p~n", [RealPath, AbsPrivDir]), + ct:log("Path: ~p PrivDir: ~p~n", [RealPath, AbsPrivDir]), true = RealPath == AbsPrivDir end. @@ -447,7 +447,7 @@ links(Config) when is_list(Config) -> true = binary_to_list(Path) == FileName, - ct:pal("Path: ~p~n", [binary_to_list(Path)]) + ct:log("Path: ~p~n", [binary_to_list(Path)]) end. %%-------------------------------------------------------------------- @@ -548,10 +548,10 @@ set_attributes(Config) when is_list(Config) -> %% Can not test that NewPermissions = Permissions as %% on Unix platforms, other bits than those listed in the %% API may be set. - ct:pal("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]), + ct:log("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]), true = OrigPermissions =/= NewPermissions, - ct:pal("Try to open the file"), + ct:log("Try to open the file"), NewReqId = 2, {ok, <>, _} = open_file(FileName, Cm, Channel, NewReqId, @@ -563,7 +563,7 @@ set_attributes(Config) when is_list(Config) -> NewReqId1 = 3, - ct:pal("Set original permissions on the now open file"), + ct:log("Set original permissions on the now open file"), {ok, <>, _} = @@ -786,7 +786,7 @@ read_dir(Handle, Cm, Channel, ReqId) -> case reply(Cm, Channel) of {ok, <>, _} -> - ct:pal("Count: ~p Listing: ~p~n", + ct:log("Count: ~p Listing: ~p~n", [Count, binary_to_list(Listing)]), read_dir(Handle, Cm, Channel, ReqId); {ok, < NumOfPorts = length(erlang:ports()), - ct:pal("Number of open ports: ~p~n", [NumOfPorts]), + ct:log("Number of open ports: ~p~n", [NumOfPorts]), {ok, <<_/binary>>} = ssh_sftp:read_file(Sftp, FileName), @@ -255,14 +255,14 @@ root_dir(Config) when is_list(Config) -> {ok, Bin} = ssh_sftp:read_file(Sftp, FileName), {ok, Listing} = ssh_sftp:list_dir(Sftp, "."), - ct:pal("Listing: ~p~n", [Listing]). + ct:log("Listing: ~p~n", [Listing]). %%-------------------------------------------------------------------- list_dir_limited(Config) when is_list(Config) -> {Sftp, _} = ?config(sftp, Config), {ok, Listing} = ssh_sftp:list_dir(Sftp, "."), - ct:pal("Listing: ~p~n", [Listing]). + ct:log("Listing: ~p~n", [Listing]). %%-------------------------------------------------------------------- ver6_basic() -> diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 97c35e549c..988ea47bd8 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -97,10 +97,10 @@ loop_io_server(TestCase, Buff0) -> {input, TestCase, Line} -> loop_io_server(TestCase, Buff0 ++ [Line]); {io_request, From, ReplyAs, Request} -> -%%ct:pal("~p",[{io_request, From, ReplyAs, Request}]), +%%ct:log("~p",[{io_request, From, ReplyAs, Request}]), {ok, Reply, Buff} = io_request(Request, TestCase, From, ReplyAs, Buff0), -%%ct:pal("io_request(~p)-->~p",[Request,{ok, Reply, Buff}]), +%%ct:log("io_request(~p)-->~p",[Request,{ok, Reply, Buff}]), io_reply(From, ReplyAs, Reply), loop_io_server(TestCase, Buff); {'EXIT',_, _} -> @@ -134,26 +134,26 @@ io_request({get_line, _Enc,_}, _, _, _, [Line | Buff]) -> io_reply(_, _, []) -> ok; io_reply(From, ReplyAs, Reply) -> -%%ct:pal("io_reply ~p sending ~p ! ~p",[self(),From, {io_reply, ReplyAs, Reply}]), +%%ct:log("io_reply ~p sending ~p ! ~p",[self(),From, {io_reply, ReplyAs, Reply}]), From ! {io_reply, ReplyAs, Reply}. reply(_, []) -> ok; reply(TestCase, Result) -> -%%ct:pal("reply ~p sending ~p ! ~p",[self(), TestCase, Result]), +%%ct:log("reply ~p sending ~p ! ~p",[self(), TestCase, Result]), TestCase ! Result. receive_exec_result(Msg) -> - ct:pal("Expect data! ~p", [Msg]), + ct:log("Expect data! ~p", [Msg]), receive {ssh_cm,_,{data,_,1, Data}} -> - ct:pal("StdErr: ~p~n", [Data]), + ct:log("StdErr: ~p~n", [Data]), receive_exec_result(Msg); Msg -> - ct:pal("1: Collected data ~p", [Msg]), + ct:log("1: Collected data ~p", [Msg]), expected; Other -> - ct:pal("Other ~p", [Other]), + ct:log("Other ~p", [Other]), {unexpected_msg, Other} end. @@ -165,15 +165,15 @@ receive_exec_end(ConnectionRef, ChannelId) -> case receive_exec_result(ExitStatus) of {unexpected_msg, Eof} -> %% Open ssh seems to not allways send these messages %% in the same order! - ct:pal("2: Collected data ~p", [Eof]), + ct:log("2: Collected data ~p", [Eof]), case receive_exec_result(ExitStatus) of expected -> expected = receive_exec_result(Closed); {unexpected_msg, Closed} -> - ct:pal("3: Collected data ~p", [Closed]) + ct:log("3: Collected data ~p", [Closed]) end; expected -> - ct:pal("4: Collected data ~p", [ExitStatus]), + ct:log("4: Collected data ~p", [ExitStatus]), expected = receive_exec_result(Eof), expected = receive_exec_result(Closed); Other -> diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index fb1c6a1b61..06bf264033 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -148,7 +148,7 @@ erlang_client_openssh_server_exec(Config) when is_list(Config) -> ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0); {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} = ExitStatus0} -> - ct:pal("0: Collected data ~p", [ExitStatus0]), + ct:log("0: Collected data ~p", [ExitStatus0]), ssh_test_lib:receive_exec_result(Data0, ConnectionRef, ChannelId0); Other0 -> @@ -164,7 +164,7 @@ erlang_client_openssh_server_exec(Config) when is_list(Config) -> ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1); {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId1, 0}} = ExitStatus1} -> - ct:pal("0: Collected data ~p", [ExitStatus1]), + ct:log("0: Collected data ~p", [ExitStatus1]), ssh_test_lib:receive_exec_result(Data1, ConnectionRef, ChannelId1); Other1 -> @@ -190,7 +190,7 @@ erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) -> ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}} = ExitStatus} -> - ct:pal("0: Collected data ~p", [ExitStatus]), + ct:log("0: Collected data ~p", [ExitStatus]), ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId); Other -> ct:fail(Other) @@ -223,11 +223,11 @@ erlang_client_openssh_server_kexs(Config) when is_list(Config) -> Acc; {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}} = ExitStatus} -> - ct:pal("0: Collected data ~p", [ExitStatus]), + ct:log("0: Collected data ~p", [ExitStatus]), ssh_test_lib:receive_exec_result(ExpectedData, ConnectionRef, ChannelId), Acc; Other -> - ct:pal("~p failed: ~p",[Kex,Other]), + ct:log("~p failed: ~p",[Kex,Other]), false end end, true, ssh_transport:supported_algorithms(kex)), @@ -256,7 +256,7 @@ erlang_server_openssh_client_exec(Config) when is_list(Config) -> Cmd = "ssh -p " ++ integer_to_list(Port) ++ " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.", - ct:pal("Cmd: ~p~n", [Cmd]), + ct:log("Cmd: ~p~n", [Cmd]), SshPort = open_port({spawn, Cmd}, [binary]), @@ -297,7 +297,7 @@ erlang_server_openssh_client_cipher_suites(Config) when is_list(Config) -> " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++ " -c " ++ Cipher ++ " 1+1.", - ct:pal("Cmd: ~p~n", [Cmd]), + ct:log("Cmd: ~p~n", [Cmd]), SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), @@ -347,7 +347,7 @@ erlang_server_openssh_client_macs(Config) when is_list(Config) -> " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++ " -o MACs=" ++ MAC ++ " 1+1.", - ct:pal("Cmd: ~p~n", [Cmd]), + ct:log("Cmd: ~p~n", [Cmd]), SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), @@ -401,7 +401,7 @@ erlang_server_openssh_client_kexs(Config) when is_list(Config) -> " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++ " -o KexAlgorithms=" ++ Kex ++ " 1+1.", - ct:pal("Cmd: ~p~n", [Cmd]), + ct:log("Cmd: ~p~n", [Cmd]), SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), @@ -411,7 +411,7 @@ erlang_server_openssh_client_kexs(Config) when is_list(Config) -> {SshPort,{data, <<"2\n">>}} -> Acc after ?TIMEOUT -> - ct:pal("Did not receive answer for ~p",[Kex]), + ct:log("Did not receive answer for ~p",[Kex]), false end; false -> @@ -419,7 +419,7 @@ erlang_server_openssh_client_kexs(Config) when is_list(Config) -> {SshPort,{data, <<"Unable to negotiate a key exchange method", _/binary>>}} -> Acc after ?TIMEOUT -> - ct:pal("Did not receive no matching kex message for ~p",[Kex]), + ct:log("Did not receive no matching kex message for ~p",[Kex]), false end end @@ -494,11 +494,11 @@ erlang_client_openssh_server_setenv(Config) when is_list(Config) -> {data,0,1, UnxpectedData}}} -> %% Some os may return things as %% ENV_TEST: Undefined variable.\n" - ct:pal("UnxpectedData: ~p", [UnxpectedData]), + ct:log("UnxpectedData: ~p", [UnxpectedData]), ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}} = ExitStatus} -> - ct:pal("0: Collected data ~p", [ExitStatus]), + ct:log("0: Collected data ~p", [ExitStatus]), ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId); Other -> @@ -601,7 +601,7 @@ erlang_client_openssh_server_password(Config) when is_list(Config) -> {user_interaction, false}, {user_dir, UserDir}]), - ct:pal("Test of user foo that does not exist. " + ct:log("Test of user foo that does not exist. " "Error msg: ~p~n", [Reason0]), User = string:strip(os:cmd("whoami"), right, $\n), @@ -615,10 +615,10 @@ erlang_client_openssh_server_password(Config) when is_list(Config) -> {password, "foo"}, {user_interaction, false}, {user_dir, UserDir}]), - ct:pal("Test of wrong Pasword. " + ct:log("Test of wrong Pasword. " "Error msg: ~p~n", [Reason1]); _ -> - ct:pal("Whoami failed reason: ~n", []) + ct:log("Whoami failed reason: ~n", []) end. %%-------------------------------------------------------------------- @@ -646,19 +646,19 @@ erlang_client_openssh_server_nonexistent_subsystem(Config) when is_list(Config) receive_hej() -> receive <<"Hej", _binary>> = Hej -> - ct:pal("Expected result: ~p~n", [Hej]); + ct:log("Expected result: ~p~n", [Hej]); <<"Hej\n", _binary>> = Hej -> - ct:pal("Expected result: ~p~n", [Hej]); + ct:log("Expected result: ~p~n", [Hej]); <<"Hej\r\n", _/binary>> = Hej -> - ct:pal("Expected result: ~p~n", [Hej]); + ct:log("Expected result: ~p~n", [Hej]); Info -> Lines = binary:split(Info, [<<"\r\n">>], [global]), case lists:member(<<"Hej">>, Lines) of true -> - ct:pal("Expected result found in lines: ~p~n", [Lines]), + ct:log("Expected result found in lines: ~p~n", [Lines]), ok; false -> - ct:pal("Extra info: ~p~n", [Info]), + ct:log("Extra info: ~p~n", [Info]), receive_hej() end end. @@ -672,7 +672,7 @@ receive_logout() -> ok end; Info -> - ct:pal("Extra info when logging out: ~p~n", [Info]), + ct:log("Extra info when logging out: ~p~n", [Info]), receive_logout() end. @@ -715,6 +715,6 @@ check_ssh_client_support2(P) -> {P, {exit_status, E}} -> E after 5000 -> - ct:pal("Openssh command timed out ~n"), + ct:log("Openssh command timed out ~n"), -1 end. diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl index c0645f3b01..85f4d36258 100644 --- a/lib/ssh/test/ssh_upgrade_SUITE.erl +++ b/lib/ssh/test/ssh_upgrade_SUITE.erl @@ -94,8 +94,8 @@ minor_upgrade(Config) when is_list(Config) -> %%% Called by ct_release_test:upgrade/4 upgrade_init(CTData, State) -> {ok, AppUp={_, _, Up, _Down}} = ct_release_test:get_appup(CTData, ssh), - ct:pal("AppUp: ~p", [AppUp]), - ct:pal("Up: ~p", [Up]), + ct:log("AppUp: ~p", [AppUp]), + ct:log("Up: ~p", [Up]), case Soft = is_soft(Up) of %% It is symmetrical, if upgrade is soft so is downgrade true -> @@ -134,12 +134,12 @@ is_soft(_) -> test_hard(State0, FileName) -> - ct:pal("test_hard State0=~p, FileName=~p",[State0, FileName]), + ct:log("test_hard State0=~p, FileName=~p",[State0, FileName]), State = setup_server_client(State0), test_connection(FileName, random_contents(), State). test_soft(State0, FileName) -> - ct:pal("test_soft State0=~p, FileName=~p",[State0, FileName]), + ct:log("test_soft State0=~p, FileName=~p",[State0, FileName]), State = test_connection(FileName, random_contents(), State0), setup_server_client( close(State) ). @@ -171,7 +171,7 @@ setup_server_client(#state{config=Config} = State) -> test_connection(FileName, FileContents, #state{client = ChannelPid, root_dir = FtpRootDir} = State) -> - ct:pal("test_connection Writing with ssh_sftp:write_file",[]), + ct:log("test_connection Writing with ssh_sftp:write_file",[]), case ssh_sftp:write_file(ChannelPid, FileName, FileContents) of ok -> case ssh_sftp:read_file(ChannelPid, FileName) of -- cgit v1.2.3 From 75ab95febea6c3d22f395a4bf986507673bb6c57 Mon Sep 17 00:00:00 2001 From: Constantin Rack Date: Sun, 9 Aug 2015 17:42:40 +0200 Subject: Fix typo --- lib/compiler/src/genop.tab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab index 8124729b35..253fd2794c 100755 --- a/lib/compiler/src/genop.tab +++ b/lib/compiler/src/genop.tab @@ -164,7 +164,7 @@ BEAM_FORMAT_NUMBER=0 25: wait/1 ## @spec wait_timeout Lable Time -## @doc Sets up a timeout of Time milllisecons and saves the address of the +## @doc Sets up a timeout of Time milliseconds and saves the address of the ## following instruction as the entry point if the timeout triggers. 26: wait_timeout/2 -- cgit v1.2.3 From a1074f44ce2f83cb97a713a183c0335ff670b06a Mon Sep 17 00:00:00 2001 From: Constantin Rack Date: Sun, 9 Aug 2015 21:08:42 +0200 Subject: Fix another small typo --- lib/compiler/src/genop.tab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab index 253fd2794c..8464af3dd0 100755 --- a/lib/compiler/src/genop.tab +++ b/lib/compiler/src/genop.tab @@ -169,7 +169,7 @@ BEAM_FORMAT_NUMBER=0 26: wait_timeout/2 # -# Arithmethic opcodes. +# Arithmetic opcodes. # 27: -m_plus/4 28: -m_minus/4 -- cgit v1.2.3 From 22f4e79f312b88d81f00c414230076bbc68769af Mon Sep 17 00:00:00 2001 From: Tobias Schlager Date: Tue, 11 Aug 2015 16:33:26 +0200 Subject: Remove built-in definition of xml.xsd from xmerl Removes the built-in definitions of http://www.w3.org/2001/xml.xsd from the xmerl_xsd module. xmerl_xsd does load the definitions of the above schema into its processing table during initialization. This leads to the inability to process XSD schemas that properly import xml.xsd (as suggested in xml.xsd itself). Furthermore, the definitions are loaded from a binary containing the corresponding terms in Erlang external term format. Since this is not refactoring safe the intended functionality already broke long ago (prior to github import) because some of the record definitions did change in releases older than R13B03. To sum up, the current code does not do anything useful because the built-in definitions from the binary can't be used due to incompatible records. Thus, this fix is not backwards incompatible. The change also adds two new test cases covering common use-cases when using 'xml:' types in custom schemas. --- lib/xmerl/src/xmerl_xsd.erl | 127 ------------ lib/xmerl/test/xmerl_xsd_SUITE.erl | 18 +- lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml | 5 + lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd | 13 ++ lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd | 287 +++++++++++++++++++++++++++ 5 files changed, 322 insertions(+), 128 deletions(-) create mode 100644 lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml create mode 100644 lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd create mode 100644 lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd (limited to 'lib') diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl index 847161e844..3038a54ee6 100644 --- a/lib/xmerl/src/xmerl_xsd.erl +++ b/lib/xmerl/src/xmerl_xsd.erl @@ -4888,7 +4888,6 @@ mk_EII_Att_QName(AttName,XMLEl,S) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% create_tables(S=#xsd_state{table=undefined}) -> Tid=ets:new(xmerl_schema_tab,[]), - initial_tab_data(Tid), S#xsd_state{table=Tid}; create_tables(S) -> S. @@ -5617,131 +5616,5 @@ format_error(Err) -> %% {shema_el_pathname(SchemaE,Env), %% xml_el_pathname(E)}. -initial_tab_data(Tab) -> - ets:insert(Tab, - binary_to_term( - <<131,108,0,0,0,9,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116, - 101,104,3,100,0,5,115,112,97,99,101,106,100,0,36,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57, - 56,47,110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99,104,101, - 109,97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,5,115,112,97, - 99,101,106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51, - 46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112, - 97,99,101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121, - 112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97, - 109,101,95,108,0,0,0,1,100,0,5,115,112,97,99,101,106,106,106,100,0,5, - 102,97,108,115,101,106,100,0,8,111,112,116,105,111,110,97,108,100,0,9, - 117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105, - 110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,2, - 100,0,6,115,99,104,101,109,97,107,0,7,120,109,108,46,120,115,100,104, - 7,100,0,6,115,99,104,101,109,97,100,0,11,117,110,113,117,97,108,105, - 102,105,101,100,100,0,11,117,110,113,117,97,108,105,102,105,101,100, - 100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114, - 103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101, - 106,106,106,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116,101, - 104,3,100,0,4,98,97,115,101,106,100,0,36,104,116,116,112,58,47,47, - 119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47, - 110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99,104,101,109, - 97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,4,98,97,115,101, - 106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111, - 114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99, - 101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101, - 104,3,100,0,6,97,110,121,85,82,73,106,100,0,32,104,116,116,112,58,47, - 47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83, - 99,104,101,109,97,106,100,0,5,102,97,108,115,101,106,100,0,8,111,112, - 116,105,111,110,97,108,100,0,9,117,110,100,101,102,105,110,101,100, - 100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101, - 102,105,110,101,100,104,2,104,2,100,0,14,97,116,116,114,105,98,117, - 116,101,71,114,111,117,112,104,3,100,0,12,115,112,101,99,105,97,108, - 65,116,116,114,115,106,100,0,36,104,116,116,112,58,47,47,119,119,119, - 46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101, - 115,112,97,99,101,104,5,100,0,22,115,99,104,101,109,97,95,97,116,116, - 114,105,98,117,116,101,95,103,114,111,117,112,104,3,100,0,12,115,112, - 101,99,105,97,108,65,116,116,114,115,106,100,0,36,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57, - 56,47,110,97,109,101,115,112,97,99,101,100,0,9,117,110,100,101,102, - 105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,108,0,0, - 0,3,104,2,100,0,9,97,116,116,114,105,98,117,116,101,104,3,100,0,4,98, - 97,115,101,106,106,104,2,100,0,9,97,116,116,114,105,98,117,116,101, - 104,3,100,0,4,108,97,110,103,106,106,104,2,100,0,9,97,116,116,114, - 105,98,117,116,101,104,3,100,0,5,115,112,97,99,101,106,106,106,104, - 2,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0, - 15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0, - 1,100,0,5,115,112,97,99,101,106,106,104,9,100,0,18,115,99,104,101, - 109,97,95,115,105,109,112,108,101,95,116,121,112,101,104,3,100,0,15, - 95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0,1, - 100,0,5,115,112,97,99,101,106,106,108,0,0,0,1,100,0,5,115,112,97,99, - 101,106,104,3,100,0,6,78,67,78,97,109,101,106,100,0,32,104,116,116, - 112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47, - 88,77,76,83,99,104,101,109,97,100,0,5,102,97,108,115,101,106,108,0,0, - 0,1,104,2,100,0,11,101,110,117,109,101,114,97,116,105,111,110,108,0,0, - 0,2,107,0,7,100,101,102,97,117,108,116,107,0,8,112,114,101,115,101, - 114,118,101,106,106,100,0,6,97,116,111,109,105,99,108,0,0,0,1,104,2, - 100,0,11,114,101,115,116,114,105,99,116,105,111,110,104,2,104,3,100, - 0,6,78,67,78,97,109,101,106,100,0,32,104,116,116,112,58,47,47,119, - 119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99, - 104,101,109,97,108,0,0,0,2,104,2,100,0,11,101,110,117,109,101,114, - 97,116,105,111,110,107,0,7,100,101,102,97,117,108,116,104,2,100,0, - 11,101,110,117,109,101,114,97,116,105,111,110,107,0,8,112,114,101, - 115,101,114,118,101,106,106,104,2,104,2,100,0,10,115,105,109,112, - 108,101,84,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110, - 111,95,110,97,109,101,95,108,0,0,0,1,100,0,4,108,97,110,103,106,106, - 104,9,100,0,18,115,99,104,101,109,97,95,115,105,109,112,108,101,95, - 116,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95, - 110,97,109,101,95,108,0,0,0,1,100,0,4,108,97,110,103,106,106,108,0,0, - 0,1,100,0,4,108,97,110,103,106,100,0,9,117,110,100,101,102,105,110, - 101,100,100,0,5,102,97,108,115,101,106,106,100,0,6,97,116,111,109, - 105,99,108,0,0,0,1,104,2,100,0,5,117,110,105,111,110,108,0,0,0,2,104, - 2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0,8,108, - 97,110,103,117,97,103,101,106,100,0,32,104,116,116,112,58,47,47,119, - 119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99,104, - 101,109,97,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104, - 3,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108, - 0,0,0,2,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101, - 95,100,0,4,108,97,110,103,106,106,106,106,104,2,104,2,100,0,9,97,116, - 116,114,105,98,117,116,101,104,3,100,0,2,105,100,106,100,0,36,104,116, - 116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47, - 49,57,57,56,47,110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99, - 104,101,109,97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,2,105, - 100,106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46, - 111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97, - 99,101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121,112, - 101,104,3,100,0,2,73,68,106,100,0,32,104,116,116,112,58,47,47,119,119, - 119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99,104,101, - 109,97,106,100,0,5,102,97,108,115,101,106,100,0,8,111,112,116,105,111, - 110,97,108,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117, - 110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110, - 101,100,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116,101,104,3, - 100,0,4,108,97,110,103,106,100,0,36,104,116,116,112,58,47,47,119,119, - 119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109, - 101,115,112,97,99,101,104,9,100,0,16,115,99,104,101,109,97,95,97,116, - 116,114,105,98,117,116,101,104,3,100,0,4,108,97,110,103,106,100,0,36, - 104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88, - 77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101,108,0,0,0,1, - 104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0,15, - 95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0,1, - 100,0,4,108,97,110,103,106,106,106,100,0,5,102,97,108,115,101,106, - 100,0,8,111,112,116,105,111,110,97,108,100,0,9,117,110,100,101,102, - 105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9, - 117,110,100,101,102,105,110,101,100,104,2,104,2,100,0,10,115,105,109, - 112,108,101,84,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95, - 110,111,95,110,97,109,101,95,108,0,0,0,2,100,0,15,95,120,109,101,114, - 108,95,110,111,95,110,97,109,101,95,100,0,4,108,97,110,103,106,106, - 104,9,100,0,18,115,99,104,101,109,97,95,115,105,109,112,108,101,95, - 116,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95, - 110,97,109,101,95,108,0,0,0,2,100,0,15,95,120,109,101,114,108,95,110, - 111,95,110,97,109,101,95,100,0,4,108,97,110,103,106,106,108,0,0,0,2, - 100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,100, - 0,4,108,97,110,103,106,104,3,100,0,6,115,116,114,105,110,103,106,100, - 0,32,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47, - 50,48,48,49,47,88,77,76,83,99,104,101,109,97,100,0,5,102,97,108,115, - 101,106,108,0,0,0,1,104,2,100,0,11,101,110,117,109,101,114,97,116,105, - 111,110,108,0,0,0,1,106,106,106,100,0,6,97,116,111,109,105,99,108,0,0, - 0,1,104,2,100,0,11,114,101,115,116,114,105,99,116,105,111,110,104,2, - 104,3,100,0,6,115,116,114,105,110,103,106,100,0,32,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76, - 83,99,104,101,109,97,108,0,0,0,1,104,2,100,0,11,101,110,117,109,101, - 114,97,116,105,111,110,106,106,106,106>>)). - default_namespace_by_convention() -> [{xml,'http://www.w3.org/XML/1998/namespace'}]. diff --git a/lib/xmerl/test/xmerl_xsd_SUITE.erl b/lib/xmerl/test/xmerl_xsd_SUITE.erl index 101fbcd50f..92c8287782 100644 --- a/lib/xmerl/test/xmerl_xsd_SUITE.erl +++ b/lib/xmerl/test/xmerl_xsd_SUITE.erl @@ -41,7 +41,8 @@ groups() -> [{group, primitive_datatypes}, {group, derived_datatypes}]}, {validation_tests, [], - [{group, xmlSchemaPrimerExamples}, + [{group, xmlXsdAndExample}, + {group, xmlSchemaPrimerExamples}, {group, miscXMLexamples}]}, {primitive_datatypes, [], [string, boolean, decimal, float, double, duration, @@ -55,6 +56,8 @@ groups() -> negativeInteger, long, int, short, byte, nonNegativeInteger, unsignedLong, unsignedInt, unsignedShort, unsignedByte, positiveInteger]}, + {xmlXsdAndExample, [], + [xml_xsd, xml_lang_attr]}, {xmlSchemaPrimerExamples, [], [po, po1, po2, ipo, ipo_redefine, '4Q99']}, {miscXMLexamples, [], @@ -863,6 +866,19 @@ compare_duration(_Config) -> ?line indefinite = xmerl_xsd_type:compare_durations("P5M","P153D"), ?line lt = xmerl_xsd_type:compare_durations("P5M","P154D"). +xml_xsd(suite) -> []; +xml_xsd(Config) -> + DataDir = ?config(data_dir, Config), + Options = [{fetch_path, [DataDir]}], + {ok, _} = xmerl_xsd:process_schema("xml.xsd", Options). + +xml_lang_attr(suite) -> []; +xml_lang_attr(Config) -> + DataDir = ?config(data_dir, Config), + {Element, _} = xmerl_scan:file(filename:join([DataDir, "book.xml"])), + Options = [{fetch_path, [DataDir]}], + {ok, Schema} = xmerl_xsd:process_schema("book.xsd", Options), + {Element, _} = xmerl_xsd:validate(Element, Schema). po(suite) -> []; po(Config) -> diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml new file mode 100644 index 0000000000..17d7ceffee --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml @@ -0,0 +1,5 @@ + + + Author1 + Author2 + diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd new file mode 100644 index 0000000000..830951ec1b --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd new file mode 100644 index 0000000000..aea7d0db0a --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd @@ -0,0 +1,287 @@ + + + + + + +

+

About the XML namespace

+ +
+

+ This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
+ + + + + + +
+ +

lang (as an attribute name)

+

+ denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+
+ + + + + + + + + +
+ + + + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
+ + + + + + +
+ + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
+
+
+ + + + +
+ +

id (as an attribute name)

+

+ denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
+
+
+ + + + + + + + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+
+
+
+
+ + + +
+

Versioning policy for this schema document

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+ + + -- cgit v1.2.3 From 030f3cbd61217bcd3eb49ed19de9d05987d1e6b7 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Thu, 13 Aug 2015 12:34:10 +0200 Subject: Update release notes --- lib/diameter/doc/src/notes.xml | 126 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) (limited to 'lib') diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index c5df63a7f0..7726d761bd 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -42,6 +42,132 @@ first.

+
diameter 1.9.2.1 + +
Fixed Bugs and Malfunctions + + +

+ Don't report 5005 (DIAMETER_AVP_MISSING) errors + unnecessarily.

+

+ An AVP whose decode failed was reported as missing, + despite having been reported with another error as a + consequence of the failure.

+

+ Own Id: OTP-12871

+
+ +

+ Fix relay encode of nested, Grouped AVPs.

+

+ A fault in OTP-12475 caused encode to fail if the first + AVP in a Grouped AVP was itself Grouped.

+

+ Own Id: OTP-12879 Aux Id: OTP-12475

+
+ +

+ Improve decode performance.

+

+ The time required to decode a message increased + quadratically with the number of AVPs in the worst case, + leading to extremely long execution times.

+

+ Own Id: OTP-12891

+
+ +

+ Match acceptable peer addresses case insensitively.

+

+ Regular expressions passed in an 'accept' tuple to + diameter_tcp or diameter_sctp inappropriately matched + case.

+

+ Own Id: OTP-12902

+
+ +

+ Improve watchdog and statistics performance.

+

+ Inefficient use of timers contributed to poor performance + at high load, as did ordering of the table statistics are + written to.

+

+ Own Id: OTP-12912

+
+ +

+ Fix start order of alternate transports.

+

+ A transport configured with diameter:add_transport/2 can + be passed multiple transport_module/transport_config + tuples in order to specify alternate configuration, + modules being attempted in order until one succeeds. This + is primarily for the connecting case; for example, to + allow a transport to be configured to first attempt + connection over SCTP, and then TCP in case SCTP fails. + Multiple module tuples can be paired with a single config + tuple, but in this case the start order was reversed + relative to the order in which the modules were specifed.

+

+ Own Id: OTP-12929

+
+ +

+ Fix decode of Grouped AVPs containing errors.

+

+ RFC 6733 says this of Failed-AVP in 7.5:

+

+

In the case where the offending AVP + is embedded within a Grouped AVP, the Failed-AVP MAY + contain the grouped AVP, which in turn contains the + single offending AVP. The same method MAY be employed if + the grouped AVP itself is embedded in yet another grouped + AVP and so on. In this case, the Failed-AVP MAY contain + the grouped AVP hierarchy up to the single offending AVP. + This enables the recipient to detect the location of the + offending AVP when embedded in a + group.

+

+ It says this of DIAMETER_INVALID_AVP_LENGTH in 7.1.5:

+

+

The request contained an AVP with + an invalid length. A Diameter message indicating this + error MUST include the offending AVPs within a Failed-AVP + AVP. In cases where the erroneous AVP length value + exceeds the message length or is less than the minimum + AVP header length, it is sufficient to include the + offending AVP header and a zero filled payload of the + minimum required length for the payloads data type. If + the AVP is a Grouped AVP, the Grouped AVP header with an + empty payload would be sufficient to indicate the + offending AVP. In the case where the offending AVP header + cannot be fully decoded when the AVP length is less than + the minimum AVP header length, it is sufficient to + include an offending AVP header that is formulated by + padding the incomplete AVP header with zero up to the + minimum AVP header length.

+

+ The AVPs placed in the errors field of a diameter_packet + record are intended to be appropriate for inclusion in a + Failed-AVP, but neither of the above paragraphs has been + followed in the Grouped case: the entire faulty AVP + (non-faulty components and all) has been included. This + made it difficult to identify the actual faulty AVP in + all but simple cases.

+

+ The decode is now adapted to the RFC, and implements the + suggested single faulty AVP, nested in as many Grouped + containers as required.

+

+ Own Id: OTP-12930

+ +
+
+ +
+
diameter 1.9.2
Fixed Bugs and Malfunctions -- cgit v1.2.3 From 8b2c875cfd6a12d3dc9ccd9198d1f6123dee8a7f Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Fri, 14 Aug 2015 00:44:02 +0200 Subject: Fix broken release notes Broken in the parent commit. --- lib/diameter/doc/src/notes.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index 2953de95d1..c5f0d66f10 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -100,6 +100,8 @@ first.

+
+
diameter 1.10 -- cgit v1.2.3 From b17eeb8319af3b3a994ccd3fcf1170ae49291e2c Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Fri, 14 Aug 2015 08:16:13 +0200 Subject: debugger: Fix broken debugger:quick/3 start Too much code was removed in commit 560f73141af --- lib/debugger/src/dbg_wx_trace.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/debugger/src/dbg_wx_trace.erl b/lib/debugger/src/dbg_wx_trace.erl index 4438466bb0..879887879a 100644 --- a/lib/debugger/src/dbg_wx_trace.erl +++ b/lib/debugger/src/dbg_wx_trace.erl @@ -72,6 +72,10 @@ start(Pid, TraceWin, BackTrace) -> start(Pid, TraceWin, BackTrace, Strings) -> case whereis(dbg_wx_mon) of + undefined -> + Parent = wx:new(), + Env = wx:get_env(), + start(Pid, Env, Parent, TraceWin, BackTrace, Strings); Monitor when is_pid(Monitor) -> Monitor ! {?MODULE, self(), get_env}, receive -- cgit v1.2.3 From c1d03aff7cb03ce6b430dfb9916df2c02940ab9b Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Mon, 3 Aug 2015 14:44:20 +0200 Subject: wx: Fix assert log test Did not work on windows, on windows getItem uses wxLogWindow instead of assert in case of out of range, so the test still caused a log window. --- lib/wx/test/wx_class_SUITE.erl | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index 465299a649..93a4c24a84 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -387,9 +387,18 @@ listCtrlSort(Config) -> Item = wxListItem:new(), - %% Force an assert on (and debug compiled) which 3.0 is by default + %% Test that wx-asserts are sent to error logger + %% Force an assert on 3.0 (when debug compiled which it is by default) wxListItem:setId(Item, 200), - io:format("Got ~p ~n", [wxListCtrl:getItem(LC, Item)]), + case os:type() of + {win32, _} -> + wxListItem:setColumn(Item, 3), + io:format("Got ~p ~n", [wxListCtrl:insertItem(LC, Item)]), + wxListItem:setColumn(Item, 0); + _ -> %% Uses generic listctrl + %% we can't use the code above on linux with wx-2.8.8 because it segfaults. + io:format("Got ~p ~n", [wxListCtrl:getItem(LC, Item)]) + end, wxListItem:setMask(Item, ?wxLIST_MASK_TEXT), _List = wx:map(fun(Int) -> -- cgit v1.2.3 From 132b23a4511dd6f76366bd61eb52d1d11ef5ef35 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 18 Aug 2015 10:19:53 +0200 Subject: dialyzer: Use the recently added orddict:orddict/2 type --- lib/dialyzer/src/dialyzer_contracts.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 0c29d524b5..1079c2e09b 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -46,7 +46,7 @@ -type file_contract() :: {file_line(), #contract{}, Extra :: [_]}. --type plt_contracts() :: [{mfa(), #contract{}}]. % actually, an orddict() +-type plt_contracts() :: orddict:orddict(mfa(), #contract{}). %%----------------------------------------------------------------------- %% Internal record for contracts whose components have not been processed -- cgit v1.2.3 From ba8740af39b7d4c612b2ee55e3bad6fbdcaf1418 Mon Sep 17 00:00:00 2001 From: Steve Vinoski Date: Mon, 10 Aug 2015 08:34:28 -0400 Subject: Handle ERRNO_BLOCK in fd_driver async functions Several users on erlang-questions have reported problems with recent releases where output to standard_error causes standard_error_sup to die from receiving an unexpected eagain error. In the fd_driver, change the fd_async() function to handle EINTR, and change fd_ready_async() to handle ERRNO_BLOCK. Add a new test to standard_error_SUITE to generate output to standard_error and ensure that standard_error_sup does not die. Thanks to Kota Uenishi for contributing the test case. --- lib/kernel/test/standard_error_SUITE.erl | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/standard_error_SUITE.erl b/lib/kernel/test/standard_error_SUITE.erl index e8917bbd47..97ead9b9fd 100644 --- a/lib/kernel/test/standard_error_SUITE.erl +++ b/lib/kernel/test/standard_error_SUITE.erl @@ -21,13 +21,13 @@ -module(standard_error_SUITE). -export([all/0,suite/0]). --export([badarg/1,getopts/1]). +-export([badarg/1,getopts/1,output/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [badarg,getopts]. + [badarg,getopts,output]. badarg(Config) when is_list(Config) -> {'EXIT',{badarg,_}} = (catch io:put_chars(standard_error, [oops])), @@ -37,3 +37,30 @@ badarg(Config) when is_list(Config) -> getopts(Config) when is_list(Config) -> [{encoding,latin1}] = io:getopts(standard_error), ok. + +%% Test that writing a lot of output to standard_error does not cause the +%% processes handling it to terminate like this: +%% +%% =ERROR REPORT==== 9-Aug-2015::23:19:23 === +%% ** Generic server standard_error_sup terminating +%% ** Last message in was {'EXIT',<0.28.0>,eagain} +%% ** When Server state == {state,standard_error,undefined,<0.28.0>, +%% {local,standard_error_sup}} +%% ** Reason for termination == +%% ** eagain +%% +%% This problem, observed with Erlang 18.0.2, was fixed in fd_driver by +%% properly handling EAGAIN if it arises on file descriptor writes. +%% +output(Config) when is_list(Config) -> + Ref = monitor(process, standard_error_sup), + Chars = [ [["1234567890" || _ <- lists:seq(1,10)], $\s, + integer_to_list(L), $\r, $\n] || L <- lists:seq(1, 100) ], + ok = io:put_chars(standard_error, Chars), + receive + {'DOWN', Ref, process, _, _} -> + error(standard_error_noproc) + after + 500 -> + ok + end. -- cgit v1.2.3 From 050d93682e07e0c50667dbfb1468389078b776f2 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 18 Aug 2015 14:54:29 +0200 Subject: dialyzer: Fix a bug concerning parameterized opaque types The example is provided by James Fish in http://erlang.org/pipermail/erlang-questions/2014-December/082204.html. Note that warnings with text such as "the _ variable breaks opaqueness" are still possible. --- .../test/opaque_SUITE_data/src/para/myqueue.erl | 17 +++++++++++++++++ .../test/opaque_SUITE_data/src/para/myqueue_params.erl | 15 +++++++++++++++ lib/hipe/cerl/erl_types.erl | 12 ++++++++---- 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl (limited to 'lib') diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl new file mode 100644 index 0000000000..0f76680464 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl @@ -0,0 +1,17 @@ +-module(myqueue). + +-export([new/0, in/2]). + +-record(myqueue, {queue = queue:new() :: queue:queue({integer(), _})}). + +-opaque myqueue(Item) :: #myqueue{queue :: queue:queue({integer(), Item})}. + +-export_type([myqueue/1]). + +-spec new() -> myqueue(_). +new() -> + #myqueue{queue=queue:new()}. + +-spec in(Item, myqueue(Item)) -> myqueue(Item). +in(Item, #myqueue{queue=Q}) -> + #myqueue{queue=queue:in({1, Item}, Q)}. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl new file mode 100644 index 0000000000..8d766b7804 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl @@ -0,0 +1,15 @@ +-module(myqueue_params). + +-export([new/0, in/2]). + +-record(myqueue_params, {myqueue = myqueue:new() :: myqueue:myqueue(integer())}). + +-type myqueue_params() :: #myqueue_params{myqueue :: + myqueue:myqueue(integer())}. +-spec new() -> myqueue_params(). +new() -> + #myqueue_params{myqueue=myqueue:new()}. + +-spec in(integer(), myqueue_params()) -> myqueue_params(). +in(Item, #myqueue_params{myqueue=Q} = P) when is_integer(Item) -> + P#myqueue_params{myqueue=myqueue:in(Item, Q)}. diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 25cf1a7ae1..a28dfb9e05 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -4244,9 +4244,8 @@ type_from_form(Name, Args, TypeNames, ET, M, MR, V, D, L) -> Rep2 = case t_is_none(Rep1) of true -> Rep1; false -> - Args2 = [subst_all_vars_to_any(ArgType) || - ArgType <- ArgTypes], - t_opaque(Module, Name, Args2, Rep1) + ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), + t_opaque(Module, Name, ArgTypes2, Rep1) end, {Rep2, L2}; error -> @@ -4298,7 +4297,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) -> NewRep1 = choose_opaque_type(NewRep, Type), NewRep2 = case t_is_none(NewRep1) of true -> NewRep1; - false -> t_opaque(Mod, Name, ArgTypes, NewRep1) + false -> + ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), + t_opaque(Mod, Name, ArgTypes2, NewRep1) end, {NewRep2, L2}; error -> @@ -4313,6 +4314,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) -> end end. +subst_all_vars_to_any_list(Types) -> + [subst_all_vars_to_any(Type) || Type <- Types]. + %% Opaque types (both local and remote) are problematic when it comes %% to the limits (TypeNames, D, and L). The reason is that if any() is %% substituted for a more specialized subtype of an opaque type, the -- cgit v1.2.3 From 85524e912e645d528ecd601aaaf8b1697ec92114 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 19 Aug 2015 17:07:48 +0200 Subject: ssl: Remove duplicate documentation Correct merge that went wrong. --- lib/ssl/doc/src/ssl.xml | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib') diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 52d68c1b4a..6c977bdb74 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -664,11 +664,6 @@ fun(srp, Username :: string(), UserState :: term()) -> cipher suite can encipher. - {psk_identity, string()} - Specifies the server identity hint the server presents to the client. - - {log_alert, boolean()} - If false, error reports will not be displayed. {honor_cipher_order, boolean()} If true, use the server's preference for cipher selection. If false (the default), use the client's preference. -- cgit v1.2.3 From c73a53164269fd59a205696467622699dca92d83 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 19 Aug 2015 17:36:36 +0200 Subject: crypto: Make ec_curves/0 return empty list if not supported --- lib/crypto/src/crypto_ec_curves.erl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/crypto/src/crypto_ec_curves.erl b/lib/crypto/src/crypto_ec_curves.erl index fe17643d96..002b03b80c 100644 --- a/lib/crypto/src/crypto_ec_curves.erl +++ b/lib/crypto/src/crypto_ec_curves.erl @@ -4,11 +4,13 @@ curves() -> CryptoSupport = crypto:supports(), - HasGF2m = proplists:get_bool(ec_gf2m, proplists:get_value(public_keys, CryptoSupport)), - prime_curves() ++ characteristic_two_curves(HasGF2m). + PubKeys = proplists:get_value(public_keys, CryptoSupport), + HasEC = proplists:get_bool(ecdh, PubKeys), + HasGF2m = proplists:get_bool(ec_gf2m, PubKeys), + prime_curves(HasEC) ++ characteristic_two_curves(HasGF2m). -prime_curves() -> +prime_curves(true) -> [secp112r1,secp112r2,secp128r1,secp128r2,secp160k1,secp160r1,secp160r2, secp192r1,secp192k1,secp224k1,secp224r1,secp256k1,secp256r1,secp384r1, secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3, @@ -16,7 +18,9 @@ prime_curves() -> brainpoolP160r1,brainpoolP160t1,brainpoolP192r1,brainpoolP192t1, brainpoolP224r1,brainpoolP224t1,brainpoolP256r1,brainpoolP256t1, brainpoolP320r1,brainpoolP320t1,brainpoolP384r1,brainpoolP384t1, - brainpoolP512r1,brainpoolP512t1]. + brainpoolP512r1,brainpoolP512t1]; +prime_curves(_) -> + []. characteristic_two_curves(true) -> [sect113r1,sect113r2,sect131r1,sect131r2,sect163k1,sect163r1, -- cgit v1.2.3 From 4732b2e14710cc6287df82ddcf1bb7d8777706a9 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 20 Aug 2015 08:50:58 +0200 Subject: stdlib: fix a qlc bug introduced in 18.0 As pointed out by roowe, qlc does not handle errors in early compiler (scanner, parser) well in OTP 18.0. --- lib/stdlib/src/qlc_pt.erl | 8 +++++++- lib/stdlib/test/qlc_SUITE.erl | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl index 4e81e2c2dd..9577d17a85 100644 --- a/lib/stdlib/src/qlc_pt.erl +++ b/lib/stdlib/src/qlc_pt.erl @@ -428,7 +428,13 @@ compile_errors(FormsNoShadows) -> end. compile_forms(Forms0, Options) -> - Forms = [F || F <- Forms0, element(1, F) =/= eof] ++ [{eof,anno0()}], + Exclude = fun(eof) -> true; + (warning) -> true; + (error) -> true; + (_) -> false + end, + Forms = ([F || F <- Forms0, not Exclude(element(1, F))] + ++ [{eof,anno0()}]), try case compile:noenv_forms(Forms, compile_options(Options)) of {ok, _ModName, Ws0} -> diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl index 72216bfa0d..52fdb69b73 100644 --- a/lib/stdlib/test/qlc_SUITE.erl +++ b/lib/stdlib/test/qlc_SUITE.erl @@ -74,6 +74,7 @@ otp_5644/1, otp_5195/1, otp_6038_bug/1, otp_6359/1, otp_6562/1, otp_6590/1, otp_6673/1, otp_6964/1, otp_7114/1, otp_7238/1, otp_7232/1, otp_7552/1, otp_6674/1, otp_7714/1, otp_11758/1, + otp_12946/1, manpage/1, @@ -143,7 +144,7 @@ groups() -> {tickets, [], [otp_5644, otp_5195, otp_6038_bug, otp_6359, otp_6562, otp_6590, otp_6673, otp_6964, otp_7114, otp_7232, - otp_7238, otp_7552, otp_6674, otp_7714, otp_11758]}, + otp_7238, otp_7552, otp_6674, otp_7714, otp_11758, otp_12946]}, {compat, [], [backward, forward]}]. init_per_suite(Config) -> @@ -7154,6 +7155,18 @@ otp_6674(Config) when is_list(Config) -> ?line run(Config, Ts). +otp_12946(doc) -> + ["Syntax error."]; +otp_12946(suite) -> []; +otp_12946(Config) when is_list(Config) -> + Text = + <<"-export([init/0]). + init() -> + ok. + y">>, + {errors,[{4,erl_parse,_}],[]} = compile_file(Config, Text, []), + ok. + manpage(doc) -> "Examples from qlc(3)."; manpage(suite) -> []; -- cgit v1.2.3 From d57dea02cc2196ff6160471d06297413af5e20f2 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 21 Aug 2015 11:54:30 +0200 Subject: hipe/dialyzer: Fix a bug concerning opaque types and keydelete/3 Thanks to ILYA Khlopotov for pointing the bug out. --- lib/dialyzer/test/small_SUITE_data/src/keydel.erl | 29 +++++++++++++++++++++++ lib/hipe/cerl/erl_bif_types.erl | 8 +++---- lib/hipe/cerl/erl_types.erl | 14 +++++++++-- 3 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 lib/dialyzer/test/small_SUITE_data/src/keydel.erl (limited to 'lib') diff --git a/lib/dialyzer/test/small_SUITE_data/src/keydel.erl b/lib/dialyzer/test/small_SUITE_data/src/keydel.erl new file mode 100644 index 0000000000..18a5c0670c --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/keydel.erl @@ -0,0 +1,29 @@ +-module(keydel). + +-export([store/3]). + +-record(att, {f}). + +-type attachment() :: list(). + +-opaque att() :: #att{} | attachment(). + +-spec store(atom(), any(), att()) -> att(). +store(Field, undefined, Att) when is_list(Att) -> + lists:keydelete(Field, 1, Att); +store(Field, Value, Att) when is_list(Att) -> + lists:keystore(Field, 1, Att, {Field, Value}); +store(Field, Value, Att) -> + store(Field, Value, upgrade(Att)). + + +-spec upgrade(#att{}) -> attachment(). +upgrade(#att{} = Att) -> + Map = lists:zip( + record_info(fields, att), + lists:seq(2, record_info(size, att)) + ), + %% Don't store undefined elements since that is default + [{F, element(I, Att)} || {F, I} <- Map, element(I, Att) /= undefined]; +upgrade(Att) -> + Att. diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 41a6c731c9..f49089d41c 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2014. All Rights Reserved. +%% Copyright Ericsson AB 2003-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -93,7 +93,7 @@ t_list/0, t_list/1, t_list_elements/2, - t_list_termination/1, + t_list_termination/2, t_mfa/0, t_module/0, t_nil/0, @@ -1336,8 +1336,8 @@ type(lists, foldr, 3, Xs, _Opaques) -> type(lists, foldl, 3, Xs); % same type(lists, keydelete, 3, Xs, Opaques) -> strict(lists, keydelete, 3, Xs, fun ([_, _, L]) -> - Term = t_list_termination(L), - t_sup(Term, erl_types:lift_list_to_pos_empty(L)) + Term = t_list_termination(L, Opaques), + t_sup(Term, erl_types:lift_list_to_pos_empty(L, Opaques)) end, Opaques); type(lists, keyfind, 3, Xs, Opaques) -> strict(lists, keyfind, 3, Xs, diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index a28dfb9e05..cc4fee0853 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -150,7 +150,7 @@ t_list/0, t_list/1, t_list_elements/1, t_list_elements/2, - t_list_termination/1, + t_list_termination/1, t_list_termination/2, t_map/0, t_map/1, t_matchstate/0, @@ -209,7 +209,7 @@ record_field_diffs_to_string/2, subst_all_vars_to_any/1, subst_all_remote/2, - lift_list_to_pos_empty/1, + lift_list_to_pos_empty/1, lift_list_to_pos_empty/2, is_opaque_type/2, is_erl_type/1, atom_to_string/1 @@ -1510,6 +1510,11 @@ t_list_elements(Type, Opaques) -> list_elements(?list(Contents, _, _)) -> Contents; list_elements(?nil) -> ?none. +-spec t_list_termination(erl_type(), opaques()) -> erl_type(). + +t_list_termination(Type, Opaques) -> + do_opaque(Type, Opaques, fun t_list_termination/1). + -spec t_list_termination(erl_type()) -> erl_type(). t_list_termination(?nil) -> ?nil; @@ -1585,6 +1590,11 @@ is_maybe_improper_list(_) -> false. %% %% false = t_is_subtype(t_nil(), Termination), %% ?list(Content, Termination, ?any). +-spec lift_list_to_pos_empty(erl_type(), opaques()) -> erl_type(). + +lift_list_to_pos_empty(Type, Opaques) -> + do_opaque(Type, Opaques, fun lift_list_to_pos_empty/1). + -spec lift_list_to_pos_empty(erl_type()) -> erl_type(). lift_list_to_pos_empty(?nil) -> ?nil; -- cgit v1.2.3 From f3cc9d1b16d86124a70f5dd0609113ec6e3b4dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 5 Aug 2015 19:35:45 +0200 Subject: beam_block: Eliminate redundant wasteful call to opt/1 opt_alloc/1 makes a redundant call to opt/1. It is redundant because the opt/1 function has already been applied to the instruction sequence prior to calling opt_alloc/1. --- lib/compiler/src/beam_block.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 2def3de7f3..4861a2d7ec 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -346,7 +346,7 @@ is_transparent(_, _) -> false. %% Optimises all allocate instructions. opt_alloc([{set,[],[],{alloc,R,{_,Ns,Nh,[]}}}|Is]) -> - [{set,[],[],opt_alloc(Is, Ns, Nh, R)}|opt(Is)]; + [{set,[],[],opt_alloc(Is, Ns, Nh, R)}|Is]; opt_alloc([I|Is]) -> [I|opt_alloc(Is)]; opt_alloc([]) -> []. -- cgit v1.2.3 From 7a47b20c3accf323bdbf7bcf9c86fbf8b2c18e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 22 Jul 2015 09:45:04 +0200 Subject: beam_block: Clean up optimization of move optimizations The 'move' optimization was relatively clean until GC BIFs were introduced. Instead of re-thinking the implementation, the existing code was fixed and patched. The current code unsuccessfully attempts to eliminate 'move' instructions across GC BIF and allocation instructions. We can simplify the code if we give up as soon as we encounter any instruction that allocates. --- lib/compiler/src/beam_block.erl | 83 ++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 4861a2d7ec..58e8f77a2c 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -287,60 +287,51 @@ opt_moves(Ds, Is) -> %% If there is a {move,Dest,FinalDest} instruction %% in the instruction stream, remove the move instruction %% and let FinalDest be the destination. -%% -%% For this optimization to be safe, we must be sure that -%% Dest will not be referenced in any other by other instructions -%% in the rest of the instruction stream. Not even the indirect -%% reference by an instruction that may allocate (such as -%% test_heap/2 or a GC Bif) is allowed. opt_move(Dest, Is) -> - opt_move_1(Dest, Is, ?MAXREG, []). - -opt_move_1(R, [{set,_,_,{alloc,Live,_}}|_]=Is, SafeRegs, Acc) when Live < SafeRegs -> - %% Downgrade number of safe regs and rescan the instruction, as it most probably - %% is a gc_bif instruction. - opt_move_1(R, Is, Live, Acc); -opt_move_1(R, [{set,[{x,X}=D],[R],move}|Is], SafeRegs, Acc) -> - case X < SafeRegs andalso beam_utils:is_killed_block(R, Is) of - true -> opt_move_2(D, Acc, Is); - false -> not_possible - end; -opt_move_1(R, [{set,[D],[R],move}|Is], _SafeRegs, Acc) -> + opt_move_1(Dest, Is, []). + +opt_move_1(R, [{set,[D],[R],move}|Is], Acc) -> + %% Check whether this instruction can be safely eliminated. + %% First check that the source (R) is not used by the + %% instructions that follow. case beam_utils:is_killed_block(R, Is) of - true -> opt_move_2(D, Acc, Is); + true -> opt_move_rev(D, Acc, Is); false -> not_possible end; -opt_move_1(R, [I|Is], SafeRegs, Acc) -> - case is_transparent(R, I) of - false -> not_possible; - true -> opt_move_1(R, Is, SafeRegs, [I|Acc]) - end. +opt_move_1({x,_}, [{set,_,_,{alloc,_,_}}|_], _) -> + %% The optimization is not possible. If the X register is not + %% killed by allocation, the optimization would not be safe. + %% If the X register is killed, it means that there cannot + %% follow a 'move' instruction with this X register as the + %% source. + not_possible; +opt_move_1(R, [{set,_,_,_}=I|Is], Acc) -> + %% If the source register is either killed or used by this + %% instruction, the optimimization is not possible. + case is_killed_or_used(R, I) of + true -> not_possible; + false -> opt_move_1(R, Is, [I|Acc]) + end; +opt_move_1(_, _, _) -> + not_possible. -%% Reverse the instructions, while checking that there are no instructions that -%% would interfere with using the new destination register chosen. +%% Reverse the instructions, while checking that there are no +%% instructions that would interfere with using the new destination +%% register (D). -opt_move_2(D, [I|Is], Acc) -> - case is_transparent(D, I) of - false -> not_possible; - true -> opt_move_2(D, Is, [I|Acc]) - end; -opt_move_2(D, [], Acc) -> {D,Acc}. - -%% is_transparent(Register, Instruction) -> true | false -%% Returns true if Instruction does not in any way references Register -%% (even indirectly by an allocation instruction). -%% Returns false if Instruction does reference Register, or we are -%% not sure. - -is_transparent({x,X}, {set,_,_,{alloc,Live,_}}) when X < Live -> - false; -is_transparent(R, {set,Ds,Ss,_Op}) -> - case member(R, Ds) of - true -> false; - false -> not member(R, Ss) +opt_move_rev(D, [I|Is], Acc) -> + case is_killed_or_used(D, I) of + true -> not_possible; + false -> opt_move_rev(D, Is, [I|Acc]) end; -is_transparent(_, _) -> false. +opt_move_rev(D, [], Acc) -> {D,Acc}. + +%% is_killed_or_used(Register, {set,_,_,_}) -> bool() +%% Test whether the register is used by the instruction. + +is_killed_or_used(R, {set,Ss,Ds,_}) -> + member(R, Ds) orelse member(R, Ss). %% opt_alloc(Instructions) -> Instructions' %% Optimises all allocate instructions. -- cgit v1.2.3 From 02d6135813dc133e018c161d803a642582aac36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 22 Jul 2015 10:20:59 +0200 Subject: beam_block: Improve the move optimizations Here is an example of a move instruction that could not be optimized away because the {x,2} register was not killed: get_tuple_element Reg Pos {x,2} . . . move {x,2} {y,0} put_list {x,2} nil Any We can do the optimization if we replace all occurrences of the {x,2} register as a source with {y,0}: get_tuple_element Reg Pos {y,0} . . . put_list {y,0} nil Dst --- lib/compiler/src/beam_block.erl | 53 +++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 58e8f77a2c..af1bf8fd08 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -291,13 +291,12 @@ opt_moves(Ds, Is) -> opt_move(Dest, Is) -> opt_move_1(Dest, Is, []). -opt_move_1(R, [{set,[D],[R],move}|Is], Acc) -> - %% Check whether this instruction can be safely eliminated. - %% First check that the source (R) is not used by the - %% instructions that follow. - case beam_utils:is_killed_block(R, Is) of - true -> opt_move_rev(D, Acc, Is); - false -> not_possible +opt_move_1(R, [{set,[D],[R],move}|Is0], Acc) -> + %% Provided that the source register is killed by instructions + %% that follow, the optimization is safe. + case eliminate_use_of_from_reg(Is0, R, D, []) of + {yes,Is} -> opt_move_rev(D, Acc, Is); + no -> not_possible end; opt_move_1({x,_}, [{set,_,_,{alloc,_,_}}|_], _) -> %% The optimization is not possible. If the X register is not @@ -333,6 +332,46 @@ opt_move_rev(D, [], Acc) -> {D,Acc}. is_killed_or_used(R, {set,Ss,Ds,_}) -> member(R, Ds) orelse member(R, Ss). +%% eliminate_use_of_from_reg([Instruction], FromRegister, ToRegister, Acc) -> +%% {yes,Is} | no +%% Eliminate any use of FromRegister in the instruction sequence +%% by replacing uses of FromRegister with ToRegister. If FromRegister +%% is referenced by an allocation instruction, return 'no' to indicate +%% that FromRegister is still used and that the optimization is not +%% possible. + +eliminate_use_of_from_reg([{set,_,_,{alloc,Live,_}}|_]=Is0, {x,X}, _, Acc) -> + if + X < Live -> + no; + true -> + {yes,reverse(Acc, Is0)} + end; +eliminate_use_of_from_reg([{set,Ds,Ss0,Op}=I0|Is], From, To, Acc) -> + I = case member(From, Ss0) of + true -> + Ss = [case S of + From -> To; + _ -> S + end || S <- Ss0], + {set,Ds,Ss,Op}; + false -> + I0 + end, + case member(From, Ds) of + true -> + {yes,reverse(Acc, [I|Is])}; + false -> + eliminate_use_of_from_reg(Is, From, To, [I|Acc]) + end; +eliminate_use_of_from_reg([I]=Is, From, _To, Acc) -> + case beam_utils:is_killed_block(From, [I]) of + true -> + {yes,reverse(Acc, Is)}; + false -> + no + end. + %% opt_alloc(Instructions) -> Instructions' %% Optimises all allocate instructions. -- cgit v1.2.3 From 5f431276f1044c673c2e434e003e2f1ffddab341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 23 Jul 2015 17:43:15 +0200 Subject: Optimize get_tuple_element instructions by moving them forward --- lib/compiler/src/beam_block.erl | 53 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index af1bf8fd08..49e66b379b 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -183,7 +183,9 @@ opt_blocks([I|Is]) -> opt_blocks([]) -> []. opt_block(Is0) -> - Is = find_fixpoint(fun opt/1, Is0), + Is = find_fixpoint(fun(Is) -> + opt_tuple_element(opt(Is)) + end, Is0), opt_alloc(Is). find_fixpoint(OptFun, Is0) -> @@ -315,6 +317,55 @@ opt_move_1(R, [{set,_,_,_}=I|Is], Acc) -> opt_move_1(_, _, _) -> not_possible. +%% opt_tuple_element([Instruction]) -> [Instruction] +%% If possible, move get_tuple_element instructions forward +%% in the instruction stream to a move instruction, eliminating +%% the move instruction. Example: +%% +%% get_tuple_element Tuple Pos Dst1 +%% ... +%% move Dst1 Dst2 +%% +%% This code may be possible to rewrite to: +%% +%% %%(Moved get_tuple_element instruction) +%% ... +%% get_tuple_element Tuple Pos Dst2 +%% + +opt_tuple_element([{set,[D],[S],{get_tuple_element,_}}=I|Is0]) -> + case opt_tuple_element_1(Is0, I, {S,D}, []) of + no -> + [I|opt_tuple_element(Is0)]; + {yes,Is} -> + opt_tuple_element(Is) + end; +opt_tuple_element([I|Is]) -> + [I|opt_tuple_element(Is)]; +opt_tuple_element([]) -> []. + +opt_tuple_element_1([{set,_,_,{alloc,_,_}}|_], _, _, _) -> + no; +opt_tuple_element_1([{set,_,_,{'catch',_}}|_], _, _, _) -> + no; +opt_tuple_element_1([{set,[D],[S],move}|Is0], I0, {_,S}, Acc) -> + case eliminate_use_of_from_reg(Is0, S, D, []) of + no -> + no; + {yes,Is} -> + {set,[S],Ss,Op} = I0, + I = {set,[D],Ss,Op}, + {yes,reverse(Acc, [I|Is])} + end; +opt_tuple_element_1([{set,Ds,Ss,_}=I|Is], MovedI, {S,D}=Regs, Acc) -> + case member(S, Ds) orelse member(D, Ss) of + true -> + no; + false -> + opt_tuple_element_1(Is, MovedI, Regs, [I|Acc]) + end; +opt_tuple_element_1(_, _, _, _) -> no. + %% Reverse the instructions, while checking that there are no %% instructions that would interfere with using the new destination %% register (D). -- cgit v1.2.3 From c288ab87fd6cafe22ce46be551baa2e815b495b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 7 Jul 2015 10:45:38 +0200 Subject: Delay get_tuple_element instructions until they are needed When matching tuples, the pattern matching compiler would generate code that would fetch all elements of the tuple that will ultimately be used, *before* testing that (for example) the first element is the correct record tag. For example: is_tuple Fail {x,0} test_arity Fail {x,0} 3 get_tuple_element {x,0} 0 {x,1} get_tuple_element {x,0} 1 {x,2} get_tuple_element {x,0} 2 {x,3} is_eq_exact Fail {x,1} some_tag If {x,2} and {x,3} are not used at label Fail, we can re-arrange the code like this: is_tuple Fail {x,0} test_arity Fail {x,0} 3 get_tuple_element {x,0} 0 {x,1} is_eq_exact Fail {x,1} some_tag get_tuple_element {x,0} 1 {x,2} get_tuple_element {x,0} 2 {x,3} Doing that may be beneficial in two ways. If the branch is taken, we have eliminated the execution of two unnecessary instructions. Even if the branch is never or rarely taken, there is the possibility for more optimizations following the is_eq_exact instructions. For example, imagine that the code looks like this: get_tuple_element {x,0} 1 {x,2} get_tuple_element {x,0} 2 {x,3} move {x,2} {y,0} move {x,3} {y,1} Assuming that {x,2} and {x,3} have no further uses in the code that follows, that can be rewritten to: get_tuple_element {x,0} 1 {y,0} get_tuple_element {x,0} 2 {y,1} When should we perform this optimization? At the very latest, it must be done before opt_blocks/1 in beam_block which does the elimination of unnecessary moves. Actually, we want do the optimization before the blocks have been established, since moving instructions out of one block into another is cumbersome. Therefore, we will do the optimization in a new pass that is run before beam_block. A new pass will make debugging easier, and beam_block already has a fair number of sub passes. --- lib/compiler/src/Makefile | 1 + lib/compiler/src/beam_reorder.erl | 113 ++++++++++++++++++++++++++++++++++++++ lib/compiler/src/beam_utils.erl | 9 +++ lib/compiler/src/compile.erl | 4 +- lib/compiler/src/compiler.app.src | 1 + lib/compiler/test/misc_SUITE.erl | 8 +++ 6 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 lib/compiler/src/beam_reorder.erl (limited to 'lib') diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index 299b2892fc..ae4007c61c 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -62,6 +62,7 @@ MODULES = \ beam_opcodes \ beam_peep \ beam_receive \ + beam_reorder \ beam_split \ beam_trim \ beam_type \ diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl new file mode 100644 index 0000000000..3230e33dbd --- /dev/null +++ b/lib/compiler/src/beam_reorder.erl @@ -0,0 +1,113 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(beam_reorder). + +-export([module/2]). +-import(lists, [member/2,reverse/1]). + +module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> + Fs = [function(F) || F <- Fs0], + {ok,{Mod,Exp,Attr,Fs,Lc}}. + +function({function,Name,Arity,CLabel,Is0}) -> + try + Is = reorder(Is0), + {function,Name,Arity,CLabel,Is} + catch + Class:Error -> + Stack = erlang:get_stacktrace(), + io:fwrite("Function: ~w/~w\n", [Name,Arity]), + erlang:raise(Class, Error, Stack) + end. + +%% reorder(Instructions0) -> Instructions +%% Reorder instructions before the beam_block pass, because reordering +%% will be more cumbersome when the blocks are in place. +%% +%% Execution of get_tuple_element instructions can be delayed until +%% they are actually needed. Consider the sequence: +%% +%% get_tuple_element Tuple Pos Dst +%% test Test Fail Operands +%% +%% If Dst is killed at label Fail (and not referenced in Operands), +%% we can can swap the instructions: +%% +%% test Test Fail Operands +%% get_tuple_element Tuple Pos Dst +%% +%% That can be beneficial in two ways: Firstly, if the branch is taken +%% we have avoided execution of the get_tuple_element instruction. +%% Secondly, even if the branch is not taken, subsequent optimization +%% (opt_blocks/1) may be able to change Dst to the final destination +%% register and eliminate a 'move' instruction. + +reorder(Is) -> + D = beam_utils:index_labels(Is), + reorder_1(Is, D, []). + +reorder_1([{label,L}=I|_], D, Acc) -> + Is = beam_utils:code_at(L, D), + reorder_1(Is, D, [I|Acc]); +reorder_1([{test,is_nonempty_list,_,_}=I|Is], D, Acc) -> + %% The run-time system may combine the is_nonempty_list test with + %% the following get_list instruction. + reorder_1(Is, D, [I|Acc]); +reorder_1([{test,_,_,_}=I, + {select,_,_,_,_}=S|Is], D, Acc) -> + %% There is nothing to gain by inserting a get_tuple_element + %% instruction between the test instruction and the select + %% instruction. + reorder_1(Is, D, [S,I|Acc]); +reorder_1([{test,_,{f,L},Ss}=I|Is0], D0, + [{get_tuple_element,_,_,El}=G|Acc0]=Acc) -> + case member(El, Ss) of + true -> + reorder_1(Is0, D0, [I|Acc]); + false -> + case beam_utils:is_killed_at(El, L, D0) of + true -> + Is = [I,G|Is0], + reorder_1(Is, D0, Acc0); + false -> + case beam_utils:is_killed(El, Is0, D0) of + true -> + Code0 = beam_utils:code_at(L, D0), + Code = [G|Code0], + D = beam_utils:index_label(L, Code, D0), + Is = [I|Is0], + reorder_1(Is, D, Acc0); + false -> + reorder_1(Is0, D0, [I|Acc]) + end + end + end; +reorder_1([{allocate_zero,N,Live}|Is], D, + [{get_tuple_element,_,_,{x,X}}=G|Acc]) + when X+1 =:= Live -> + %% Move allocation instruction upwards past get_tuple_element + %% instructions to give more opportunities for moving + %% get_tuple_element instructions. + I = {allocate_zero,N,X}, + reorder_1([I,G|Is], D, Acc); +reorder_1([I|Is], D, Acc) -> + reorder_1(Is, D, [I|Acc]); +reorder_1([], _, Acc) -> reverse(Acc). diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index fbcd5de1bb..68d6105cfa 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -484,6 +484,15 @@ check_liveness(R, [{get_map_elements,{f,Fail},S,{list,L}}|Is], St0) -> Other end end; +check_liveness(R, [{test_heap,N,Live}|Is], St) -> + I = {block,[{set,[],[],{alloc,Live,{nozero,nostack,N,[]}}}]}, + check_liveness(R, [I|Is], St); +check_liveness(R, [{allocate_zero,N,Live}|Is], St) -> + I = {block,[{set,[],[],{alloc,Live,{zero,N,0,[]}}}]}, + check_liveness(R, [I|Is], St); +check_liveness(R, [{get_list,S,D1,D2}|Is], St) -> + I = {block,[{set,[D1,D2],[S],get_list}]}, + check_liveness(R, [I|Is], St); check_liveness(_R, Is, St) when is_list(Is) -> %% case Is of %% [I|_] -> diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index cf79fdc9f9..605f5b8fd5 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -673,7 +673,9 @@ asm_passes() -> [{pass,beam_a}, {iff,da,{listing,"a"}}, {unless,no_postopt, - [{pass,beam_block}, + [{unless,no_reorder,{pass,beam_reorder}}, + {iff,dre,{listing,"reorder"}}, + {pass,beam_block}, {iff,dblk,{listing,"block"}}, {unless,no_except,{pass,beam_except}}, {iff,dexcept,{listing,"except"}}, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index afb85f4710..62ea9cee80 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -37,6 +37,7 @@ beam_opcodes, beam_peep, beam_receive, + beam_reorder, beam_split, beam_trim, beam_type, diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index 8606935504..3582e055c8 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -192,6 +192,14 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, expect_error(fun() -> beam_a:module(BeamAInput, []) end), + %% beam_reorder + BlockInput = {?MODULE,[{foo,0}],[], + [{function,foo,0,2, + [{label,1}, + {func_info,{atom,?MODULE},{atom,foo},0}, + {label,2}|non_proper_list]}],99}, + expect_error(fun() -> beam_reorder:module(BlockInput, []) end), + %% beam_block BlockInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, -- cgit v1.2.3 From 3640e5c89bda0ca45b3320e8a00efb48b9d9f531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 5 Aug 2015 19:12:15 +0200 Subject: Reorder instructions across try/catch Simplify further optimizations by moving safe instructions to before the 'try' or 'catch' instruction. --- lib/compiler/src/beam_reorder.erl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'lib') diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl index 3230e33dbd..70adca6b04 100644 --- a/lib/compiler/src/beam_reorder.erl +++ b/lib/compiler/src/beam_reorder.erl @@ -64,6 +64,16 @@ reorder(Is) -> D = beam_utils:index_labels(Is), reorder_1(Is, D, []). +reorder_1([{Op,_,_}=TryCatch|[I|Is]=Is0], D, Acc) + when Op =:= 'catch'; Op =:= 'try' -> + %% Don't allow 'try' or 'catch' instructions to split blocks if + %% it can be avoided. + case is_safe(I) of + false -> + reorder_1(Is0, D, [TryCatch|Acc]); + true -> + reorder_1([TryCatch|Is], D, [I|Acc]) + end; reorder_1([{label,L}=I|_], D, Acc) -> Is = beam_utils:code_at(L, D), reorder_1(Is, D, [I|Acc]); @@ -111,3 +121,14 @@ reorder_1([{allocate_zero,N,Live}|Is], D, reorder_1([I|Is], D, Acc) -> reorder_1(Is, D, [I|Acc]); reorder_1([], _, Acc) -> reverse(Acc). + +%% is_safe(Instruction) -> true|false +%% Test whether an instruction is safe (cannot cause an exception). + +is_safe({kill,_}) -> true; +is_safe({move,_,_}) -> true; +is_safe({put,_}) -> true; +is_safe({put_list,_,_,_}) -> true; +is_safe({put_tuple,_,_}) -> true; +is_safe({test_heap,_,_}) -> true; +is_safe(_) -> false. -- cgit v1.2.3 From 30cc5c902d9e653d48452a7f84fcd664cfc3f0a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 5 Aug 2015 19:19:56 +0200 Subject: Put 'try' in blocks to optimize allocation instructions Put 'try' instructions inside block to improve the optimization of allocation instructions. Currently, the compiler only looks at initialization of y registers inside blocks when determining which y registers that will be "naturally" initialized. --- lib/compiler/src/beam_block.erl | 7 +++++-- lib/compiler/src/beam_jump.erl | 2 +- lib/compiler/src/beam_split.erl | 4 ++-- lib/compiler/src/beam_type.erl | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 49e66b379b..0b284299be 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -149,7 +149,10 @@ collect({put_map,F,Op,S,D,R,{list,Puts}}) -> collect({get_map_elements,F,S,{list,Gets}}) -> {Ss,Ds} = beam_utils:split_even(Gets), {set,Ds,[S|Ss],{get_map_elements,F}}; -collect({'catch',R,L}) -> {set,[R],[],{'catch',L}}; +collect({'catch'=Op,R,L}) -> + {set,[R],[],{try_catch,Op,L}}; +collect({'try'=Op,R,L}) -> + {set,[R],[],{try_catch,Op,L}}; collect(fclearerror) -> {set,[],[],fclearerror}; collect({fcheckerror,{f,0}}) -> {set,[],[],fcheckerror}; collect({fmove,S,D}) -> {set,[D],[S],fmove}; @@ -346,7 +349,7 @@ opt_tuple_element([]) -> []. opt_tuple_element_1([{set,_,_,{alloc,_,_}}|_], _, _, _) -> no; -opt_tuple_element_1([{set,_,_,{'catch',_}}|_], _, _, _) -> +opt_tuple_element_1([{set,_,_,{try_catch,_,_}}|_], _, _, _) -> no; opt_tuple_element_1([{set,[D],[S],move}|Is0], I0, {_,S}, Acc) -> case eliminate_use_of_from_reg(Is0, S, D, []) of diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index 5e58e0f6ac..3b6eb19fe8 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -495,7 +495,7 @@ is_label_used_in_block({set,_,_,Info}, Lbl) -> {alloc,_,{gc_bif,_,{f,F}}} -> F =:= Lbl; {alloc,_,{put_map,_,{f,F}}} -> F =:= Lbl; {get_map_elements,{f,F}} -> F =:= Lbl; - {'catch',{f,F}} -> F =:= Lbl; + {try_catch,_,{f,F}} -> F =:= Lbl; {alloc,_,_} -> false; {put_tuple,_} -> false; {get_tuple_element,_} -> false; diff --git a/lib/compiler/src/beam_split.erl b/lib/compiler/src/beam_split.erl index 3be9311080..bb1c0e23a9 100644 --- a/lib/compiler/src/beam_split.erl +++ b/lib/compiler/src/beam_split.erl @@ -57,8 +57,8 @@ split_block([{set,[D],[S|Puts],{alloc,R,{put_map,Op,{f,Lbl}=Fail}}}|Is], split_block([{set,Ds,[S|Ss],{get_map_elements,Fail}}|Is], Bl, Acc) -> Gets = beam_utils:join_even(Ss,Ds), split_block(Is, [], [{get_map_elements,Fail,S,{list,Gets}}|make_block(Bl, Acc)]); -split_block([{set,[R],[],{'catch',L}}|Is], Bl, Acc) -> - split_block(Is, [], [{'catch',R,L}|make_block(Bl, Acc)]); +split_block([{set,[R],[],{try_catch,Op,L}}|Is], Bl, Acc) -> + split_block(Is, [], [{Op,R,L}|make_block(Bl, Acc)]); split_block([{set,[],[],{line,_}=Line}|Is], Bl, Acc) -> split_block(Is, [], [Line|make_block(Bl, Acc)]); split_block([I|Is], Bl, Acc) -> diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index 5298589f83..40d67d1670 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -92,7 +92,7 @@ simplify_basic_1([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Acc) - Ts = update(I, Ts0), simplify_basic_1(Is0, Ts, [I|Acc]) end; -simplify_basic_1([{set,_,_,{'catch',_}}=I|Is], _Ts, Acc) -> +simplify_basic_1([{set,_,_,{try_catch,_,_}}=I|Is], _Ts, Acc) -> simplify_basic_1(Is, tdb_new(), [I|Acc]); simplify_basic_1([{test,is_tuple,_,[R]}=I|Is], Ts, Acc) -> case tdb_find(R, Ts) of @@ -199,7 +199,7 @@ simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0, Ts = tdb_update([{D0,float}], Ts0), simplify_float_1(Is, Ts, Rs, Acc) end; -simplify_float_1([{set,_,_,{'catch',_}}=I|Is]=Is0, _Ts, Rs0, Acc0) -> +simplify_float_1([{set,_,_,{try_catch,_,_}}=I|Is]=Is0, _Ts, Rs0, Acc0) -> Acc = flush_all(Rs0, Is0, Acc0), simplify_float_1(Is, tdb_new(), Rs0, [I|Acc]); simplify_float_1([{set,_,_,{line,_}}=I|Is], Ts, Rs, Acc) -> -- cgit v1.2.3 From f63b503f9c7ea4d5824899dc5b287075e261e6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 10 Aug 2015 14:27:50 +0200 Subject: Move rewriting of select_val to is_boolean from beam_peep to beam_dead We can rewrite more instances of select_val to is_boolean because it is not necessary that a particular label follows the select_val. --- lib/compiler/src/beam_dead.erl | 24 +++++++++++++++++++++--- lib/compiler/src/beam_peep.erl | 28 ---------------------------- 2 files changed, 21 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index ead88b57e9..0cb5040177 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -242,8 +242,15 @@ backward([{select,select_val,Reg,{f,Fail0},List0}|Is], D, Acc) -> List = shortcut_select_list(List0, Reg, D, []), Fail1 = shortcut_label(Fail0, D), Fail = shortcut_bs_test(Fail1, Is, D), - Sel = {select,select_val,Reg,{f,Fail},List}, - backward(Is, D, [Sel|Acc]); + case List of + [{atom,B1},F,{atom,B2},F] when B1 =:= not B2 -> + Test = {test,is_boolean,{f,Fail},[Reg]}, + Jump = {jump,F}, + backward([Jump,Test|Is], D, Acc); + [_|_] -> + Sel = {select,select_val,Reg,{f,Fail},List}, + backward(Is, D, [Sel|Acc]) + end; backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) -> To = shortcut_select_label(To0, Reg, Src, D), Jump = {jump,{f,To}}, @@ -295,7 +302,18 @@ backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) -> is_eq_exact -> combine_eqs(To, Ops0, D, Acc); _ -> {test,Op,{f,To},Ops0} end, - backward(Is, D, [I|Acc]); + case {I,Acc} of + {{test,is_atom,Fail,Ops0},[{test,is_boolean,Fail,Ops0}|_]} -> + %% An is_atom test before an is_boolean test (with the + %% same failure label) is redundant. + backward(Is, D, Acc); + {{test,_,_,_},_} -> + %% Still a test instruction. Done. + backward(Is, D, [I|Acc]); + {_,_} -> + %% Rewritten to a select_val. Rescan. + backward([I|Is], D, Acc) + end; backward([{test,Op,{f,To0},Live,Ops0,Dst}|Is], D, Acc) -> To1 = shortcut_bs_test(To0, Is, D), To2 = shortcut_label(To1, D), diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl index 17fd2e502a..75be86b83f 100644 --- a/lib/compiler/src/beam_peep.erl +++ b/lib/compiler/src/beam_peep.erl @@ -65,18 +65,6 @@ function({function,Name,Arity,CLabel,Is0}) -> %% InEncoding =:= latin1, OutEncoding =:= unicode; %% InEncoding =:= latin1, OutEncoding =:= utf8 -> %% -%% (2) A select_val/4 instruction that only verifies that -%% its argument is either 'true' or 'false' can be -%% be replaced with an is_boolean/2 instruction. That is: -%% -%% select_val Reg Fail [ true Next false Next ] -%% Next: ... -%% -%% can be rewritten to -%% -%% is_boolean Fail Reg -%% Next: ... -%% peep(Is) -> peep(Is, gb_sets:empty(), []). @@ -95,12 +83,6 @@ peep([{gc_bif,_,_,_,_,Dst}=I|Is], SeenTests0, Acc) -> %% Kill all remembered tests that depend on the destination register. SeenTests = kill_seen(Dst, SeenTests0), peep(Is, SeenTests, [I|Acc]); -peep([{test,is_boolean,{f,Fail},Ops}|_]=Is, SeenTests, - [{test,is_atom,{f,Fail},Ops}|Acc]) -> - %% The previous is_atom/2 test (with the same failure label) is redundant. - %% (If is_boolean(Src) is true, is_atom(Src) is also true, so it is - %% OK to still remember that we have seen is_atom/1.) - peep(Is, SeenTests, Acc); peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) -> case beam_utils:is_pure_test(I) of false -> @@ -121,16 +103,6 @@ peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) -> peep(Is, SeenTests, [I|Acc]) end end; -peep([{select,select_val,Src,Fail, - [{atom,false},{f,L},{atom,true},{f,L}]}| - [{label,L}|_]=Is], SeenTests, Acc) -> - I = {test,is_boolean,Fail,[Src]}, - peep([I|Is], SeenTests, Acc); -peep([{select,select_val,Src,Fail, - [{atom,true},{f,L},{atom,false},{f,L}]}| - [{label,L}|_]=Is], SeenTests, Acc) -> - I = {test,is_boolean,Fail,[Src]}, - peep([I|Is], SeenTests, Acc); peep([I|Is], _, Acc) -> %% An unknown instruction. Throw away all information we %% have collected about test instructions. -- cgit v1.2.3 From e92ad3c4d6358cecbba7643ccc14610957ad79ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 10 Aug 2015 06:25:00 +0200 Subject: v3_core: Improve code generation for guards When translating guards to Core Erlang, it is sometimes necessary to add an is_boolean/1 guard test. Here is an example when it is necessary: o(A, B) when A or B -> ok. That would be translated to something like: o(A, B) when ((A =:= true) or (B =:= true)) and is_boolean(A) and is_boolean(B) -> ok. The is_boolean/1 tests are necessary to ensure that the guard fails for calls such as: o(true, not_boolean) However, because of a bug in v3_core, is_boolean/1 tests were added when they were not necessary. Here is an example: f(B) when not B -> ok. That would be translated to: f(B) when (B =:= false) and is_boolean(B) -> ok. The following translation will work just as well. f(B) when B =:= false -> ok. Correct the bug to suppress those unnecessary is_boolean/1 tests. --- lib/compiler/src/v3_core.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 0941ad5dd5..7c229210a0 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -469,7 +469,8 @@ unforce_tree([#iset{var=#c_var{name=V},arg=Arg0}|Es], D0) -> unforce_tree(Es, D); unforce_tree([#icall{}=Call], D) -> unforce_tree_subst(Call, D); -unforce_tree([Top], _) -> Top. +unforce_tree([#c_var{name=V}], D) -> + gb_trees:get(V, D). unforce_tree_subst(#icall{module=#c_literal{val=erlang}, name=#c_literal{val='=:='}, -- cgit v1.2.3 From 93c5e457faeccfd8ccbb1e6c587ad6df1f200408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 21 Aug 2015 07:07:49 +0200 Subject: beam_validator: Don't allow x(1023) to be used In 45f469ca0890, the BEAM loader started to use x(1023) as scratch register for some instructions. Therefore we should not allow x(1023) to be used in code emitted by the compiler. --- lib/compiler/src/beam_block.erl | 1 - lib/compiler/src/beam_bool.erl | 2 -- lib/compiler/src/beam_clean.erl | 2 +- lib/compiler/src/beam_validator.erl | 31 +++++++++++++--------- lib/compiler/test/beam_validator_SUITE.erl | 6 ++--- .../test/beam_validator_SUITE_data/xrange.S | 4 +-- 6 files changed, 24 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 0b284299be..4e179daa0e 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -24,7 +24,6 @@ -export([module/2]). -import(lists, [mapfoldl/3,reverse/1,reverse/2,foldl/3,member/2]). --define(MAXREG, 1024). module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) -> {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0), diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl index 14b6381230..c9e103eae9 100644 --- a/lib/compiler/src/beam_bool.erl +++ b/lib/compiler/src/beam_bool.erl @@ -25,8 +25,6 @@ -import(lists, [reverse/1,reverse/2,foldl/3,mapfoldl/3,map/2]). --define(MAXREG, 1024). - -record(st, {next, %Next label number. ll %Live regs at labels. diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl index 919ee3ee7d..7d66985791 100644 --- a/lib/compiler/src/beam_clean.erl +++ b/lib/compiler/src/beam_clean.erl @@ -141,7 +141,7 @@ renumber_labels([{bif,is_record,{f,_}, renumber_labels(Is, Acc, St); renumber_labels([{test,is_record,{f,_}=Fail, [Term,{atom,Tag}=TagAtom,{integer,Arity}]}|Is0], Acc, St) -> - Tmp = {x,1023}, + Tmp = {x,1022}, Is = case is_record_tuple(Term, Tag, Arity) of yes -> Is0; diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 942d69a756..ab5fedf3bf 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -31,8 +31,6 @@ -import(lists, [reverse/1,foldl/3,foreach/2,dropwhile/2]). --define(MAXREG, 1024). - %%-define(DEBUG, 1). -ifdef(DEBUG). -define(DBG_FORMAT(F, D), (io:format((F), (D)))). @@ -970,9 +968,9 @@ get_fls(#vst{current=#st{fls=Fls}}) when is_atom(Fls) -> Fls. init_fregs() -> 0. -set_freg({fr,Fr}, #vst{current=#st{f=Fregs0}=St}=Vst) +set_freg({fr,Fr}=Freg, #vst{current=#st{f=Fregs0}=St}=Vst) when is_integer(Fr), 0 =< Fr -> - limit_check(Fr), + check_limit(Freg), Bit = 1 bsl Fr, if Fregs0 band Bit =:= 0 -> @@ -985,9 +983,10 @@ set_freg(Fr, _) -> error({bad_target,Fr}). assert_freg_set({fr,Fr}=Freg, #vst{current=#st{f=Fregs}}) when is_integer(Fr), 0 =< Fr -> if - Fregs band (1 bsl Fr) =/= 0 -> - limit_check(Fr); - true -> error({uninitialized_reg,Freg}) + (Fregs bsr Fr) band 1 =:= 0 -> + error({uninitialized_reg,Freg}); + true -> + ok end; assert_freg_set(Fr, _) -> error({bad_source,Fr}). @@ -1066,16 +1065,16 @@ set_type(Type, {x,_}=Reg, Vst) -> set_type_reg(Type, Reg, Vst); set_type(Type, {y,_}=Reg, Vst) -> set_type_y(Type, Reg, Vst); set_type(_, _, #vst{}=Vst) -> Vst. -set_type_reg(Type, {x,X}, #vst{current=#st{x=Xs}=St}=Vst) +set_type_reg(Type, {x,X}=Reg, #vst{current=#st{x=Xs}=St}=Vst) when is_integer(X), 0 =< X -> - limit_check(X), + check_limit(Reg), Vst#vst{current=St#st{x=gb_trees:enter(X, Type, Xs)}}; set_type_reg(Type, Reg, Vst) -> set_type_y(Type, Reg, Vst). set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys0}=St}=Vst) when is_integer(Y), 0 =< Y -> - limit_check(Y), + check_limit(Reg), Ys = case gb_trees:lookup(Y, Ys0) of none -> error({invalid_store,Reg,Type}); @@ -1591,9 +1590,15 @@ return_type_math(pow, 2) -> {float,[]}; return_type_math(pi, 0) -> {float,[]}; return_type_math(F, A) when is_atom(F), is_integer(A), A >= 0 -> term. -limit_check(Num) when is_integer(Num), Num >= ?MAXREG -> - error(limit); -limit_check(_) -> ok. +check_limit({x,X}) when is_integer(X), X < 1023 -> + %% Note: x(1023) is reserved for use by the BEAM loader. + ok; +check_limit({y,Y}) when is_integer(Y), Y < 1024 -> + ok; +check_limit({fr,Fr}) when is_integer(Fr), Fr < 1024 -> + ok; +check_limit(_) -> + error(limit). min(A, B) when is_integer(A), is_integer(B), A < B -> A; min(A, B) when is_integer(A), is_integer(B) -> B. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 69391b15eb..d6deb4a730 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -107,13 +107,13 @@ xrange(Config) when is_list(Config) -> {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4, {uninitialized_reg,{x,-1}}}}, {{t,sum_2,2}, - {{bif,'+',{f,0},[{x,0},{x,1024}],{x,0}},4, - {uninitialized_reg,{x,1024}}}}, + {{bif,'+',{f,0},[{x,0},{x,1023}],{x,0}},4, + {uninitialized_reg,{x,1023}}}}, {{t,sum_3,2}, {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4, {invalid_store,{x,-1},number}}}, {{t,sum_4,2}, - {{bif,'+',{f,0},[{x,0},{x,1}],{x,1024}},4,limit}}] = Errors, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,1023}},4,limit}}] = Errors, ok. yrange(Config) when is_list(Config) -> diff --git a/lib/compiler/test/beam_validator_SUITE_data/xrange.S b/lib/compiler/test/beam_validator_SUITE_data/xrange.S index c6f20288f7..a76408dde3 100644 --- a/lib/compiler/test/beam_validator_SUITE_data/xrange.S +++ b/lib/compiler/test/beam_validator_SUITE_data/xrange.S @@ -20,7 +20,7 @@ {label,3}. {func_info,{atom,t},{atom,sum_2},2}. {label,4}. - {bif,'+',{f,0},[{x,0},{x,1024}],{x,0}}. + {bif,'+',{f,0},[{x,0},{x,1023}],{x,0}}. {'%live',1}. return. @@ -38,7 +38,7 @@ {label,7}. {func_info,{atom,t},{atom,sum_4},2}. {label,8}. - {bif,'+',{f,0},[{x,0},{x,1}],{x,1024}}. + {bif,'+',{f,0},[{x,0},{x,1}],{x,1023}}. {'%live',1}. return. -- cgit v1.2.3 From 1d967bb8406dfd475265520b24ac4bcf099a3df1 Mon Sep 17 00:00:00 2001 From: Constantin Rack Date: Mon, 24 Aug 2015 09:41:12 +0200 Subject: Fix typo: message to send is in x(1) not x(0) --- lib/compiler/src/genop.tab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab index 8464af3dd0..8f7b5add1d 100755 --- a/lib/compiler/src/genop.tab +++ b/lib/compiler/src/genop.tab @@ -137,7 +137,7 @@ BEAM_FORMAT_NUMBER=0 # Sending & receiving. # ## @spec send -## @doc Send argument in x(0) as a message to the destination process in x(0). +## @doc Send argument in x(1) as a message to the destination process in x(0). ## The message in x(1) ends up as the result of the send in x(0). 20: send/0 -- cgit v1.2.3 From 02abeffc9d753b5fcd1ce7da93f437887f574bad Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Fri, 21 Aug 2015 13:13:17 +0200 Subject: Optimize zip:unzip/2 when uncompressing to memory Optimize the case where we are appending to the end of the binary, use binary syntax to create binaries with room for expansion in the next loop, instead of using iolist_to_binary which creates a binary of the exact size and needs to be copied in each loop. Also remove support the unused Acc as iolists. --- lib/stdlib/src/zip.erl | 68 ++++++++++++++++---------------------------------- 1 file changed, 22 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl index d6031dabbc..bec0bd3f6d 100644 --- a/lib/stdlib/src/zip.erl +++ b/lib/stdlib/src/zip.erl @@ -1550,57 +1550,33 @@ unix_extra_field_and_var_from_bin(_) -> %% A pwrite-like function for iolists (used by memory-option) -split_iolist(B, Pos) when is_binary(B) -> - split_binary(B, Pos); -split_iolist(L, Pos) when is_list(L) -> - splitter([], L, Pos). - -splitter(Left, Right, 0) -> - {Left, Right}; -splitter(Left, [A | Right], RelPos) when is_list(A) or is_binary(A) -> - Sz = erlang:iolist_size(A), - case Sz > RelPos of - true -> - {Leftx, Rightx} = split_iolist(A, RelPos), - {[Left | Leftx], [Rightx, Right]}; - _ -> - splitter([Left | A], Right, RelPos - Sz) - end; -splitter(Left, [A | Right], RelPos) when is_integer(A) -> - splitter([Left, A], Right, RelPos - 1); -splitter(Left, Right, RelPos) when is_binary(Right) -> - splitter(Left, [Right], RelPos). +pwrite_binary(B, Pos, Bin) when byte_size(B) =:= Pos -> + append_bins(Bin, B); +pwrite_binary(B, Pos, Bin) -> + erlang:iolist_to_binary(pwrite_iolist(B, Pos, Bin)). -skip_iolist(B, Pos) when is_binary(B) -> - case B of - <<_:Pos/binary, Bin/binary>> -> Bin; - _ -> <<>> - end; -skip_iolist(L, Pos) when is_list(L) -> - skipper(L, Pos). - -skipper(Right, 0) -> - Right; -skipper([A | Right], RelPos) when is_list(A) or is_binary(A) -> - Sz = erlang:iolist_size(A), - case Sz > RelPos of - true -> - Rightx = skip_iolist(A, RelPos), - [Rightx, Right]; - _ -> - skip_iolist(Right, RelPos - Sz) - end; -skipper([A | Right], RelPos) when is_integer(A) -> - skip_iolist(Right, RelPos - 1). +append_bins([Bin|Bins], B) when is_binary(Bin) -> + append_bins(Bins, <>); +append_bins([List|Bins], B) when is_list(List) -> + append_bins(Bins, append_bins(List, B)); +append_bins(Bin, B) when is_binary(Bin) -> + <>; +append_bins([_|_]=List, B) -> + <>; +append_bins([], B) -> + B. -pwrite_iolist(Iolist, Pos, Bin) -> - {Left, Right} = split_iolist(Iolist, Pos), +pwrite_iolist(B, Pos, Bin) -> + {Left, Right} = split_binary(B, Pos), Sz = erlang:iolist_size(Bin), - R = skip_iolist(Right, Sz), + R = skip_bin(Right, Sz), [Left, Bin | R]. -pwrite_binary(B, Pos, Bin) -> - erlang:iolist_to_binary(pwrite_iolist(B, Pos, Bin)). +skip_bin(B, Pos) when is_binary(B) -> + case B of + <<_:Pos/binary, Bin/binary>> -> Bin; + _ -> <<>> + end. %% ZIP header manipulations -- cgit v1.2.3 From 528b41c676cedeb88859c910d7384c20e3407dc7 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 24 Aug 2015 16:00:13 +0200 Subject: ssh: dependencies added in ssh/src/Makefile --- lib/ssh/src/Makefile | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'lib') diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile index 98fb90d7c4..b44c8eef35 100644 --- a/lib/ssh/src/Makefile +++ b/lib/ssh/src/Makefile @@ -144,3 +144,78 @@ release_spec: opt release_docs_spec: + +deps: + erlc -M $(ERL_FILES) \ + | sed 's@$(ERL_TOP)/lib@../..@g' \ + | sed 's/\.$(EMULATOR)/\.$$\(EMULATOR\)/' \ + | sed 's@^ssh_@$$(EBIN)/ssh_@' + +ssh.$(EMULATOR): ssh.erl ssh.hrl ssh_connect.hrl \ + ../../public_key/include/public_key.hrl \ + ../../public_key/include/OTP-PUB-KEY.hrl \ + ../../public_key/include/PKCS-FRAME.hrl \ + ../../kernel/include/file.hrl +$(EBIN)/ssh_sup.$(EMULATOR): ssh_sup.erl +sshc_sup.$(EMULATOR): sshc_sup.erl +sshd_sup.$(EMULATOR): sshd_sup.erl ssh.hrl +$(EBIN)/ssh_connection_sup.$(EMULATOR): ssh_connection_sup.erl +$(EBIN)/ssh_connection.$(EMULATOR): ssh_connection.erl ssh.hrl ssh_connect.hrl \ + ssh_transport.hrl +$(EBIN)/ssh_connection_handler.$(EMULATOR): ssh_connection_handler.erl ssh.hrl \ + ssh_transport.hrl ssh_auth.hrl ssh_connect.hrl +$(EBIN)/ssh_shell.$(EMULATOR): ssh_shell.erl ssh_connect.hrl +$(EBIN)/ssh_system_sup.$(EMULATOR): ssh_system_sup.erl ssh.hrl +$(EBIN)/ssh_subsystem_sup.$(EMULATOR): ssh_subsystem_sup.erl +$(EBIN)/ssh_channel_sup.$(EMULATOR): ssh_channel_sup.erl +$(EBIN)/ssh_acceptor_sup.$(EMULATOR): ssh_acceptor_sup.erl ssh.hrl +$(EBIN)/ssh_acceptor.$(EMULATOR): ssh_acceptor.erl ssh.hrl +$(EBIN)/ssh_app.$(EMULATOR): ssh_app.erl +$(EBIN)/ssh_auth.$(EMULATOR): ssh_auth.erl \ + ../../public_key/include/public_key.hrl \ + ../../public_key/include/OTP-PUB-KEY.hrl \ + ../../public_key/include/PKCS-FRAME.hrl \ + ssh.hrl ssh_auth.hrl ssh_transport.hrl +$(EBIN)/ssh_bits.$(EMULATOR): ssh_bits.erl ssh.hrl +$(EBIN)/ssh_cli.$(EMULATOR): ssh_cli.erl ssh.hrl ssh_connect.hrl +$(EBIN)/ssh_file.$(EMULATOR): ssh_file.erl \ + ../../public_key/include/public_key.hrl \ + ../../public_key/include/OTP-PUB-KEY.hrl \ + ../../public_key/include/PKCS-FRAME.hrl \ + ../../kernel/include/file.hrl ssh.hrl +$(EBIN)/ssh_io.$(EMULATOR): ssh_io.erl ssh.hrl +$(EBIN)/ssh_info.$(EMULATOR): ssh_info.erl +$(EBIN)/ssh_message.$(EMULATOR): ssh_message.erl \ + ../../public_key/include/public_key.hrl \ + ../../public_key/include/OTP-PUB-KEY.hrl \ + ../../public_key/include/PKCS-FRAME.hrl \ + ssh.hrl ssh_connect.hrl ssh_auth.hrl ssh_transport.hrl +$(EBIN)/ssh_no_io.$(EMULATOR): ssh_no_io.erl ssh_transport.hrl +$(EBIN)/ssh_sftp.$(EMULATOR): ssh_sftp.erl \ + ../../kernel/include/file.hrl ssh.hrl \ + ssh_xfer.hrl +$(EBIN)/ssh_sftpd.$(EMULATOR): ssh_sftpd.erl \ + ../../kernel/include/file.hrl ssh.hrl \ + ssh_xfer.hrl +$(EBIN)/ssh_sftpd_file.$(EMULATOR): ssh_sftpd_file.erl +$(EBIN)/ssh_transport.$(EMULATOR): ssh_transport.erl \ + ../../public_key/include/public_key.hrl \ + ../../public_key/include/OTP-PUB-KEY.hrl \ + ../../public_key/include/PKCS-FRAME.hrl \ + ../../kernel/include/inet.hrl \ + ssh_transport.hrl ssh.hrl +$(EBIN)/ssh_xfer.$(EMULATOR): ssh_xfer.erl ssh.hrl ssh_xfer.hrl +$(EBIN)/ssh_sftpd_file_api.$(EMULATOR): ssh_sftpd_file_api.erl +$(EBIN)/ssh_channel.$(EMULATOR): ssh_channel.erl ssh_connect.hrl +$(EBIN)/ssh_daemon_channel.$(EMULATOR): ssh_daemon_channel.erl +$(EBIN)/ssh_client_key_api.$(EMULATOR): ssh_client_key_api.erl \ + ../../public_key/include/public_key.hrl \ + ../../public_key/include/OTP-PUB-KEY.hrl \ + ../../public_key/include/PKCS-FRAME.hrl \ + ssh.hrl +$(EBIN)/ssh_server_key_api.$(EMULATOR): ssh_server_key_api.erl \ + ../../public_key/include/public_key.hrl \ + ../../public_key/include/OTP-PUB-KEY.hrl \ + ../../public_key/include/PKCS-FRAME.hrl \ + ssh.hrl + -- cgit v1.2.3 From b5eba8b61ce3ea0058ba37df288738586c68d6ac Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 20 Aug 2015 20:18:57 +0200 Subject: erts: Change THE_NON_VALUE to not be hard coded in hipe compiler Instead ask running VM for the value of THE_NON_VALUE, which is different between opt and debug VM. Same hipe compiler can now compile for both opt and debug VM. --- lib/hipe/main/hipe.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src index 008393e63c..aa86b6dc5b 100644 --- a/lib/hipe/main/hipe.app.src +++ b/lib/hipe/main/hipe.app.src @@ -225,4 +225,4 @@ {applications, [kernel,stdlib]}, {env, []}, {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-2.5","kernel-3.0", - "erts-7.0","compiler-5.0"]}]}. + "erts-7.1","compiler-5.0"]}]}. -- cgit v1.2.3 From bc28d2308209ffc7cec0218028fc62b88a413f0f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 24 Aug 2015 17:18:25 +0200 Subject: ssh: doubled short timetrap in testcase --- lib/ssh/test/ssh_sftp_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index bab5bf9fe9..8d0b887d83 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -291,7 +291,7 @@ init_per_testcase(Case, Config0) -> prep(Config0), Config1 = lists:keydelete(watchdog, 1, Config0), Config2 = lists:keydelete(sftp, 1, Config1), - Dog = ct:timetrap(?default_timeout), + Dog = ct:timetrap(2 * ?default_timeout), User = ?config(user, Config0), Passwd = ?config(passwd, Config0), -- cgit v1.2.3 From 502189ba42469d3332bc0658caa2bd0de1e3fcb9 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Mon, 24 Aug 2015 16:14:49 +0200 Subject: Add service_opt() strict_mbit There are differing opinions on whether or not reception of an arbitrary AVP setting the M-bit is an error. 1.3.4 of RFC 6733 says this about how an existing Diameter application may be modified: o The M-bit allows the sender to indicate to the receiver whether or not understanding the semantics of an AVP and its content is mandatory. If the M-bit is set by the sender and the receiver does not understand the AVP or the values carried within that AVP, then a failure is generated (see Section 7). It is the decision of the protocol designer when to develop a new Diameter application rather than extending Diameter in other ways. However, a new Diameter application MUST be created when one or more of the following criteria are met: M-bit Setting An AVP with the M-bit in the MUST column of the AVP flag table is added to an existing Command/Application. An AVP with the M-bit in the MAY column of the AVP flag table is added to an existing Command/Application. The point here is presumably interoperability: that the command grammar should specify explicitly what mandatory AVPs much be understood, and that anything more is an error. On the other hand, 3.2 says thus about command grammars: avp-name = avp-spec / "AVP" ; The string "AVP" stands for *any* arbitrary AVP ; Name, not otherwise listed in that Command Code ; definition. The inclusion of this string ; is recommended for all CCFs to allow for ; extensibility. This renders 1.3.4 pointless unless "*any* AVP" is qualified by "not setting the M-bit", since the sender can effectively violate 1.3.4 without this necessitating an error at the receiver. If clients add arbitrary AVPs setting the M-bit then request handling becomes more implementation-dependent. The current interpretation in diameter is strict: if a command grammar doesn't explicitly allow an AVP setting the M-bit then reception of such an AVP is regarded as an error. The strict_mbit option now allows this behaviour to be changed, false turning all responsibility for the M-bit over to the user. --- lib/diameter/doc/src/diameter.xml | 43 ++++++++++++++++++++++++++++++ lib/diameter/include/diameter_gen.hrl | 8 ++++-- lib/diameter/src/base/diameter.erl | 1 + lib/diameter/src/base/diameter_codec.erl | 10 ++++--- lib/diameter/src/base/diameter_config.erl | 3 +++ lib/diameter/src/base/diameter_service.erl | 4 ++- lib/diameter/src/base/diameter_traffic.erl | 4 ++- 7 files changed, 65 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index 854bc5b432..b0cff32c9a 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -912,6 +912,49 @@ Options monitor and link are ignored.

Defaults to the empty list.

+ +{strict_mbit, boolean()} + +

+Whether or not to regard an AVP setting the M-bit as erroneous when +the command grammar in question does not explicitly allow the AVP. +If true then such AVPs are regarded as 5001 errors, +DIAMETER_AVP_UNSUPPORTED. +If false then the M-bit is ignored and policing +it becomes the receiver's responsibility.

+ +

+Defaults to true.

+ + +

+RFC 6733 is unclear about the semantics of the M-bit. +One the one hand, the CCF specification in section 3.2 documents AVP +in a command grammar as meaning any arbitrary AVP; on the +other hand, 1.3.4 states that AVPs setting the M-bit cannot be added +to an existing command: the modified command must instead be +placed in a new Diameter application.

+

+The reason for the latter is presumably interoperability: +allowing arbitrary AVPs setting the M-bit in a command makes its +interpretation implementation-dependent, since there's no +guarantee that all implementations will understand the same set of +arbitrary AVPs in the context of a given command. +However, interpreting AVP in a command grammar as any +AVP, regardless of M-bit, renders 1.3.4 meaningless, since the receiver +can simply ignore any AVP it thinks isn't relevant, regardless of the +sender's intent.

+

+Beware of confusing mandatory in the sense of the M-bit with mandatory +in the sense of the command grammar. +The former is a semantic requirement: that the receiver understand the +semantics of the AVP in the context in question. +The latter is a syntactic requirement: whether or not the AVP must +occur in the message in question.

+
+ +
+ {string_decode, boolean()} diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl index ac2126cdc5..39ccdc9873 100644 --- a/lib/diameter/include/diameter_gen.hrl +++ b/lib/diameter/include/diameter_gen.hrl @@ -30,7 +30,10 @@ %% Key to a value in the process dictionary that determines whether or %% not an unrecognized AVP setting the M-bit should be regarded as an -%% error or not. See is_strict/0. +%% error or not. See is_strict/0. This is only used to relax M-bit +%% interpretation inside Grouped AVPs not setting the M-bit. The +%% service_opt() strict_mbit can be used to disable the check +%% globally. -define(STRICT_KEY, strict). %% Key that says whether or not we should do a best-effort decode @@ -447,7 +450,8 @@ relax(_, _) -> false. is_strict() -> - false /= getr(?STRICT_KEY). + diameter_codec:getopt(strict_mbit) + andalso false /= getr(?STRICT_KEY). %% relax/1 %% diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl index 010f977b97..9d71bcbbf8 100644 --- a/lib/diameter/src/base/diameter.erl +++ b/lib/diameter/src/base/diameter.erl @@ -311,6 +311,7 @@ call(SvcName, App, Message) -> | {sequence, sequence() | evaluable()} | {share_peers, remotes()} | {string_decode, boolean()} + | {strict_mbit, boolean()} | {incoming_maxlen, message_length()} | {use_shared_peers, remotes()} | {spawn_opt, list()}. diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl index f900bb0c5e..aab8b5887e 100644 --- a/lib/diameter/src/base/diameter_codec.erl +++ b/lib/diameter/src/base/diameter_codec.erl @@ -76,9 +76,10 @@ setopts(Opts) when is_list(Opts) -> lists:foreach(fun setopt/1, Opts). -%% Decode stringish types to string()? The default true is for -%% backwards compatibility. -setopt({string_decode = K, false = B}) -> +%% The default string_decode true is for backwards compatibility. +setopt({K, false = B}) + when K == string_decode; + K == strict_mbit -> setopt(K, B); %% Regard anything but the generated RFC 3588 dictionary as modern. @@ -96,7 +97,8 @@ setopt(Key, Value) -> getopt(Key) -> case get({diameter, Key}) of - undefined when Key == string_decode -> + undefined when Key == string_decode; + Key == strict_mbit -> true; undefined when Key == rfc -> 6733; diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl index 89b26707ad..242b6b4d08 100644 --- a/lib/diameter/src/base/diameter_config.erl +++ b/lib/diameter/src/base/diameter_config.erl @@ -646,6 +646,7 @@ make_config(SvcName, Opts) -> {?NOMASK, sequence}, {nodes, restrict_connections}, {16#FFFFFF, incoming_maxlen}, + {true, strict_mbit}, {true, string_decode}, {[], spawn_opt}]), @@ -684,12 +685,14 @@ opt(K, false = B) K == use_shared_peers; K == monitor; K == restrict_connections; + K == strict_mbit; K == string_decode -> B; opt(K, true = B) when K == share_peers; K == use_shared_peers; + K == strict_mbit; K == string_decode -> B; diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index a31cef2c8c..7d4a24f7a0 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -128,6 +128,7 @@ | {share_peers, diameter:remotes()} %% broadcast to | {use_shared_peers, diameter:remotes()} %% use from | {restrict_connections, diameter:restriction()} + | {strict_mbit, boolean()} | {string_decode, boolean()} | {incoming_maxlen, diameter:message_length()}]}). %% shared_peers reflects the peers broadcast from remote nodes. @@ -697,7 +698,8 @@ service_options(Opts) -> ?RESTRICT)}, {spawn_opt, proplists:get_value(spawn_opt, Opts, [])}, {string_decode, proplists:get_value(string_decode, Opts, true)}, - {incoming_maxlen, proplists:get_value(incoming_maxlen, Opts, 16#FFFFFF)}]. + {incoming_maxlen, proplists:get_value(incoming_maxlen, Opts, 16#FFFFFF)}, + {strict_mbit, proplists:get_value(strict_mbit, Opts, true)}]. %% The order of options is significant since we match against the list. mref(false = No) -> diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index 230a05fa11..6be2c35d48 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -79,6 +79,7 @@ apps :: [#diameter_app{}], sequence :: diameter:sequence(), codec :: [{string_decode, boolean()} + | {strict_mbit, boolean()} | {incoming_maxlen, diameter:message_length()}]}). %% Note that incoming_maxlen is currently handled in diameter_peer_fsm, %% so that any message exceeding the maximum is discarded. Retain the @@ -108,7 +109,8 @@ make_recvdata([SvcName, PeerT, Apps, SvcOpts | _]) -> sequence = Mask, codec = [T || {K,_} = T <- SvcOpts, lists:member(K, [string_decode, - incoming_maxlen])]}. + incoming_maxlen, + strict_mbit])]}. %% --------------------------------------------------------------------------- %% peer_up/1 -- cgit v1.2.3 From be602ec806a37fb3951dc3327ff5f2a96fe9cc86 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 29 Jun 2015 16:45:10 +0200 Subject: dialyzer: Generalize an argument of erl_types:t_from_form() Add more information about the caller of t_from_form(). Instead of just the module, also provide name of the type, spec, or record where the type form resides. --- lib/dialyzer/src/dialyzer_contracts.erl | 102 ++++----- lib/dialyzer/src/dialyzer_utils.erl | 35 +-- lib/hipe/cerl/erl_types.erl | 377 +++++++++++++++++--------------- 3 files changed, 269 insertions(+), 245 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 1079c2e09b..7251de8b10 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -395,22 +395,21 @@ insert_constraints([], Dict) -> Dict. store_tmp_contract(MFA, FileLine, {TypeSpec, Xtra}, SpecDict, RecordsDict) -> %% io:format("contract from form: ~p\n", [TypeSpec]), - {Module, _, _} = MFA, - TmpContract = contract_from_form(TypeSpec, Module, RecordsDict, FileLine), + TmpContract = contract_from_form(TypeSpec, MFA, RecordsDict, FileLine), %% io:format("contract: ~p\n", [TmpContract]), dict:store(MFA, {FileLine, TmpContract, Xtra}, SpecDict). -contract_from_form(Forms, Module, RecDict, FileLine) -> - {CFuns, Forms1} = contract_from_form(Forms, Module, RecDict, FileLine, [], []), +contract_from_form(Forms, MFA, RecDict, FileLine) -> + {CFuns, Forms1} = contract_from_form(Forms, MFA, RecDict, FileLine, [], []), #tmp_contract{contract_funs = CFuns, forms = Forms1}. -contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], Module, RecDict, +contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], MFA, RecDict, FileLine, TypeAcc, FormAcc) -> TypeFun = fun(ExpTypes, AllRecords) -> NewType = try - from_form_with_check(Form, ExpTypes, Module, AllRecords) + from_form_with_check(Form, ExpTypes, MFA, AllRecords) catch throw:{error, Msg} -> {File, Line} = FileLine, @@ -423,55 +422,55 @@ contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], Module, RecDict, end, NewTypeAcc = [TypeFun | TypeAcc], NewFormAcc = [{Form, []} | FormAcc], - contract_from_form(Left, Module, RecDict, FileLine, NewTypeAcc, NewFormAcc); + contract_from_form(Left, MFA, RecDict, FileLine, NewTypeAcc, NewFormAcc); contract_from_form([{type, _L1, bounded_fun, [{type, _L2, 'fun', [_, _]} = Form, Constr]}| Left], - Module, RecDict, FileLine, TypeAcc, FormAcc) -> + MFA, RecDict, FileLine, TypeAcc, FormAcc) -> TypeFun = fun(ExpTypes, AllRecords) -> {Constr1, VarDict} = - process_constraints(Constr, Module, RecDict, ExpTypes, AllRecords), - NewType = from_form_with_check(Form, ExpTypes, Module, AllRecords, + process_constraints(Constr, MFA, RecDict, ExpTypes, AllRecords), + NewType = from_form_with_check(Form, ExpTypes, MFA, AllRecords, VarDict), NewTypeNoVars = erl_types:subst_all_vars_to_any(NewType), {NewTypeNoVars, Constr1} end, NewTypeAcc = [TypeFun | TypeAcc], NewFormAcc = [{Form, Constr} | FormAcc], - contract_from_form(Left, Module, RecDict, FileLine, NewTypeAcc, NewFormAcc); -contract_from_form([], _Module, _RecDict, _FileLine, TypeAcc, FormAcc) -> + contract_from_form(Left, MFA, RecDict, FileLine, NewTypeAcc, NewFormAcc); +contract_from_form([], _MFA, _RecDict, _FileLine, TypeAcc, FormAcc) -> {lists:reverse(TypeAcc), lists:reverse(FormAcc)}. -process_constraints(Constrs, Module, RecDict, ExpTypes, AllRecords) -> - Init0 = initialize_constraints(Constrs, Module, RecDict, ExpTypes, AllRecords), +process_constraints(Constrs, MFA, RecDict, ExpTypes, AllRecords) -> + Init0 = initialize_constraints(Constrs, MFA, RecDict, ExpTypes, AllRecords), Init = remove_cycles(Init0), - constraints_fixpoint(Init, Module, RecDict, ExpTypes, AllRecords). + constraints_fixpoint(Init, MFA, RecDict, ExpTypes, AllRecords). -initialize_constraints(Constrs, Module, RecDict, ExpTypes, AllRecords) -> - initialize_constraints(Constrs, Module, RecDict, ExpTypes, AllRecords, []). +initialize_constraints(Constrs, MFA, RecDict, ExpTypes, AllRecords) -> + initialize_constraints(Constrs, MFA, RecDict, ExpTypes, AllRecords, []). -initialize_constraints([], _Module, _RecDict, _ExpTypes, _AllRecords, Acc) -> +initialize_constraints([], _MFA, _RecDict, _ExpTypes, _AllRecords, Acc) -> Acc; -initialize_constraints([Constr|Rest], Module, RecDict, ExpTypes, AllRecords, Acc) -> +initialize_constraints([Constr|Rest], MFA, RecDict, ExpTypes, AllRecords, Acc) -> case Constr of {type, _, constraint, [{atom, _, is_subtype}, [Type1, Type2]]} -> - T1 = final_form(Type1, ExpTypes, Module, AllRecords, dict:new()), + T1 = final_form(Type1, ExpTypes, MFA, AllRecords, dict:new()), Entry = {T1, Type2}, - initialize_constraints(Rest, Module, RecDict, ExpTypes, AllRecords, [Entry|Acc]); + initialize_constraints(Rest, MFA, RecDict, ExpTypes, AllRecords, [Entry|Acc]); {type, _, constraint, [{atom,_,Name}, List]} -> N = length(List), throw({error, io_lib:format("Unsupported type guard ~w/~w\n", [Name, N])}) end. -constraints_fixpoint(Constrs, Module, RecDict, ExpTypes, AllRecords) -> +constraints_fixpoint(Constrs, MFA, RecDict, ExpTypes, AllRecords) -> VarDict = - constraints_to_dict(Constrs, Module, RecDict, ExpTypes, AllRecords, dict:new()), - constraints_fixpoint(VarDict, Module, Constrs, RecDict, ExpTypes, AllRecords). + constraints_to_dict(Constrs, MFA, RecDict, ExpTypes, AllRecords, dict:new()), + constraints_fixpoint(VarDict, MFA, Constrs, RecDict, ExpTypes, AllRecords). -constraints_fixpoint(OldVarDict, Module, Constrs, RecDict, ExpTypes, AllRecords) -> +constraints_fixpoint(OldVarDict, MFA, Constrs, RecDict, ExpTypes, AllRecords) -> NewVarDict = - constraints_to_dict(Constrs, Module, RecDict, ExpTypes, AllRecords, OldVarDict), + constraints_to_dict(Constrs, MFA, RecDict, ExpTypes, AllRecords, OldVarDict), case NewVarDict of OldVarDict -> DictFold = @@ -481,33 +480,33 @@ constraints_fixpoint(OldVarDict, Module, Constrs, RecDict, ExpTypes, AllRecords) FinalConstrs = dict:fold(DictFold, [], NewVarDict), {FinalConstrs, NewVarDict}; _Other -> - constraints_fixpoint(NewVarDict, Module, Constrs, RecDict, ExpTypes, AllRecords) + constraints_fixpoint(NewVarDict, MFA, Constrs, RecDict, ExpTypes, AllRecords) end. -final_form(Form, ExpTypes, Module, AllRecords, VarDict) -> - from_form_with_check(Form, ExpTypes, Module, AllRecords, VarDict). +final_form(Form, ExpTypes, MFA, AllRecords, VarDict) -> + from_form_with_check(Form, ExpTypes, MFA, AllRecords, VarDict). -from_form_with_check(Form, ExpTypes, Module, AllRecords) -> - erl_types:t_check_record_fields(Form, ExpTypes, Module, AllRecords), - erl_types:t_from_form(Form, ExpTypes, Module, AllRecords). +from_form_with_check(Form, ExpTypes, MFA, AllRecords) -> + from_form_with_check(Form, ExpTypes, MFA, AllRecords, dict:new()). -from_form_with_check(Form, ExpTypes, Module, AllRecords, VarDict) -> - erl_types:t_check_record_fields(Form, ExpTypes, Module, AllRecords, +from_form_with_check(Form, ExpTypes, MFA, AllRecords, VarDict) -> + Site = {spec, MFA}, + erl_types:t_check_record_fields(Form, ExpTypes, Site, AllRecords, VarDict), - erl_types:t_from_form(Form, ExpTypes, Module, AllRecords, VarDict). + erl_types:t_from_form(Form, ExpTypes, Site, AllRecords, VarDict). -constraints_to_dict(Constrs, Module, RecDict, ExpTypes, AllRecords, VarDict) -> +constraints_to_dict(Constrs, MFA, RecDict, ExpTypes, AllRecords, VarDict) -> Subtypes = - constraints_to_subs(Constrs, Module, RecDict, ExpTypes, AllRecords, VarDict, []), + constraints_to_subs(Constrs, MFA, RecDict, ExpTypes, AllRecords, VarDict, []), insert_constraints(Subtypes, dict:new()). -constraints_to_subs([], _Module, _RecDict, _ExpTypes, _AllRecords, _VarDict, Acc) -> +constraints_to_subs([], _MFA, _RecDict, _ExpTypes, _AllRecords, _VarDict, Acc) -> Acc; -constraints_to_subs([C|Rest], Module, RecDict, ExpTypes, AllRecords, VarDict, Acc) -> +constraints_to_subs([C|Rest], MFA, RecDict, ExpTypes, AllRecords, VarDict, Acc) -> {T1, Form2} = C, - T2 = final_form(Form2, ExpTypes, Module, AllRecords, VarDict), + T2 = final_form(Form2, ExpTypes, MFA, AllRecords, VarDict), NewAcc = [{subtype, T1, T2}|Acc], - constraints_to_subs(Rest, Module, RecDict, ExpTypes, AllRecords, VarDict, NewAcc). + constraints_to_subs(Rest, MFA, RecDict, ExpTypes, AllRecords, VarDict, NewAcc). %% Replaces variables with '_' when necessary to break up cycles among %% the constraints. @@ -630,7 +629,7 @@ get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract, _Xtra}}|Left], {error, {extra_range, ExtraRanges, STRange}} -> Warn = case t_from_forms_without_remote(Contract#contract.forms, - RecDict) of + MFA, RecDict) of {ok, NoRemoteType} -> CRet = erl_types:t_fun_range(NoRemoteType), erl_types:t_is_subtype(ExtraRanges, CRet); @@ -705,7 +704,7 @@ picky_contract_check(CSig0, Sig0, MFA, WarningInfo, Contract, RecDict, Acc) -> end end. -extra_contract_warning({M, F, A}, WarningInfo, Contract, CSig, Sig, RecDict) -> +extra_contract_warning(MFA, WarningInfo, Contract, CSig, Sig, RecDict) -> %% We do not want to depend upon erl_types:t_to_string() possibly %% hiding the contents of opaque types. SigUnopaque = erl_types:t_unopaque(Sig), @@ -717,11 +716,12 @@ extra_contract_warning({M, F, A}, WarningInfo, Contract, CSig, Sig, RecDict) -> %% The only difference is in record fields containing 'undefined' or not. IsUndefRecordFieldsRelated = SigString0 =:= ContractString0, {IsRemoteTypesRelated, SubtypeRelation} = - is_remote_types_related(Contract, CSig, Sig, RecDict), + is_remote_types_related(Contract, CSig, Sig, MFA, RecDict), case IsUndefRecordFieldsRelated orelse IsRemoteTypesRelated of true -> no_warning; false -> + {M, F, A} = MFA, SigString = lists:flatten(dialyzer_utils:format_sig(Sig, RecDict)), ContractString = contract_to_string(Contract), {Tag, Msg} = @@ -739,14 +739,15 @@ extra_contract_warning({M, F, A}, WarningInfo, Contract, CSig, Sig, RecDict) -> {warning, {Tag, WarningInfo, Msg}} end. -is_remote_types_related(Contract, CSig, Sig, RecDict) -> +is_remote_types_related(Contract, CSig, Sig, MFA, RecDict) -> case erl_types:t_is_subtype(CSig, Sig) of true -> {false, contract_is_subtype}; false -> case erl_types:t_is_subtype(Sig, CSig) of true -> - case t_from_forms_without_remote(Contract#contract.forms, RecDict) of + case t_from_forms_without_remote(Contract#contract.forms, MFA, + RecDict) of {ok, NoRemoteTypeSig} -> case blame_remote(CSig, NoRemoteTypeSig, Sig) of true -> @@ -762,13 +763,14 @@ is_remote_types_related(Contract, CSig, Sig, RecDict) -> end end. -t_from_forms_without_remote([{FType, []}], RecDict) -> - Type1 = erl_types:t_from_form_without_remote(FType, RecDict), +t_from_forms_without_remote([{FType, []}], MFA, RecDict) -> + Site = {spec, MFA}, + Type1 = erl_types:t_from_form_without_remote(FType, Site, RecDict), {ok, erl_types:subst_all_vars_to_any(Type1)}; -t_from_forms_without_remote([{_FType, _Constrs}], _RecDict) -> +t_from_forms_without_remote([{_FType, _Constrs}], _MFA, _RecDict) -> %% 'When' constraints unsupported; -t_from_forms_without_remote(_Forms, _RecDict) -> +t_from_forms_without_remote(_Forms, _MFA, _RecDict) -> %% Lots of forms unsupported. diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index b585646fde..7fe982a992 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -304,15 +304,16 @@ process_record_remote_types(CServer) -> RecordFun = fun(Key, Value) -> case Key of - {record, _Name} -> + {record, Name} -> FieldFun = - fun(_Arity, Fields) -> - [{Name, Field, + fun(Arity, Fields) -> + Site = {record, {Module, Name, Arity}}, + [{FieldName, Field, erl_types:t_from_form(Field, TempExpTypes, - Module, + Site, TempRecords1)} - || {Name, Field, _} <- Fields] + || {FieldName, Field, _} <- Fields] end, {FileLine, Fields} = Value, {FileLine, orddict:map(FieldFun, Fields)}; @@ -340,9 +341,10 @@ process_opaque_types(TempRecords, TempExpTypes) -> RecordFun = fun(Key, Value) -> case Key of - {opaque, _Name, _NArgs} -> + {opaque, Name, NArgs} -> {{_Module, _FileLine, Form, _ArgNames}=F, _Type} = Value, - Type = erl_types:t_from_form(Form, TempExpTypes, Module, + Site = {type, {Module, Name, NArgs}}, + Type = erl_types:t_from_form(Form, TempExpTypes, Site, TempRecords), {F, Type}; _Other -> Value @@ -355,25 +357,28 @@ process_opaque_types(TempRecords, TempExpTypes) -> check_record_fields(Records, TempExpTypes) -> CheckFun = fun({Module, Element}) -> - CheckForm = fun(F) -> - erl_types:t_check_record_fields(F, TempExpTypes, - Module, Records) + CheckForm = fun(Form, Site) -> + erl_types:t_check_record_fields(Form, TempExpTypes, + Site, Records) end, ElemFun = fun({Key, Value}) -> case Key of - {record, _Name} -> + {record, Name} -> FieldFun = - fun({_Arity, Fields}) -> - _ = [ok = CheckForm(Field) || {_, Field, _} <- Fields], + fun({Arity, Fields}) -> + Site = {record, {Module, Name, Arity}}, + _ = [ok = CheckForm(Field, Site) || + {_, Field, _} <- Fields], ok end, {FileLine, Fields} = Value, Fun = fun() -> lists:foreach(FieldFun, Fields) end, msg_with_position(Fun, FileLine); - {_OpaqueOrType, _Name, _} -> + {_OpaqueOrType, Name, NArgs} -> + Site = {type, {Module, Name, NArgs}}, {{_Module, FileLine, Form, _ArgNames}, _Type} = Value, - Fun = fun() -> ok = CheckForm(Form) end, + Fun = fun() -> ok = CheckForm(Form, Site) end, msg_with_position(Fun, FileLine) end end, diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index cc4fee0853..f0b907f86c 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -82,7 +82,7 @@ t_form_to_string/1, t_from_form/4, t_from_form/5, - t_from_form_without_remote/2, + t_from_form_without_remote/3, t_check_record_fields/4, t_check_record_fields/5, t_from_range/2, @@ -3971,27 +3971,32 @@ mod_name(Mod, Name) -> -type type_names() :: [type_key() | record_key()]. +-type mta() :: {module(), atom(), arity()}. +-type mra() :: {module(), atom(), arity()}. +-type site() :: {'type', mta()} | {'spec', mfa()} | {'record', mra()}. + -spec t_from_form(parse_form(), sets:set(mfa()), - module(), mod_records()) -> erl_type(). + site(), mod_records()) -> erl_type(). -t_from_form(Form, ExpTypes, Module, RecDict) -> - t_from_form(Form, ExpTypes, Module, RecDict, dict:new()). +t_from_form(Form, ExpTypes, Site, RecDict) -> + t_from_form(Form, ExpTypes, Site, RecDict, dict:new()). -spec t_from_form(parse_form(), sets:set(mfa()), - module(), mod_records(), var_table()) -> erl_type(). + site(), mod_records(), var_table()) -> erl_type(). -t_from_form(Form, ExpTypes, Module, RecDict, VarDict) -> - {T, _} = t_from_form1(Form, [], ExpTypes, Module, RecDict, VarDict), +t_from_form(Form, ExpTypes, Site, RecDict, VarDict) -> + {T, _} = t_from_form1(Form, ExpTypes, Site, RecDict, VarDict), T. %% Replace external types with with none(). --spec t_from_form_without_remote(parse_form(), type_table()) -> erl_type(). +-spec t_from_form_without_remote(parse_form(), site(), type_table()) -> + erl_type(). -t_from_form_without_remote(Form, TypeTable) -> - Module = mod, +t_from_form_without_remote(Form, Site, TypeTable) -> + Module = site_module(Site), RecDict = dict:from_list([{Module, TypeTable}]), ExpTypes = replace_by_none, - {T, _} = t_from_form1(Form, [], ExpTypes, Module, RecDict, dict:new()), + {T, _} = t_from_form1(Form, ExpTypes, Site, RecDict, dict:new()), T. %% REC_TYPE_LIMIT is used for limiting the depth of recursive types. @@ -4005,23 +4010,23 @@ t_from_form_without_remote(Form, TypeTable) -> -type expand_depth() :: integer(). -t_from_form1(Form, TypeNames, ET, M, MR, V) -> - t_from_form1(Form, TypeNames, ET, M, MR, V, ?EXPAND_DEPTH). +t_from_form1(Form, ET, Site, MR, V) -> + t_from_form1(Form, ET, Site, MR, V, ?EXPAND_DEPTH). -t_from_form1(Form, TypeNames, ET, M, MR, V, D) -> +t_from_form1(Form, ET, Site, MR, V, D) -> L = ?EXPAND_LIMIT, - {T, L1} = t_from_form(Form, TypeNames, ET, M, MR, V, D, L), + {T, L1} = t_from_form(Form, [], ET, Site, MR, V, D, L), if L1 =< 0, D > 1 -> D1 = D div 2, - t_from_form1(Form, TypeNames, ET, M, MR, V, D1); + t_from_form1(Form, ET, Site, MR, V, D1); true -> {T, L1} end. -spec t_from_form(parse_form(), type_names(), sets:set(mfa()) | 'replace_by_none', - module(), mod_records(), var_table(), + site(), mod_records(), var_table(), expand_depth(), expand_limit()) -> {erl_type(), expand_limit()}. @@ -4031,193 +4036,194 @@ t_from_form1(Form, TypeNames, ET, M, MR, V, D) -> %% self() ! {self(), ext_types, {RemMod, Name, ArgsLen}} %% is called, unless 'replace_by_none' is given. %% -%% It is assumed that M can be found in MR. +%% It is assumed that site_module(S) can be found in MR. -t_from_form(_, _TypeNames, _ET, _M, _MR, _V, D, L) when D =< 0 ; L =< 0 -> +t_from_form(_, _TypeNames, _ET, _S, _MR, _V, D, L) when D =< 0 ; L =< 0 -> {t_any(), L}; -t_from_form({var, _L, '_'}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({var, _L, '_'}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_any(), L}; -t_from_form({var, _L, Name}, _TypeNames, _ET, _M, _MR, V, _D, L) -> +t_from_form({var, _L, Name}, _TypeNames, _ET, _S, _MR, V, _D, L) -> case dict:find(Name, V) of error -> {t_var(Name), L}; {ok, Val} -> {Val, L} end; -t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, ET, M, MR, V, D, L) -> - t_from_form(Type, TypeNames, ET, M, MR, V, D, L); -t_from_form({paren_type, _L, [Type]}, TypeNames, ET, M, MR, V, D, L) -> - t_from_form(Type, TypeNames, ET, M, MR, V, D, L); +t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, ET, S, MR, V, D, L) -> + t_from_form(Type, TypeNames, ET, S, MR, V, D, L); +t_from_form({paren_type, _L, [Type]}, TypeNames, ET, S, MR, V, D, L) -> + t_from_form(Type, TypeNames, ET, S, MR, V, D, L); t_from_form({remote_type, _L, [{atom, _, Module}, {atom, _, Type}, Args]}, - TypeNames, ET, M, MR, V, D, L) -> - remote_from_form(Module, Type, Args, TypeNames, ET, M, MR, V, D, L); -t_from_form({atom, _L, Atom}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> + TypeNames, ET, S, MR, V, D, L) -> + remote_from_form(Module, Type, Args, TypeNames, ET, S, MR, V, D, L); +t_from_form({atom, _L, Atom}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_atom(Atom), L}; -t_from_form({integer, _L, Int}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({integer, _L, Int}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_integer(Int), L}; -t_from_form({op, _L, _Op, _Arg} = Op, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({op, _L, _Op, _Arg} = Op, _TypeNames, _ET, _S, _MR, _V, _D, L) -> case erl_eval:partial_eval(Op) of {integer, _, Val} -> {t_integer(Val), L}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])}) end; t_from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _TypeNames, - _ET, _M, _MR, _V, _D, L) -> + _ET, _S, _MR, _V, _D, L) -> case erl_eval:partial_eval(Op) of {integer, _, Val} -> {t_integer(Val), L}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])}) end; -t_from_form({type, _L, any, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, any, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_any(), L}; -t_from_form({type, _L, arity, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, arity, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_arity(), L}; -t_from_form({type, _L, atom, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, atom, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_atom(), L}; -t_from_form({type, _L, binary, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, binary, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_binary(), L}; t_from_form({type, _L, binary, [Base, Unit]} = Type, - _TypeNames, _ET, _M, _MR, _V, _D, L) -> + _TypeNames, _ET, _S, _MR, _V, _D, L) -> case {erl_eval:partial_eval(Base), erl_eval:partial_eval(Unit)} of {{integer, _, B}, {integer, _, U}} when B >= 0, U >= 0 -> {t_bitstr(U, B), L}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])}) end; -t_from_form({type, _L, bitstring, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, bitstring, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_bitstr(), L}; -t_from_form({type, _L, bool, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, bool, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_boolean(), L}; % XXX: Temporarily -t_from_form({type, _L, boolean, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, boolean, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_boolean(), L}; -t_from_form({type, _L, byte, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, byte, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_byte(), L}; -t_from_form({type, _L, char, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, char, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_char(), L}; -t_from_form({type, _L, float, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, float, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_float(), L}; -t_from_form({type, _L, function, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, function, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_fun(), L}; -t_from_form({type, _L, 'fun', []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, 'fun', []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_fun(), L}; t_from_form({type, _L, 'fun', [{type, _, any}, Range]}, TypeNames, - ET, M, MR, V, D, L) -> - {T, L1} = t_from_form(Range, TypeNames, ET, M, MR, V, D - 1, L - 1), + ET, S, MR, V, D, L) -> + {T, L1} = t_from_form(Range, TypeNames, ET, S, MR, V, D - 1, L - 1), {t_fun(T), L1}; t_from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]}, - TypeNames, ET, M, MR, V, D, L) -> - {Dom1, L1} = list_from_form(Domain, TypeNames, ET, M, MR, V, D, L), - {Ran1, L2} = t_from_form(Range, TypeNames, ET, M, MR, V, D - 1, L1), + TypeNames, ET, S, MR, V, D, L) -> + {Dom1, L1} = list_from_form(Domain, TypeNames, ET, S, MR, V, D, L), + {Ran1, L2} = t_from_form(Range, TypeNames, ET, S, MR, V, D - 1, L1), {t_fun(Dom1, Ran1), L2}; -t_from_form({type, _L, identifier, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, identifier, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_identifier(), L}; -t_from_form({type, _L, integer, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, integer, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_integer(), L}; -t_from_form({type, _L, iodata, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, iodata, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_iodata(), L}; -t_from_form({type, _L, iolist, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, iolist, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_iolist(), L}; -t_from_form({type, _L, list, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, list, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_list(), L}; -t_from_form({type, _L, list, [Type]}, TypeNames, ET, M, MR, V, D, L) -> - {T, L1} = t_from_form(Type, TypeNames, ET, M, MR, V, D - 1, L - 1), +t_from_form({type, _L, list, [Type]}, TypeNames, ET, S, MR, V, D, L) -> + {T, L1} = t_from_form(Type, TypeNames, ET, S, MR, V, D - 1, L - 1), {t_list(T), L1}; -t_from_form({type, _L, map, _}, TypeNames, ET, M, MR, V, D, L) -> - builtin_type(map, t_map([]), TypeNames, ET, M, MR, V, D, L); -t_from_form({type, _L, mfa, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, map, _}, TypeNames, ET, S, MR, V, D, L) -> + builtin_type(map, t_map([]), TypeNames, ET, S, MR, V, D, L); +t_from_form({type, _L, mfa, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_mfa(), L}; -t_from_form({type, _L, module, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, module, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_module(), L}; -t_from_form({type, _L, nil, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, nil, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_nil(), L}; -t_from_form({type, _L, neg_integer, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, neg_integer, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_neg_integer(), L}; -t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _ET, _M, _MR, +t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_non_neg_integer(), L}; -t_from_form({type, _L, no_return, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, no_return, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_unit(), L}; -t_from_form({type, _L, node, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, node, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_node(), L}; -t_from_form({type, _L, none, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, none, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_none(), L}; -t_from_form({type, _L, nonempty_list, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, nonempty_list, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_nonempty_list(), L}; -t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, ET, M, MR, V, D, L) -> - {T, L1} = t_from_form(Type, TypeNames, ET, M, MR, V, D, L - 1), +t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, ET, S, MR, V, D, L) -> + {T, L1} = t_from_form(Type, TypeNames, ET, S, MR, V, D, L - 1), {t_nonempty_list(T), L1}; t_from_form({type, _L, nonempty_improper_list, [Cont, Term]}, TypeNames, - ET, M, MR, V, D, L) -> - {T1, L1} = t_from_form(Cont, TypeNames, ET, M, MR, V, D, L - 1), - {T2, L2} = t_from_form(Term, TypeNames, ET, M, MR, V, D, L1), + ET, S, MR, V, D, L) -> + {T1, L1} = t_from_form(Cont, TypeNames, ET, S, MR, V, D, L - 1), + {T2, L2} = t_from_form(Term, TypeNames, ET, S, MR, V, D, L1), {t_cons(T1, T2), L2}; t_from_form({type, _L, nonempty_maybe_improper_list, []}, _TypeNames, - _ET, _M, _MR, _V, _D, L) -> + _ET, _S, _MR, _V, _D, L) -> {t_cons(?any, ?any), L}; t_from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]}, - TypeNames, ET, M, MR, V, D, L) -> - {T1, L1} = t_from_form(Cont, TypeNames, ET, M, MR, V, D, L - 1), - {T2, L2} = t_from_form(Term, TypeNames, ET, M, MR, V, D, L1), + TypeNames, ET, S, MR, V, D, L) -> + {T1, L1} = t_from_form(Cont, TypeNames, ET, S, MR, V, D, L - 1), + {T2, L2} = t_from_form(Term, TypeNames, ET, S, MR, V, D, L1), {t_cons(T1, T2), L2}; -t_from_form({type, _L, nonempty_string, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, nonempty_string, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_nonempty_string(), L}; -t_from_form({type, _L, number, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, number, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_number(), L}; -t_from_form({type, _L, pid, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, pid, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_pid(), L}; -t_from_form({type, _L, port, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, port, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_port(), L}; -t_from_form({type, _L, pos_integer, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, pos_integer, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_pos_integer(), L}; t_from_form({type, _L, maybe_improper_list, []}, _TypeNames, - _ET, _M, _MR, _V, _D, L) -> + _ET, _S, _MR, _V, _D, L) -> {t_maybe_improper_list(), L}; t_from_form({type, _L, maybe_improper_list, [Content, Termination]}, - TypeNames, ET, M, MR, V, D, L) -> - {T1, L1} = t_from_form(Content, TypeNames, ET, M, MR, V, D, L - 1), - {T2, L2} = t_from_form(Termination, TypeNames, ET, M, MR, V, D, L1), + TypeNames, ET, S, MR, V, D, L) -> + {T1, L1} = t_from_form(Content, TypeNames, ET, S, MR, V, D, L - 1), + {T2, L2} = t_from_form(Termination, TypeNames, ET, S, MR, V, D, L1), {t_maybe_improper_list(T1, T2), L2}; -t_from_form({type, _L, product, Elements}, TypeNames, ET, M, MR, V, D, L) -> - {Lst, L1} = list_from_form(Elements, TypeNames, ET, M, MR, V, D - 1, L), +t_from_form({type, _L, product, Elements}, TypeNames, ET, S, MR, V, D, L) -> + {Lst, L1} = list_from_form(Elements, TypeNames, ET, S, MR, V, D - 1, L), {t_product(Lst), L1}; t_from_form({type, _L, range, [From, To]} = Type, - _TypeNames, _ET, _M, _MR, _V, _D, L) -> + _TypeNames, _ET, _S, _MR, _V, _D, L) -> case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of {{integer, _, FromVal}, {integer, _, ToVal}} -> {t_from_range(FromVal, ToVal), L}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])}) end; -t_from_form({type, _L, record, [Name|Fields]}, TypeNames, ET, M, MR, V, D, L) -> - record_from_form(Name, Fields, TypeNames, ET, M, MR, V, D, L); -t_from_form({type, _L, reference, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, record, [Name|Fields]}, TypeNames, ET, S, MR, V, D, L) -> + record_from_form(Name, Fields, TypeNames, ET, S, MR, V, D, L); +t_from_form({type, _L, reference, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_reference(), L}; -t_from_form({type, _L, string, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, string, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_string(), L}; -t_from_form({type, _L, term, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, term, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_any(), L}; -t_from_form({type, _L, timeout, []}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, timeout, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_timeout(), L}; -t_from_form({type, _L, tuple, any}, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +t_from_form({type, _L, tuple, any}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {t_tuple(), L}; -t_from_form({type, _L, tuple, Args}, TypeNames, ET, M, MR, V, D, L) -> - {Lst, L1} = list_from_form(Args, TypeNames, ET, M, MR, V, D - 1, L), +t_from_form({type, _L, tuple, Args}, TypeNames, ET, S, MR, V, D, L) -> + {Lst, L1} = list_from_form(Args, TypeNames, ET, S, MR, V, D - 1, L), {t_tuple(Lst), L1}; -t_from_form({type, _L, union, Args}, TypeNames, ET, M, MR, V, D, L) -> - {Lst, L1} = list_from_form(Args, TypeNames, ET, M, MR, V, D, L), +t_from_form({type, _L, union, Args}, TypeNames, ET, S, MR, V, D, L) -> + {Lst, L1} = list_from_form(Args, TypeNames, ET, S, MR, V, D, L), {t_sup(Lst), L1}; -t_from_form({user_type, _L, Name, Args}, TypeNames, ET, M, MR, V, D, L) -> - type_from_form(Name, Args, TypeNames, ET, M, MR, V, D, L); -t_from_form({type, _L, Name, Args}, TypeNames, ET, M, MR, V, D, L) -> +t_from_form({user_type, _L, Name, Args}, TypeNames, ET, S, MR, V, D, L) -> + type_from_form(Name, Args, TypeNames, ET, S, MR, V, D, L); +t_from_form({type, _L, Name, Args}, TypeNames, ET, S, MR, V, D, L) -> %% Compatibility: modules compiled before Erlang/OTP 18.0. - type_from_form(Name, Args, TypeNames, ET, M, MR, V, D, L); + type_from_form(Name, Args, TypeNames, ET, S, MR, V, D, L); t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, - _ET, _M, _MR, _V, _D, L) -> + _ET, _S, _MR, _V, _D, L) -> %% XXX. To be removed. {t_opaque(Mod, Name, Args, Rep), L}. -builtin_type(Name, Type, TypeNames, ET, M, MR, V, D, L) -> +builtin_type(Name, Type, TypeNames, ET, Site, MR, V, D, L) -> + M = site_module(Site), case dict:find(M, MR) of {ok, R} -> case lookup_type(Name, 0, R) of {_, {{_M, _FL, _F, _A}, _T}} -> - type_from_form(Name, [], TypeNames, ET, M, MR, V, D, L); + type_from_form(Name, [], TypeNames, ET, Site, MR, V, D, L); error -> {Type, L} end; @@ -4225,29 +4231,31 @@ builtin_type(Name, Type, TypeNames, ET, M, MR, V, D, L) -> {Type, L} end. -type_from_form(Name, Args, TypeNames, ET, M, MR, V, D, L) -> +type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> ArgsLen = length(Args), - {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, M, MR, V, D, L), - {ok, R} = dict:find(M, MR), + {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, Site0, MR, V, D, L), + Module = site_module(Site0), + {ok, R} = dict:find(Module, MR), + TypeName = {type, {Module, Name, ArgsLen}}, case lookup_type(Name, ArgsLen, R) of {type, {{Module, _FileName, Form, ArgNames}, _Type}} -> - TypeName = {type, Module, Name, ArgsLen}, case can_unfold_more(TypeName, TypeNames) of true -> List = lists:zip(ArgNames, ArgTypes), TmpV = dict:from_list(List), - t_from_form(Form, [TypeName|TypeNames], ET, M, MR, TmpV, D, L1); + Site = TypeName, + t_from_form(Form, [TypeName|TypeNames], ET, Site, MR, TmpV, D, L1); false -> {t_any(), L1} end; {opaque, {{Module, _FileName, Form, ArgNames}, Type}} -> - TypeName = {opaque, Module, Name, ArgsLen}, {Rep, L2} = case can_unfold_more(TypeName, TypeNames) of true -> List = lists:zip(ArgNames, ArgTypes), TmpV = dict:from_list(List), - t_from_form(Form, [TypeName|TypeNames], ET, M, MR, TmpV, D, L1); + Site = TypeName, + t_from_form(Form, [TypeName|TypeNames], ET, Site, MR, TmpV, D, L1); false -> {t_any(), L1} end, Rep1 = choose_opaque_type(Rep, Type), @@ -4263,36 +4271,36 @@ type_from_form(Name, Args, TypeNames, ET, M, MR, V, D, L) -> throw({error, Msg}) end. -remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) -> - {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, M, MR, V, D, L), +remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> + {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, S, MR, V, D, L), if ET =:= replace_by_none -> {t_none(), L1}; true -> ArgsLen = length(Args), + MFA = {RemMod, Name, ArgsLen}, case dict:find(RemMod, MR) of error -> - self() ! {self(), ext_types, {RemMod, Name, ArgsLen}}, + self() ! {self(), ext_types, MFA}, {t_any(), L1}; {ok, RemDict} -> - MFA = {RemMod, Name, ArgsLen}, + RemType = {type, MFA}, case sets:is_element(MFA, ET) of true -> case lookup_type(Name, ArgsLen, RemDict) of {type, {{_Mod, _FileLine, Form, ArgNames}, _Type}} -> - RemType = {type, RemMod, Name, ArgsLen}, case can_unfold_more(RemType, TypeNames) of true -> List = lists:zip(ArgNames, ArgTypes), TmpVarDict = dict:from_list(List), NewTypeNames = [RemType|TypeNames], + Site = RemType, t_from_form(Form, NewTypeNames, ET, - RemMod, MR, TmpVarDict, D, L1); + Site, MR, TmpVarDict, D, L1); false -> {t_any(), L1} end; {opaque, {{Mod, _FileLine, Form, ArgNames}, Type}} -> - RemType = {opaque, RemMod, Name, ArgsLen}, List = lists:zip(ArgNames, ArgTypes), TmpVarDict = dict:from_list(List), {NewRep, L2} = @@ -4346,22 +4354,24 @@ choose_opaque_type(Type, DeclType) -> false -> DeclType end. -record_from_form({atom, _, Name}, ModFields, TypeNames, ET, M, MR, V, D, L) -> +record_from_form({atom, _, Name}, ModFields, TypeNames, ET, S, MR, V, D, L) -> case can_unfold_more({record, Name}, TypeNames) of true -> + M = site_module(S), {ok, R} = dict:find(M, MR), case lookup_record(Name, R) of {ok, DeclFields} -> NewTypeNames = [{record, Name}|TypeNames], + S1 = {record, {M, Name, length(DeclFields)}}, {GetModRec, L1} = get_mod_record(ModFields, DeclFields, - NewTypeNames, ET, M, MR, V, D, L), + NewTypeNames, ET, S1, MR, V, D, L), case GetModRec of {error, FieldName} -> throw({error, io_lib:format("Illegal declaration of #~w{~w}\n", [Name, FieldName])}); {ok, NewFields} -> {NewFields1, L2} = - fields_from_form(NewFields, NewTypeNames, ET, M, MR, + fields_from_form(NewFields, NewTypeNames, ET, S1, MR, dict:new(), D, L1), Rec = t_tuple( [t_atom(Name)|[Type @@ -4375,12 +4385,12 @@ record_from_form({atom, _, Name}, ModFields, TypeNames, ET, M, MR, V, D, L) -> {t_any(), L} end. -get_mod_record([], DeclFields, _TypeNames, _ET, _M, _MR, _V, _D, L) -> +get_mod_record([], DeclFields, _TypeNames, _ET, _S, _MR, _V, _D, L) -> {{ok, DeclFields}, L}; -get_mod_record(ModFields, DeclFields, TypeNames, ET, M, MR, V, D, L) -> +get_mod_record(ModFields, DeclFields, TypeNames, ET, S, MR, V, D, L) -> DeclFieldsDict = lists:keysort(1, DeclFields), {ModFieldsDict, L1} = - build_field_dict(ModFields, TypeNames, ET, M, MR, V, D, L), + build_field_dict(ModFields, TypeNames, ET, S, MR, V, D, L), case get_mod_record_types(DeclFieldsDict, ModFieldsDict, []) of {error, _FieldName} = Error -> {Error, L1}; {ok, FinalKeyDict} -> @@ -4389,17 +4399,17 @@ get_mod_record(ModFields, DeclFields, TypeNames, ET, M, MR, V, D, L) -> {{ok, Fields}, L1} end. -build_field_dict(FieldTypes, TypeNames, ET, M, MR, V, D, L) -> - build_field_dict(FieldTypes, TypeNames, ET, M, MR, V, D, L, []). +build_field_dict(FieldTypes, TypeNames, ET, S, MR, V, D, L) -> + build_field_dict(FieldTypes, TypeNames, ET, S, MR, V, D, L, []). build_field_dict([{type, _, field_type, [{atom, _, Name}, Type]}|Left], - TypeNames, ET, M, MR, V, D, L, Acc) -> - {T, L1} = t_from_form(Type, TypeNames, ET, M, MR, V, D, L - 1), + TypeNames, ET, S, MR, V, D, L, Acc) -> + {T, L1} = t_from_form(Type, TypeNames, ET, S, MR, V, D, L - 1), NewAcc = [{Name, Type, T}|Acc], {Dict, L2} = - build_field_dict(Left, TypeNames, ET, M, MR, V, D, L1, NewAcc), + build_field_dict(Left, TypeNames, ET, S, MR, V, D, L1, NewAcc), {Dict, L2}; -build_field_dict([], _TypeNames, _ET, _M, _MR, _V, _D, L, Acc) -> +build_field_dict([], _TypeNames, _ET, _S, _MR, _V, _D, L, Acc) -> {lists:keysort(1, Acc), L}. get_mod_record_types([{FieldName, _Abstr, _DeclType}|Left1], @@ -4418,88 +4428,94 @@ get_mod_record_types(_, [{FieldName2, _FormType, _ModType}|_], _Acc) -> %% It is important to create a limited version of the record type %% since nested record types can otherwise easily result in huge %% terms. -fields_from_form([], _TypeNames, _ET, _M, _MR, _V, _D, L) -> +fields_from_form([], _TypeNames, _ET, _S, _MR, _V, _D, L) -> {[], L}; -fields_from_form([{Name, Abstr, _Type}|Tail], TypeNames, ET, M, MR, +fields_from_form([{Name, Abstr, _Type}|Tail], TypeNames, ET, S, MR, V, D, L) -> - {T, L1} = t_from_form(Abstr, TypeNames, ET, M, MR, V, D, L), - {F, L2} = fields_from_form(Tail, TypeNames, ET, M, MR, V, D, L1), + {T, L1} = t_from_form(Abstr, TypeNames, ET, S, MR, V, D, L), + {F, L2} = fields_from_form(Tail, TypeNames, ET, S, MR, V, D, L1), {[{Name, T}|F], L2}. -list_from_form([], _TypeNames, _ET, _M, _MR, _V, _D, L) -> +list_from_form([], _TypeNames, _ET, _S, _MR, _V, _D, L) -> {[], L}; -list_from_form([H|Tail], TypeNames, ET, M, MR, V, D, L) -> - {H1, L1} = t_from_form(H, TypeNames, ET, M, MR, V, D, L - 1), - {T1, L2} = list_from_form(Tail, TypeNames, ET, M, MR, V, D, L1), +list_from_form([H|Tail], TypeNames, ET, S, MR, V, D, L) -> + {H1, L1} = t_from_form(H, TypeNames, ET, S, MR, V, D, L - 1), + {T1, L2} = list_from_form(Tail, TypeNames, ET, S, MR, V, D, L1), {[H1|T1], L2}. --spec t_check_record_fields(parse_form(), sets:set(mfa()), module(), +-spec t_check_record_fields(parse_form(), sets:set(mfa()), site(), mod_records()) -> ok. -t_check_record_fields(Form, ExpTypes, Module, RecDict) -> - t_check_record_fields(Form, ExpTypes, Module, RecDict, dict:new()). +t_check_record_fields(Form, ExpTypes, Site, RecDict) -> + t_check_record_fields(Form, ExpTypes, Site, RecDict, dict:new()). --spec t_check_record_fields(parse_form(), sets:set(mfa()), module(), +-spec t_check_record_fields(parse_form(), sets:set(mfa()), site(), mod_records(), var_table()) -> ok. %% If there is something wrong with parse_form() %% throw({error, io_lib:chars()} is called. -t_check_record_fields({var, _L, _}, _ET, _M, _MR, _V) -> ok; -t_check_record_fields({ann_type, _L, [_Var, Type]}, ET, M, MR, V) -> - t_check_record_fields(Type, ET, M, MR, V); -t_check_record_fields({paren_type, _L, [Type]}, ET, M, MR, V) -> - t_check_record_fields(Type, ET, M, MR, V); +t_check_record_fields({var, _L, _}, _ET, _S, _MR, _V) -> ok; +t_check_record_fields({ann_type, _L, [_Var, Type]}, ET, S, MR, V) -> + t_check_record_fields(Type, ET, S, MR, V); +t_check_record_fields({paren_type, _L, [Type]}, ET, S, MR, V) -> + t_check_record_fields(Type, ET, S, MR, V); t_check_record_fields({remote_type, _L, [{atom, _, _}, {atom, _, _}, Args]}, - ET, M, MR, V) -> - list_check_record_fields(Args, ET, M, MR, V); -t_check_record_fields({atom, _L, _}, _ET, _M, _MR, _V) -> ok; -t_check_record_fields({integer, _L, _}, _ET, _M, _MR, _V) -> ok; -t_check_record_fields({op, _L, _Op, _Arg}, _ET, _M, _MR, _V) -> ok; -t_check_record_fields({op, _L, _Op, _Arg1, _Arg2}, _ET, _M, _MR, _V) -> ok; -t_check_record_fields({type, _L, tuple, any}, _ET, _M, _MR, _V) -> ok; -t_check_record_fields({type, _L, map, any}, _ET, _M, _MR, _V) -> ok; -t_check_record_fields({type, _L, binary, [_Base, _Unit]}, _ET, _M, _MR, _V) -> + ET, S, MR, V) -> + list_check_record_fields(Args, ET, S, MR, V); +t_check_record_fields({atom, _L, _}, _ET, _S, _MR, _V) -> ok; +t_check_record_fields({integer, _L, _}, _ET, _S, _MR, _V) -> ok; +t_check_record_fields({op, _L, _Op, _Arg}, _ET, _S, _MR, _V) -> ok; +t_check_record_fields({op, _L, _Op, _Arg1, _Arg2}, _ET, _S, _MR, _V) -> ok; +t_check_record_fields({type, _L, tuple, any}, _ET, _S, _MR, _V) -> ok; +t_check_record_fields({type, _L, map, any}, _ET, _S, _MR, _V) -> ok; +t_check_record_fields({type, _L, binary, [_Base, _Unit]}, _ET, _S, _MR, _V) -> ok; t_check_record_fields({type, _L, 'fun', [{type, _, any}, Range]}, - ET, M, MR, V) -> - t_check_record_fields(Range, ET, M, MR, V); -t_check_record_fields({type, _L, range, [_From, _To]}, _ET, _M, _MR, _V) -> + ET, S, MR, V) -> + t_check_record_fields(Range, ET, S, MR, V); +t_check_record_fields({type, _L, range, [_From, _To]}, _ET, _S, _MR, _V) -> ok; -t_check_record_fields({type, _L, record, [Name|Fields]}, ET, M, MR, V) -> - check_record(Name, Fields, ET, M, MR, V); -t_check_record_fields({type, _L, _, Args}, ET, M, MR, V) -> - list_check_record_fields(Args, ET, M, MR, V); -t_check_record_fields({user_type, _L, _Name, Args}, ET, M, MR, V) -> - list_check_record_fields(Args, ET, M, MR, V). - -check_record({atom, _, Name}, ModFields, ET, M, MR, V) -> +t_check_record_fields({type, _L, record, [Name|Fields]}, ET, S, MR, V) -> + check_record(Name, Fields, ET, S, MR, V); +t_check_record_fields({type, _L, _, Args}, ET, S, MR, V) -> + list_check_record_fields(Args, ET, S, MR, V); +t_check_record_fields({user_type, _L, _Name, Args}, ET, S, MR, V) -> + list_check_record_fields(Args, ET, S, MR, V). + +check_record({atom, _, Name}, ModFields, ET, Site, MR, V) -> + M = site_module(Site), {ok, R} = dict:find(M, MR), {ok, DeclFields} = lookup_record(Name, R), - case check_fields(ModFields, DeclFields, ET, M, MR, V) of + case check_fields(Name, ModFields, DeclFields, ET, Site, MR, V) of {error, FieldName} -> throw({error, io_lib:format("Illegal declaration of #~w{~w}\n", [Name, FieldName])}); ok -> ok end. -check_fields([{type, _, field_type, [{atom, _, Name}, Abstr]}|Left], - DeclFields, ET, M, MR, V) -> - Type = t_from_form(Abstr, ET, M, MR, V), +check_fields(RecName, [{type, _, field_type, [{atom, _, Name}, Abstr]}|Left], + DeclFields, ET, Site0, MR, V) -> + M = site_module(Site0), + Site = {record, {M, RecName, length(DeclFields)}}, + Type = t_from_form(Abstr, ET, Site, MR, V), {Name, _, DeclType} = lists:keyfind(Name, 1, DeclFields), TypeNoVars = subst_all_vars_to_any(Type), case t_is_subtype(TypeNoVars, DeclType) of false -> {error, Name}; - true -> check_fields(Left, DeclFields, ET, M, MR, V) + true -> check_fields(RecName, Left, DeclFields, ET, Site0, MR, V) end; -check_fields([], _Decl, _ET, _M, _MR, _V) -> +check_fields(_RecName, [], _Decl, _ET, _Site, _MR, _V) -> ok. -list_check_record_fields([], _ET, _M, _MR, _V) -> +list_check_record_fields([], _ET, _S, _MR, _V) -> ok; -list_check_record_fields([H|Tail], ET, M, MR, V) -> - ok = t_check_record_fields(H, ET, M, MR, V), - list_check_record_fields(Tail, ET, M, MR, V). +list_check_record_fields([H|Tail], ET, S, MR, V) -> + ok = t_check_record_fields(H, ET, S, MR, V), + list_check_record_fields(Tail, ET, S, MR, V). + +site_module({_, {Module, _, _}}) -> + Module. -spec t_var_names([erl_type()]) -> [atom()]. @@ -4594,8 +4610,9 @@ t_form_to_string({type, _L, Name, []} = T) -> M = mod, D0 = dict:new(), MR = dict:from_list([{M, D0}]), + S = {type, {M,Name,0}}, {T1, _} = - t_from_form(T, [], sets:new(), M, MR, D0, _Deep=1000, _ALot=100000), + t_from_form(T, [], sets:new(), S, MR, D0, _Deep=1000, _ALot=100000), t_to_string(T1) catch throw:{error, _} -> atom_to_string(Name) ++ "()" end; -- cgit v1.2.3 From 85f6fe3b1343c726a380b6efa4b108ab98eff00d Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 30 Jun 2015 14:35:53 +0200 Subject: dialyzer: Improve the handling of recursive parameterized opaque types --- lib/hipe/cerl/erl_types.erl | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index f0b907f86c..ad92324911 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -4010,16 +4010,25 @@ t_from_form_without_remote(Form, Site, TypeTable) -> -type expand_depth() :: integer(). +-spec t_from_form1(parse_form(), sets:set(mfa()) | 'replace_by_none', + site(), mod_records(), var_table()) -> + {erl_type(), expand_limit()}. + t_from_form1(Form, ET, Site, MR, V) -> - t_from_form1(Form, ET, Site, MR, V, ?EXPAND_DEPTH). + TypeNames = initial_typenames(Site), + t_from_form1(Form, TypeNames, ET, Site, MR, V, ?EXPAND_DEPTH). + +initial_typenames({type, _MTA}=Site) -> [Site]; +initial_typenames({spec, _MFA}) -> []; +initial_typenames({record, _MRA}) -> []. -t_from_form1(Form, ET, Site, MR, V, D) -> +t_from_form1(Form, TypeNames, ET, Site, MR, V, D) -> L = ?EXPAND_LIMIT, - {T, L1} = t_from_form(Form, [], ET, Site, MR, V, D, L), + {T, L1} = t_from_form(Form, TypeNames, ET, Site, MR, V, D, L), if L1 =< 0, D > 1 -> D1 = D div 2, - t_from_form1(Form, ET, Site, MR, V, D1); + t_from_form1(Form, TypeNames, ET, Site, MR, V, D1); true -> {T, L1} end. @@ -4259,7 +4268,7 @@ type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> false -> {t_any(), L1} end, Rep1 = choose_opaque_type(Rep, Type), - Rep2 = case t_is_none(Rep1) of + Rep2 = case cannot_have_opaque(Rep1, TypeName, TypeNames) of true -> Rep1; false -> ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), @@ -4307,18 +4316,19 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> case can_unfold_more(RemType, TypeNames) of true -> NewTypeNames = [RemType|TypeNames], - t_from_form(Form, NewTypeNames, ET, RemMod, MR, + Site = RemType, + t_from_form(Form, NewTypeNames, ET, Site, MR, TmpVarDict, D, L1); - false -> - {t_any(), L1} + false -> {t_any(), L1} end, NewRep1 = choose_opaque_type(NewRep, Type), - NewRep2 = case t_is_none(NewRep1) of - true -> NewRep1; + NewRep2 = + case cannot_have_opaque(NewRep1, RemType, TypeNames) of + true -> NewRep1; false -> ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), t_opaque(Mod, Name, ArgTypes2, NewRep1) - end, + end, {NewRep2, L2}; error -> Msg = io_lib:format("Unable to find remote type ~w:~w()\n", @@ -4704,6 +4714,12 @@ lookup_type(Name, Arity, RecDict) -> type_is_defined(TypeOrOpaque, Name, Arity, RecDict) -> dict:is_key({TypeOrOpaque, Name, Arity}, RecDict). +cannot_have_opaque(Type, TypeName, TypeNames) -> + t_is_none(Type) orelse is_recursive(TypeName, TypeNames). + +is_recursive(TypeName, TypeNames) -> + lists:member(TypeName, TypeNames). + can_unfold_more(TypeName, TypeNames) -> Fun = fun(E, Acc) -> case E of TypeName -> Acc + 1; _ -> Acc end end, lists:foldl(Fun, 0, TypeNames) < ?REC_TYPE_LIMIT. -- cgit v1.2.3 From 9a5788654c0e6a08b404ac3e68bf3894cf7e8252 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 2 Jul 2015 15:12:54 +0200 Subject: dialyzer: Optimize the expansion of parameterized types somewhat Expand parameters when needed only. The opaqueness is removed from types expanded to any(). --- lib/hipe/cerl/erl_types.erl | 94 ++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 43 deletions(-) (limited to 'lib') diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index ad92324911..f00663444a 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -4242,7 +4242,6 @@ builtin_type(Name, Type, TypeNames, ET, Site, MR, V, D, L) -> type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> ArgsLen = length(Args), - {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, Site0, MR, V, D, L), Module = site_module(Site0), {ok, R} = dict:find(Module, MR), TypeName = {type, {Module, Name, ArgsLen}}, @@ -4250,48 +4249,52 @@ type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> {type, {{Module, _FileName, Form, ArgNames}, _Type}} -> case can_unfold_more(TypeName, TypeNames) of true -> + {ArgTypes, L1} = + list_from_form(Args, TypeNames, ET, Site0, MR, V, D, L), List = lists:zip(ArgNames, ArgTypes), TmpV = dict:from_list(List), Site = TypeName, t_from_form(Form, [TypeName|TypeNames], ET, Site, MR, TmpV, D, L1); false -> - {t_any(), L1} + {t_any(), L} end; {opaque, {{Module, _FileName, Form, ArgNames}, Type}} -> - {Rep, L2} = - case can_unfold_more(TypeName, TypeNames) of - true -> - List = lists:zip(ArgNames, ArgTypes), - TmpV = dict:from_list(List), - Site = TypeName, - t_from_form(Form, [TypeName|TypeNames], ET, Site, MR, TmpV, D, L1); - false -> {t_any(), L1} - end, - Rep1 = choose_opaque_type(Rep, Type), - Rep2 = case cannot_have_opaque(Rep1, TypeName, TypeNames) of - true -> Rep1; - false -> - ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), - t_opaque(Module, Name, ArgTypes2, Rep1) - end, - {Rep2, L2}; + case can_unfold_more(TypeName, TypeNames) of + true -> + {ArgTypes, L1} = + list_from_form(Args, TypeNames, ET, Site0, MR, V, D, L), + List = lists:zip(ArgNames, ArgTypes), + TmpV = dict:from_list(List), + Site = TypeName, + {Rep, L2} = + t_from_form(Form, [TypeName|TypeNames], ET, Site, MR, + TmpV, D, L1), + Rep1 = choose_opaque_type(Rep, Type), + Rep2 = case cannot_have_opaque(Rep1, TypeName, TypeNames) of + true -> Rep1; + false -> + ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), + t_opaque(Module, Name, ArgTypes2, Rep1) + end, + {Rep2, L2}; + false -> {t_any(), L} + end; error -> Msg = io_lib:format("Unable to find type ~w/~w\n", [Name, ArgsLen]), throw({error, Msg}) end. remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> - {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, S, MR, V, D, L), if ET =:= replace_by_none -> - {t_none(), L1}; + {t_none(), L}; true -> ArgsLen = length(Args), MFA = {RemMod, Name, ArgsLen}, case dict:find(RemMod, MR) of error -> self() ! {self(), ext_types, MFA}, - {t_any(), L1}; + {t_any(), L}; {ok, RemDict} -> RemType = {type, MFA}, case sets:is_element(MFA, ET) of @@ -4300,6 +4303,8 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> {type, {{_Mod, _FileLine, Form, ArgNames}, _Type}} -> case can_unfold_more(RemType, TypeNames) of true -> + {ArgTypes, L1} = + list_from_form(Args, TypeNames, ET, S, MR, V, D, L), List = lists:zip(ArgNames, ArgTypes), TmpVarDict = dict:from_list(List), NewTypeNames = [RemType|TypeNames], @@ -4307,29 +4312,32 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> t_from_form(Form, NewTypeNames, ET, Site, MR, TmpVarDict, D, L1); false -> - {t_any(), L1} + {t_any(), L} end; {opaque, {{Mod, _FileLine, Form, ArgNames}, Type}} -> - List = lists:zip(ArgNames, ArgTypes), - TmpVarDict = dict:from_list(List), - {NewRep, L2} = - case can_unfold_more(RemType, TypeNames) of - true -> - NewTypeNames = [RemType|TypeNames], - Site = RemType, + case can_unfold_more(RemType, TypeNames) of + true -> + NewTypeNames = [RemType|TypeNames], + {ArgTypes, L1} = + list_from_form(Args, TypeNames, ET, S, MR, V, D, L), + List = lists:zip(ArgNames, ArgTypes), + TmpVarDict = dict:from_list(List), + Site = RemType, + {NewRep, L2} = t_from_form(Form, NewTypeNames, ET, Site, MR, - TmpVarDict, D, L1); - false -> {t_any(), L1} - end, - NewRep1 = choose_opaque_type(NewRep, Type), - NewRep2 = - case cannot_have_opaque(NewRep1, RemType, TypeNames) of - true -> NewRep1; - false -> - ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), - t_opaque(Mod, Name, ArgTypes2, NewRep1) - end, - {NewRep2, L2}; + TmpVarDict, D, L1), + NewRep1 = choose_opaque_type(NewRep, Type), + NewRep2 = + case cannot_have_opaque(NewRep1, RemType, TypeNames) of + true -> NewRep1; + false -> + ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), + t_opaque(Mod, Name, ArgTypes2, NewRep1) + end, + {NewRep2, L2}; + false -> + {t_any(), L} + end; error -> Msg = io_lib:format("Unable to find remote type ~w:~w()\n", [RemMod, Name]), @@ -4337,7 +4345,7 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> end; false -> self() ! {self(), ext_types, {RemMod, Name, ArgsLen}}, - {t_any(), L1} + {t_any(), L} end end end. -- cgit v1.2.3 From f51ee4709129bc2259e8dd443a278124b0d7e312 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 2 Jul 2015 15:52:19 +0200 Subject: dialyzer: Optimize expansion of parameters of opaque types Opaque recursive parameters are expanded faster. --- .../opaque_SUITE_data/src/big_external_type.erl | 526 +++++++++++++++++++++ .../test/opaque_SUITE_data/src/big_local_type.erl | 523 ++++++++++++++++++++ lib/hipe/cerl/erl_types.erl | 25 +- 3 files changed, 1063 insertions(+), 11 deletions(-) create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl (limited to 'lib') diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl new file mode 100644 index 0000000000..d286a378ed --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl @@ -0,0 +1,526 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%%% A copy of small_SUITE_data/src/big_external_type.erl, where +%%% abstract_expr() is opaque. The transformation of forms to types is +%%% now much faster than it used to be, for this module. + +-module(big_external_type). + +-export([parse_form/1,parse_exprs/1,parse_term/1]). +-export([normalise/1,tokens/1,tokens/2]). +-export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]). + +-export_type([abstract_clause/0, abstract_expr/0, abstract_form/0, + error_info/0]). + +%% Start of Abstract Format + +-type line() :: erl_anno:line(). + +-export_type([af_record_index/0, af_record_field/1, af_record_name/0, + af_field_name/0, af_function_decl/0]). + +-export_type([af_module/0, af_export/0, af_import/0, af_fa_list/0, + af_compile/0, af_file/0, af_record_decl/0, + af_field_decl/0, af_wild_attribute/0, + af_record_update/1, af_catch/0, af_local_call/0, + af_remote_call/0, af_args/0, af_local_function/0, + af_remote_function/0, af_list_comprehension/0, + af_binary_comprehension/0, af_template/0, + af_qualifier_seq/0, af_qualifier/0, af_generator/0, + af_filter/0, af_block/0, af_if/0, af_case/0, af_try/0, + af_clause_seq/0, af_catch_clause_seq/0, af_receive/0, + af_local_fun/0, af_remote_fun/0, af_fun/0, af_query/0, + af_query_access/0, af_clause/0, + af_catch_clause/0, af_catch_pattern/0, af_catch_class/0, + af_body/0, af_guard_seq/0, af_guard/0, af_guard_test/0, + af_record_access/1, af_guard_call/0, + af_remote_guard_call/0, af_pattern/0, af_literal/0, + af_atom/0, af_lit_atom/1, af_integer/0, af_float/0, + af_string/0, af_match/1, af_variable/0, + af_anon_variable/0, af_tuple/1, af_nil/0, af_cons/1, + af_bin/1, af_binelement/1, af_binelement_size/0, + af_binary_op/1, af_binop/0, af_unary_op/1, af_unop/0]). + +-type abstract_form() :: ?MODULE:af_module() + | ?MODULE:af_export() + | ?MODULE:af_import() + | ?MODULE:af_compile() + | ?MODULE:af_file() + | ?MODULE:af_record_decl() + | ?MODULE:af_wild_attribute() + | ?MODULE:af_function_decl(). + +-type af_module() :: {attribute, line(), module, module()}. + +-type af_export() :: {attribute, line(), export, ?MODULE:af_fa_list()}. + +-type af_import() :: {attribute, line(), import, ?MODULE:af_fa_list()}. + +-type af_fa_list() :: [{function(), arity()}]. + +-type af_compile() :: {attribute, line(), compile, any()}. + +-type af_file() :: {attribute, line(), file, {string(), line()}}. + +-type af_record_decl() :: + {attribute, line(), record, ?MODULE:af_record_name(), [?MODULE:af_field_decl()]}. + +-type af_field_decl() :: {record_field, line(), ?MODULE:af_atom()} + | {record_field, line(), ?MODULE:af_atom(), ?MODULE:abstract_expr()}. + +%% Types and specs, among other things... +-type af_wild_attribute() :: {attribute, line(), ?MODULE:af_atom(), any()}. + +-type af_function_decl() :: + {function, line(), function(), arity(), ?MODULE:af_clause_seq()}. + +-opaque abstract_expr() :: ?MODULE:af_literal() + | ?MODULE:af_match(?MODULE:abstract_expr()) + | ?MODULE:af_variable() + | ?MODULE:af_tuple(?MODULE:abstract_expr()) + | ?MODULE:af_nil() + | ?MODULE:af_cons(?MODULE:abstract_expr()) + | ?MODULE:af_bin(?MODULE:abstract_expr()) + | ?MODULE:af_binary_op(?MODULE:abstract_expr()) + | ?MODULE:af_unary_op(?MODULE:abstract_expr()) + | ?MODULE:af_record_access(?MODULE:abstract_expr()) + | ?MODULE:af_record_update(?MODULE:abstract_expr()) + | ?MODULE:af_record_index() + | ?MODULE:af_record_field(?MODULE:abstract_expr()) + | ?MODULE:af_catch() + | ?MODULE:af_local_call() + | ?MODULE:af_remote_call() + | ?MODULE:af_list_comprehension() + | ?MODULE:af_binary_comprehension() + | ?MODULE:af_block() + | ?MODULE:af_if() + | ?MODULE:af_case() + | ?MODULE:af_try() + | ?MODULE:af_receive() + | ?MODULE:af_local_fun() + | ?MODULE:af_remote_fun() + | ?MODULE:af_fun() + | ?MODULE:af_query() + | ?MODULE:af_query_access(). + +-type af_record_update(T) :: {record, + line(), + ?MODULE:abstract_expr(), + ?MODULE:af_record_name(), + [?MODULE:af_record_field(T)]}. + +-type af_catch() :: {'catch', line(), ?MODULE:abstract_expr()}. + +-type af_local_call() :: {call, line(), ?MODULE:af_local_function(), ?MODULE:af_args()}. + +-type af_remote_call() :: {call, line(), ?MODULE:af_remote_function(), ?MODULE:af_args()}. + +-type af_args() :: [?MODULE:abstract_expr()]. + +-type af_local_function() :: ?MODULE:abstract_expr(). + +-type af_remote_function() :: + {remote, line(), ?MODULE:abstract_expr(), ?MODULE:abstract_expr()}. + +-type af_list_comprehension() :: + {lc, line(), ?MODULE:af_template(), ?MODULE:af_qualifier_seq()}. + +-type af_binary_comprehension() :: + {bc, line(), ?MODULE:af_template(), ?MODULE:af_qualifier_seq()}. + +-type af_template() :: ?MODULE:abstract_expr(). + +-type af_qualifier_seq() :: [?MODULE:af_qualifier()]. + +-type af_qualifier() :: ?MODULE:af_generator() | ?MODULE:af_filter(). + +-type af_generator() :: {generate, line(), ?MODULE:af_pattern(), ?MODULE:abstract_expr()} + | {b_generate, line(), ?MODULE:af_pattern(), ?MODULE:abstract_expr()}. + +-type af_filter() :: ?MODULE:abstract_expr(). + +-type af_block() :: {block, line(), ?MODULE:af_body()}. + +-type af_if() :: {'if', line(), ?MODULE:af_clause_seq()}. + +-type af_case() :: {'case', line(), ?MODULE:abstract_expr(), ?MODULE:af_clause_seq()}. + +-type af_try() :: {'try', + line(), + ?MODULE:af_body(), + ?MODULE:af_clause_seq(), + ?MODULE:af_catch_clause_seq(), + ?MODULE:af_body()}. + +-type af_clause_seq() :: [?MODULE:af_clause(), ...]. + +-type af_catch_clause_seq() :: [?MODULE:af_clause(), ...]. + +-type af_receive() :: + {'receive', line(), ?MODULE:af_clause_seq()} + | {'receive', line(), ?MODULE:af_clause_seq(), ?MODULE:abstract_expr(), ?MODULE:af_body()}. + +-type af_local_fun() :: {'fun', line(), {function, function(), arity()}}. + +-type af_remote_fun() :: + {'fun', line(), {function, module(), function(), arity()}} + | {'fun', line(), {function, ?MODULE:af_atom(), ?MODULE:af_atom(), ?MODULE:af_integer()}}. + +-type af_fun() :: {'fun', line(), {clauses, ?MODULE:af_clause_seq()}}. + +-type af_query() :: {'query', line(), ?MODULE:af_list_comprehension()}. + +-type af_query_access() :: + {record_field, line(), ?MODULE:abstract_expr(), ?MODULE:af_field_name()}. + +-type abstract_clause() :: ?MODULE:af_clause() | ?MODULE:af_catch_clause(). + +-type af_clause() :: + {clause, line(), [?MODULE:af_pattern()], ?MODULE:af_guard_seq(), ?MODULE:af_body()}. + +-type af_catch_clause() :: + {clause, line(), [?MODULE:af_catch_pattern()], ?MODULE:af_guard_seq(), ?MODULE:af_body()}. + +-type af_catch_pattern() :: + {?MODULE:af_catch_class(), ?MODULE:af_pattern(), ?MODULE:af_anon_variable()}. + +-type af_catch_class() :: + ?MODULE:af_variable() + | ?MODULE:af_lit_atom(throw) | ?MODULE:af_lit_atom(error) | ?MODULE:af_lit_atom(exit). + +-type af_body() :: [?MODULE:abstract_expr(), ...]. + +-type af_guard_seq() :: [?MODULE:af_guard()]. + +-type af_guard() :: [?MODULE:af_guard_test(), ...]. + +-type af_guard_test() :: ?MODULE:af_literal() + | ?MODULE:af_variable() + | ?MODULE:af_tuple(?MODULE:af_guard_test()) + | ?MODULE:af_nil() + | ?MODULE:af_cons(?MODULE:af_guard_test()) + | ?MODULE:af_bin(?MODULE:af_guard_test()) + | ?MODULE:af_binary_op(?MODULE:af_guard_test()) + | ?MODULE:af_unary_op(?MODULE:af_guard_test()) + | ?MODULE:af_record_access(?MODULE:af_guard_test()) + | ?MODULE:af_record_index() + | ?MODULE:af_record_field(?MODULE:af_guard_test()) + | ?MODULE:af_guard_call() + | ?MODULE:af_remote_guard_call(). + +-type af_record_access(T) :: + {record, line(), ?MODULE:af_record_name(), [?MODULE:af_record_field(T)]}. + +-type af_guard_call() :: {call, line(), function(), [?MODULE:af_guard_test()]}. + +-type af_remote_guard_call() :: + {call, line(), atom(), ?MODULE:af_lit_atom(erlang), [?MODULE:af_guard_test()]}. + +-type af_pattern() :: ?MODULE:af_literal() + | ?MODULE:af_match(?MODULE:af_pattern()) + | ?MODULE:af_variable() + | ?MODULE:af_anon_variable() + | ?MODULE:af_tuple(?MODULE:af_pattern()) + | ?MODULE:af_nil() + | ?MODULE:af_cons(?MODULE:af_pattern()) + | ?MODULE:af_bin(?MODULE:af_pattern()) + | ?MODULE:af_binary_op(?MODULE:af_pattern()) + | ?MODULE:af_unary_op(?MODULE:af_pattern()) + | ?MODULE:af_record_index() + | ?MODULE:af_record_field(?MODULE:af_pattern()). + +-type af_literal() :: ?MODULE:af_atom() | ?MODULE:af_integer() | ?MODULE:af_float() | ?MODULE:af_string(). + +-type af_atom() :: ?MODULE:af_lit_atom(atom()). + +-type af_lit_atom(A) :: {atom, line(), A}. + +-type af_integer() :: {integer, line(), non_neg_integer()}. + +-type af_float() :: {float, line(), float()}. + +-type af_string() :: {string, line(), [byte()]}. + +-type af_match(T) :: {match, line(), T, T}. + +-type af_variable() :: {var, line(), atom()}. + +-type af_anon_variable() :: {var, line(), '_'}. + +-type af_tuple(T) :: {tuple, line(), [T]}. + +-type af_nil() :: {nil, line()}. + +-type af_cons(T) :: {cons, line, T, T}. + +-type af_bin(T) :: {bin, line(), [?MODULE:af_binelement(T)]}. + +-type af_binelement(T) :: {bin_element, + line(), + T, + ?MODULE:af_binelement_size(), + type_specifier_list()}. + +-type af_binelement_size() :: default | ?MODULE:abstract_expr(). + +-type af_binary_op(T) :: {op, line(), T, ?MODULE:af_binop(), T}. + +-type af_binop() :: '/' | '*' | 'div' | 'rem' | 'band' | 'and' | '+' | '-' + | 'bor' | 'bxor' | 'bsl' | 'bsr' | 'or' | 'xor' | '++' + | '--' | '==' | '/=' | '=<' | '<' | '>=' | '>' | '=:=' + | '=/='. + +-type af_unary_op(T) :: {op, line(), ?MODULE:af_unop(), T}. + +-type af_unop() :: '+' | '*' | 'bnot' | 'not'. + +%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}. +-type type_specifier_list() :: default | [type_specifier(), ...]. + +-type type_specifier() :: af_type() + | af_signedness() + | af_endianness() + | af_unit(). + +-type af_type() :: integer + | float + | binary + | bytes + | bitstring + | bits + | utf8 + | utf16 + | utf32. + +-type af_signedness() :: signed | unsigned. + +-type af_endianness() :: big | little | native. + +-type af_unit() :: {unit, 1..256}. + +-type af_record_index() :: + {record_index, line(), af_record_name(), af_field_name()}. + +-type af_record_field(T) :: {record_field, line(), af_field_name(), T}. + +-type af_record_name() :: atom(). + +-type af_field_name() :: atom(). + +%% End of Abstract Format + +-type error_description() :: term(). +-type error_info() :: {erl_anno:line(), module(), error_description()}. +-type token() :: {Tag :: atom(), Line :: erl_anno:line()}. + +%% mkop(Op, Arg) -> {op,Line,Op,Arg}. +%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}. + +-define(mkop2(L, OpPos, R), + begin + {Op,Pos} = OpPos, + {op,Pos,Op,L,R} + end). + +-define(mkop1(OpPos, A), + begin + {Op,Pos} = OpPos, + {op,Pos,Op,A} + end). + +%% keep track of line info in tokens +-define(line(Tup), element(2, Tup)). + +%% Entry points compatible to old erl_parse. +%% These really suck and are only here until Calle gets multiple +%% entry points working. + +-spec parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo} when + Tokens :: [token()], + AbsForm :: abstract_form(), + ErrorInfo :: error_info(). +parse_form([{'-',L1},{atom,L2,spec}|Tokens]) -> + parse([{'-',L1},{'spec',L2}|Tokens]); +parse_form([{'-',L1},{atom,L2,callback}|Tokens]) -> + parse([{'-',L1},{'callback',L2}|Tokens]); +parse_form(Tokens) -> + parse(Tokens). + +-spec parse_exprs(Tokens) -> {ok, ExprList} | {error, ErrorInfo} when + Tokens :: [token()], + ExprList :: [abstract_expr()], + ErrorInfo :: error_info(). +parse_exprs(Tokens) -> + case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of + {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} -> + {ok,Exprs}; + {error,_} = Err -> Err + end. + +-spec parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo} when + Tokens :: [token()], + Term :: term(), + ErrorInfo :: error_info(). +parse_term(Tokens) -> + case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of + {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} -> + try normalise(Expr) of + Term -> {ok,Term} + catch + _:_R -> {error,{?line(Expr),?MODULE,"bad term"}} + end; + {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[_E1,E2|_Es]}]}} -> + {error,{?line(E2),?MODULE,"bad term"}}; + {error,_} = Err -> Err + end. + +%% Convert between the abstract form of a term and a term. + +-spec normalise(AbsTerm) -> Data when + AbsTerm :: abstract_expr(), + Data :: term(). +normalise({char,_,C}) -> C; +normalise({integer,_,I}) -> I; +normalise({float,_,F}) -> F; +normalise({atom,_,A}) -> A; +normalise({string,_,S}) -> S; +normalise({nil,_}) -> []; +normalise({bin,_,Fs}) -> + {value, B, _} = + eval_bits:expr_grp(Fs, [], + fun(E, _) -> + {value, normalise(E), []} + end, [], true), + B; +normalise({cons,_,Head,Tail}) -> + [normalise(Head)|normalise(Tail)]; +normalise({tuple,_,Args}) -> + list_to_tuple(normalise_list(Args)); +%% Atom dot-notation, as in 'foo.bar.baz' +%% Special case for unary +/-. +normalise({op,_,'+',{char,_,I}}) -> I; +normalise({op,_,'+',{integer,_,I}}) -> I; +normalise({op,_,'+',{float,_,F}}) -> F; +normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible! +normalise({op,_,'-',{integer,_,I}}) -> -I; +normalise({op,_,'-',{float,_,F}}) -> -F; +normalise(X) -> erlang:error({badarg, X}). + +normalise_list([H|T]) -> + [normalise(H)|normalise_list(T)]; +normalise_list([]) -> + []. + +%% Generate a list of tokens representing the abstract term. + +-spec tokens(AbsTerm) -> Tokens when + AbsTerm :: abstract_expr(), + Tokens :: [token()]. +tokens(Abs) -> + tokens(Abs, []). + +-spec tokens(AbsTerm, MoreTokens) -> Tokens when + AbsTerm :: abstract_expr(), + MoreTokens :: [token()], + Tokens :: [token()]. +tokens({char,L,C}, More) -> [{char,L,C}|More]; +tokens({integer,L,N}, More) -> [{integer,L,N}|More]; +tokens({float,L,F}, More) -> [{float,L,F}|More]; +tokens({atom,L,A}, More) -> [{atom,L,A}|More]; +tokens({var,L,V}, More) -> [{var,L,V}|More]; +tokens({string,L,S}, More) -> [{string,L,S}|More]; +tokens({nil,L}, More) -> [{'[',L},{']',L}|More]; +tokens({cons,L,Head,Tail}, More) -> + [{'[',L}|tokens(Head, tokens_tail(Tail, More))]; +tokens({tuple,L,[]}, More) -> + [{'{',L},{'}',L}|More]; +tokens({tuple,L,[E|Es]}, More) -> + [{'{',L}|tokens(E, tokens_tuple(Es, ?line(E), More))]. + +tokens_tail({cons,L,Head,Tail}, More) -> + [{',',L}|tokens(Head, tokens_tail(Tail, More))]; +tokens_tail({nil,L}, More) -> + [{']',L}|More]; +tokens_tail(Other, More) -> + L = ?line(Other), + [{'|',L}|tokens(Other, [{']',L}|More])]. + +tokens_tuple([E|Es], Line, More) -> + [{',',Line}|tokens(E, tokens_tuple(Es, ?line(E), More))]; +tokens_tuple([], Line, More) -> + [{'}',Line}|More]. + +%% Give the relative precedences of operators. + +inop_prec('=') -> {150,100,100}; +inop_prec('!') -> {150,100,100}; +inop_prec('orelse') -> {160,150,150}; +inop_prec('andalso') -> {200,160,160}; +inop_prec('==') -> {300,200,300}; +inop_prec('/=') -> {300,200,300}; +inop_prec('=<') -> {300,200,300}; +inop_prec('<') -> {300,200,300}; +inop_prec('>=') -> {300,200,300}; +inop_prec('>') -> {300,200,300}; +inop_prec('=:=') -> {300,200,300}; +inop_prec('=/=') -> {300,200,300}; +inop_prec('++') -> {400,300,300}; +inop_prec('--') -> {400,300,300}; +inop_prec('+') -> {400,400,500}; +inop_prec('-') -> {400,400,500}; +inop_prec('bor') -> {400,400,500}; +inop_prec('bxor') -> {400,400,500}; +inop_prec('bsl') -> {400,400,500}; +inop_prec('bsr') -> {400,400,500}; +inop_prec('or') -> {400,400,500}; +inop_prec('xor') -> {400,400,500}; +inop_prec('*') -> {500,500,600}; +inop_prec('/') -> {500,500,600}; +inop_prec('div') -> {500,500,600}; +inop_prec('rem') -> {500,500,600}; +inop_prec('band') -> {500,500,600}; +inop_prec('and') -> {500,500,600}; +inop_prec('#') -> {800,700,800}; +inop_prec(':') -> {900,800,900}; +inop_prec('.') -> {900,900,1000}. + +-type pre_op() :: 'catch' | '+' | '-' | 'bnot' | 'not' | '#'. + +-spec preop_prec(pre_op()) -> {0 | 600 | 700, 100 | 700 | 800}. + +preop_prec('catch') -> {0,100}; +preop_prec('+') -> {600,700}; +preop_prec('-') -> {600,700}; +preop_prec('bnot') -> {600,700}; +preop_prec('not') -> {600,700}; +preop_prec('#') -> {700,800}. + +-spec func_prec() -> {800,700}. + +func_prec() -> {800,700}. + +-spec max_prec() -> 1000. + +max_prec() -> 1000. + +parse(T) -> + bar:foo(T). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl new file mode 100644 index 0000000000..7daceb5260 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl @@ -0,0 +1,523 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%%% A copy of small_SUITE_data/src/big_local_type.erl, where +%%% abstract_expr() is opaque. The transformation of forms to types is +%%% now much faster than it used to be, for this module. + +-module(big_local_type). + +-export([parse_form/1,parse_exprs/1,parse_term/1]). +-export([normalise/1,tokens/1,tokens/2]). +-export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]). + +-export_type([abstract_clause/0, abstract_expr/0, abstract_form/0, + error_info/0]). + +%% Start of Abstract Format + +-type line() :: erl_anno:line(). + +-export_type([af_module/0, af_export/0, af_import/0, af_fa_list/0, + af_compile/0, af_file/0, af_record_decl/0, + af_field_decl/0, af_wild_attribute/0, + af_record_update/1, af_catch/0, af_local_call/0, + af_remote_call/0, af_args/0, af_local_function/0, + af_remote_function/0, af_list_comprehension/0, + af_binary_comprehension/0, af_template/0, + af_qualifier_seq/0, af_qualifier/0, af_generator/0, + af_filter/0, af_block/0, af_if/0, af_case/0, af_try/0, + af_clause_seq/0, af_catch_clause_seq/0, af_receive/0, + af_local_fun/0, af_remote_fun/0, af_fun/0, af_query/0, + af_query_access/0, af_clause/0, + af_catch_clause/0, af_catch_pattern/0, af_catch_class/0, + af_body/0, af_guard_seq/0, af_guard/0, af_guard_test/0, + af_record_access/1, af_guard_call/0, + af_remote_guard_call/0, af_pattern/0, af_literal/0, + af_atom/0, af_lit_atom/1, af_integer/0, af_float/0, + af_string/0, af_match/1, af_variable/0, + af_anon_variable/0, af_tuple/1, af_nil/0, af_cons/1, + af_bin/1, af_binelement/1, af_binelement_size/0, + af_binary_op/1, af_binop/0, af_unary_op/1, af_unop/0]). + +-type abstract_form() :: af_module() + | af_export() + | af_import() + | af_compile() + | af_file() + | af_record_decl() + | af_wild_attribute() + | af_function_decl(). + +-type af_module() :: {attribute, line(), module, module()}. + +-type af_export() :: {attribute, line(), export, af_fa_list()}. + +-type af_import() :: {attribute, line(), import, af_fa_list()}. + +-type af_fa_list() :: [{function(), arity()}]. + +-type af_compile() :: {attribute, line(), compile, any()}. + +-type af_file() :: {attribute, line(), file, {string(), line()}}. + +-type af_record_decl() :: + {attribute, line(), record, af_record_name(), [af_field_decl()]}. + +-type af_field_decl() :: {record_field, line(), af_atom()} + | {record_field, line(), af_atom(), abstract_expr()}. + +%% Types and specs, among other things... +-type af_wild_attribute() :: {attribute, line(), af_atom(), any()}. + +-type af_function_decl() :: + {function, line(), function(), arity(), af_clause_seq()}. + +-opaque abstract_expr() :: af_literal() + | af_match(abstract_expr()) + | af_variable() + | af_tuple(abstract_expr()) + | af_nil() + | af_cons(abstract_expr()) + | af_bin(abstract_expr()) + | af_binary_op(abstract_expr()) + | af_unary_op(abstract_expr()) + | af_record_access(abstract_expr()) + | af_record_update(abstract_expr()) + | af_record_index() + | af_record_field(abstract_expr()) + | af_catch() + | af_local_call() + | af_remote_call() + | af_list_comprehension() + | af_binary_comprehension() + | af_block() + | af_if() + | af_case() + | af_try() + | af_receive() + | af_local_fun() + | af_remote_fun() + | af_fun() + | af_query() + | af_query_access(). + +-type af_record_update(T) :: {record, + line(), + abstract_expr(), + af_record_name(), + [af_record_field(T)]}. + +-type af_catch() :: {'catch', line(), abstract_expr()}. + +-type af_local_call() :: {call, line(), af_local_function(), af_args()}. + +-type af_remote_call() :: {call, line(), af_remote_function(), af_args()}. + +-type af_args() :: [abstract_expr()]. + +-type af_local_function() :: abstract_expr(). + +-type af_remote_function() :: + {remote, line(), abstract_expr(), abstract_expr()}. + +-type af_list_comprehension() :: + {lc, line(), af_template(), af_qualifier_seq()}. + +-type af_binary_comprehension() :: + {bc, line(), af_template(), af_qualifier_seq()}. + +-type af_template() :: abstract_expr(). + +-type af_qualifier_seq() :: [af_qualifier()]. + +-type af_qualifier() :: af_generator() | af_filter(). + +-type af_generator() :: {generate, line(), af_pattern(), abstract_expr()} + | {b_generate, line(), af_pattern(), abstract_expr()}. + +-type af_filter() :: abstract_expr(). + +-type af_block() :: {block, line(), af_body()}. + +-type af_if() :: {'if', line(), af_clause_seq()}. + +-type af_case() :: {'case', line(), abstract_expr(), af_clause_seq()}. + +-type af_try() :: {'try', + line(), + af_body(), + af_clause_seq(), + af_catch_clause_seq(), + af_body()}. + +-type af_clause_seq() :: [af_clause(), ...]. + +-type af_catch_clause_seq() :: [af_clause(), ...]. + +-type af_receive() :: + {'receive', line(), af_clause_seq()} + | {'receive', line(), af_clause_seq(), abstract_expr(), af_body()}. + +-type af_local_fun() :: {'fun', line(), {function, function(), arity()}}. + +-type af_remote_fun() :: + {'fun', line(), {function, module(), function(), arity()}} + | {'fun', line(), {function, af_atom(), af_atom(), af_integer()}}. + +-type af_fun() :: {'fun', line(), {clauses, af_clause_seq()}}. + +-type af_query() :: {'query', line(), af_list_comprehension()}. + +-type af_query_access() :: + {record_field, line(), abstract_expr(), af_field_name()}. + +-type abstract_clause() :: af_clause() | af_catch_clause(). + +-type af_clause() :: + {clause, line(), [af_pattern()], af_guard_seq(), af_body()}. + +-type af_catch_clause() :: + {clause, line(), [af_catch_pattern()], af_guard_seq(), af_body()}. + +-type af_catch_pattern() :: + {af_catch_class(), af_pattern(), af_anon_variable()}. + +-type af_catch_class() :: + af_variable() + | af_lit_atom(throw) | af_lit_atom(error) | af_lit_atom(exit). + +-type af_body() :: [abstract_expr(), ...]. + +-type af_guard_seq() :: [af_guard()]. + +-type af_guard() :: [af_guard_test(), ...]. + +-type af_guard_test() :: af_literal() + | af_variable() + | af_tuple(af_guard_test()) + | af_nil() + | af_cons(af_guard_test()) + | af_bin(af_guard_test()) + | af_binary_op(af_guard_test()) + | af_unary_op(af_guard_test()) + | af_record_access(af_guard_test()) + | af_record_index() + | af_record_field(af_guard_test()) + | af_guard_call() + | af_remote_guard_call(). + +-type af_record_access(T) :: + {record, line(), af_record_name(), [af_record_field(T)]}. + +-type af_guard_call() :: {call, line(), function(), [af_guard_test()]}. + +-type af_remote_guard_call() :: + {call, line(), atom(), af_lit_atom(erlang), [af_guard_test()]}. + +-type af_pattern() :: af_literal() + | af_match(af_pattern()) + | af_variable() + | af_anon_variable() + | af_tuple(af_pattern()) + | af_nil() + | af_cons(af_pattern()) + | af_bin(af_pattern()) + | af_binary_op(af_pattern()) + | af_unary_op(af_pattern()) + | af_record_index() + | af_record_field(af_pattern()). + +-type af_literal() :: af_atom() | af_integer() | af_float() | af_string(). + +-type af_atom() :: af_lit_atom(atom()). + +-type af_lit_atom(A) :: {atom, line(), A}. + +-type af_integer() :: {integer, line(), non_neg_integer()}. + +-type af_float() :: {float, line(), float()}. + +-type af_string() :: {string, line(), [byte()]}. + +-type af_match(T) :: {match, line(), T, T}. + +-type af_variable() :: {var, line(), atom()}. + +-type af_anon_variable() :: {var, line(), '_'}. + +-type af_tuple(T) :: {tuple, line(), [T]}. + +-type af_nil() :: {nil, line()}. + +-type af_cons(T) :: {cons, line, T, T}. + +-type af_bin(T) :: {bin, line(), [af_binelement(T)]}. + +-type af_binelement(T) :: {bin_element, + line(), + T, + af_binelement_size(), + type_specifier_list()}. + +-type af_binelement_size() :: default | abstract_expr(). + +-type af_binary_op(T) :: {op, line(), T, af_binop(), T}. + +-type af_binop() :: '/' | '*' | 'div' | 'rem' | 'band' | 'and' | '+' | '-' + | 'bor' | 'bxor' | 'bsl' | 'bsr' | 'or' | 'xor' | '++' + | '--' | '==' | '/=' | '=<' | '<' | '>=' | '>' | '=:=' + | '=/='. + +-type af_unary_op(T) :: {op, line(), af_unop(), T}. + +-type af_unop() :: '+' | '*' | 'bnot' | 'not'. + +%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}. +-type type_specifier_list() :: default | [type_specifier(), ...]. + +-type type_specifier() :: af_type() + | af_signedness() + | af_endianness() + | af_unit(). + +-type af_type() :: integer + | float + | binary + | bytes + | bitstring + | bits + | utf8 + | utf16 + | utf32. + +-type af_signedness() :: signed | unsigned. + +-type af_endianness() :: big | little | native. + +-type af_unit() :: {unit, 1..256}. + +-type af_record_index() :: + {record_index, line(), af_record_name(), af_field_name()}. + +-type af_record_field(T) :: {record_field, line(), af_field_name(), T}. + +-type af_record_name() :: atom(). + +-type af_field_name() :: atom(). + +%% End of Abstract Format + +-type error_description() :: term(). +-type error_info() :: {erl_anno:line(), module(), error_description()}. +-type token() :: {Tag :: atom(), Line :: erl_anno:line()}. + +%% mkop(Op, Arg) -> {op,Line,Op,Arg}. +%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}. + +-define(mkop2(L, OpPos, R), + begin + {Op,Pos} = OpPos, + {op,Pos,Op,L,R} + end). + +-define(mkop1(OpPos, A), + begin + {Op,Pos} = OpPos, + {op,Pos,Op,A} + end). + +%% keep track of line info in tokens +-define(line(Tup), element(2, Tup)). + +%% Entry points compatible to old erl_parse. +%% These really suck and are only here until Calle gets multiple +%% entry points working. + +-spec parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo} when + Tokens :: [token()], + AbsForm :: abstract_form(), + ErrorInfo :: error_info(). +parse_form([{'-',L1},{atom,L2,spec}|Tokens]) -> + parse([{'-',L1},{'spec',L2}|Tokens]); +parse_form([{'-',L1},{atom,L2,callback}|Tokens]) -> + parse([{'-',L1},{'callback',L2}|Tokens]); +parse_form(Tokens) -> + parse(Tokens). + +-spec parse_exprs(Tokens) -> {ok, ExprList} | {error, ErrorInfo} when + Tokens :: [token()], + ExprList :: [abstract_expr()], + ErrorInfo :: error_info(). +parse_exprs(Tokens) -> + case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of + {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} -> + {ok,Exprs}; + {error,_} = Err -> Err + end. + +-spec parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo} when + Tokens :: [token()], + Term :: term(), + ErrorInfo :: error_info(). +parse_term(Tokens) -> + case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of + {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} -> + try normalise(Expr) of + Term -> {ok,Term} + catch + _:_R -> {error,{?line(Expr),?MODULE,"bad term"}} + end; + {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[_E1,E2|_Es]}]}} -> + {error,{?line(E2),?MODULE,"bad term"}}; + {error,_} = Err -> Err + end. + +%% Convert between the abstract form of a term and a term. + +-spec normalise(AbsTerm) -> Data when + AbsTerm :: abstract_expr(), + Data :: term(). +normalise({char,_,C}) -> C; +normalise({integer,_,I}) -> I; +normalise({float,_,F}) -> F; +normalise({atom,_,A}) -> A; +normalise({string,_,S}) -> S; +normalise({nil,_}) -> []; +normalise({bin,_,Fs}) -> + {value, B, _} = + eval_bits:expr_grp(Fs, [], + fun(E, _) -> + {value, normalise(E), []} + end, [], true), + B; +normalise({cons,_,Head,Tail}) -> + [normalise(Head)|normalise(Tail)]; +normalise({tuple,_,Args}) -> + list_to_tuple(normalise_list(Args)); +%% Atom dot-notation, as in 'foo.bar.baz' +%% Special case for unary +/-. +normalise({op,_,'+',{char,_,I}}) -> I; +normalise({op,_,'+',{integer,_,I}}) -> I; +normalise({op,_,'+',{float,_,F}}) -> F; +normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible! +normalise({op,_,'-',{integer,_,I}}) -> -I; +normalise({op,_,'-',{float,_,F}}) -> -F; +normalise(X) -> erlang:error({badarg, X}). + +normalise_list([H|T]) -> + [normalise(H)|normalise_list(T)]; +normalise_list([]) -> + []. + +%% Generate a list of tokens representing the abstract term. + +-spec tokens(AbsTerm) -> Tokens when + AbsTerm :: abstract_expr(), + Tokens :: [token()]. +tokens(Abs) -> + tokens(Abs, []). + +-spec tokens(AbsTerm, MoreTokens) -> Tokens when + AbsTerm :: abstract_expr(), + MoreTokens :: [token()], + Tokens :: [token()]. +tokens({char,L,C}, More) -> [{char,L,C}|More]; +tokens({integer,L,N}, More) -> [{integer,L,N}|More]; +tokens({float,L,F}, More) -> [{float,L,F}|More]; +tokens({atom,L,A}, More) -> [{atom,L,A}|More]; +tokens({var,L,V}, More) -> [{var,L,V}|More]; +tokens({string,L,S}, More) -> [{string,L,S}|More]; +tokens({nil,L}, More) -> [{'[',L},{']',L}|More]; +tokens({cons,L,Head,Tail}, More) -> + [{'[',L}|tokens(Head, tokens_tail(Tail, More))]; +tokens({tuple,L,[]}, More) -> + [{'{',L},{'}',L}|More]; +tokens({tuple,L,[E|Es]}, More) -> + [{'{',L}|tokens(E, tokens_tuple(Es, ?line(E), More))]. + +tokens_tail({cons,L,Head,Tail}, More) -> + [{',',L}|tokens(Head, tokens_tail(Tail, More))]; +tokens_tail({nil,L}, More) -> + [{']',L}|More]; +tokens_tail(Other, More) -> + L = ?line(Other), + [{'|',L}|tokens(Other, [{']',L}|More])]. + +tokens_tuple([E|Es], Line, More) -> + [{',',Line}|tokens(E, tokens_tuple(Es, ?line(E), More))]; +tokens_tuple([], Line, More) -> + [{'}',Line}|More]. + +%% Give the relative precedences of operators. + +inop_prec('=') -> {150,100,100}; +inop_prec('!') -> {150,100,100}; +inop_prec('orelse') -> {160,150,150}; +inop_prec('andalso') -> {200,160,160}; +inop_prec('==') -> {300,200,300}; +inop_prec('/=') -> {300,200,300}; +inop_prec('=<') -> {300,200,300}; +inop_prec('<') -> {300,200,300}; +inop_prec('>=') -> {300,200,300}; +inop_prec('>') -> {300,200,300}; +inop_prec('=:=') -> {300,200,300}; +inop_prec('=/=') -> {300,200,300}; +inop_prec('++') -> {400,300,300}; +inop_prec('--') -> {400,300,300}; +inop_prec('+') -> {400,400,500}; +inop_prec('-') -> {400,400,500}; +inop_prec('bor') -> {400,400,500}; +inop_prec('bxor') -> {400,400,500}; +inop_prec('bsl') -> {400,400,500}; +inop_prec('bsr') -> {400,400,500}; +inop_prec('or') -> {400,400,500}; +inop_prec('xor') -> {400,400,500}; +inop_prec('*') -> {500,500,600}; +inop_prec('/') -> {500,500,600}; +inop_prec('div') -> {500,500,600}; +inop_prec('rem') -> {500,500,600}; +inop_prec('band') -> {500,500,600}; +inop_prec('and') -> {500,500,600}; +inop_prec('#') -> {800,700,800}; +inop_prec(':') -> {900,800,900}; +inop_prec('.') -> {900,900,1000}. + +-type pre_op() :: 'catch' | '+' | '-' | 'bnot' | 'not' | '#'. + +-spec preop_prec(pre_op()) -> {0 | 600 | 700, 100 | 700 | 800}. + +preop_prec('catch') -> {0,100}; +preop_prec('+') -> {600,700}; +preop_prec('-') -> {600,700}; +preop_prec('bnot') -> {600,700}; +preop_prec('not') -> {600,700}; +preop_prec('#') -> {700,800}. + +-spec func_prec() -> {800,700}. + +func_prec() -> {800,700}. + +-spec max_prec() -> 1000. + +max_prec() -> 1000. + +parse(T) -> + bar:foo(T). diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index f00663444a..56ec757dbf 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -4249,26 +4249,27 @@ type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> {type, {{Module, _FileName, Form, ArgNames}, _Type}} -> case can_unfold_more(TypeName, TypeNames) of true -> + NewTypeNames = [TypeName|TypeNames], {ArgTypes, L1} = list_from_form(Args, TypeNames, ET, Site0, MR, V, D, L), List = lists:zip(ArgNames, ArgTypes), TmpV = dict:from_list(List), Site = TypeName, - t_from_form(Form, [TypeName|TypeNames], ET, Site, MR, TmpV, D, L1); + t_from_form(Form, NewTypeNames, ET, Site, MR, TmpV, D, L1); false -> {t_any(), L} end; {opaque, {{Module, _FileName, Form, ArgNames}, Type}} -> case can_unfold_more(TypeName, TypeNames) of true -> + NewTypeNames = [TypeName|TypeNames], {ArgTypes, L1} = - list_from_form(Args, TypeNames, ET, Site0, MR, V, D, L), + list_from_form(Args, NewTypeNames, ET, Site0, MR, V, D, L), List = lists:zip(ArgNames, ArgTypes), TmpV = dict:from_list(List), Site = TypeName, {Rep, L2} = - t_from_form(Form, [TypeName|TypeNames], ET, Site, MR, - TmpV, D, L1), + t_from_form(Form, NewTypeNames, ET, Site, MR, TmpV, D, L1), Rep1 = choose_opaque_type(Rep, Type), Rep2 = case cannot_have_opaque(Rep1, TypeName, TypeNames) of true -> Rep1; @@ -4278,7 +4279,7 @@ type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> end, {Rep2, L2}; false -> {t_any(), L} - end; + end; error -> Msg = io_lib:format("Unable to find type ~w/~w\n", [Name, ArgsLen]), throw({error, Msg}) @@ -4303,11 +4304,11 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> {type, {{_Mod, _FileLine, Form, ArgNames}, _Type}} -> case can_unfold_more(RemType, TypeNames) of true -> - {ArgTypes, L1} = - list_from_form(Args, TypeNames, ET, S, MR, V, D, L), + NewTypeNames = [RemType|TypeNames], + {ArgTypes, L1} = list_from_form(Args, TypeNames, + ET, S, MR, V, D, L), List = lists:zip(ArgNames, ArgTypes), TmpVarDict = dict:from_list(List), - NewTypeNames = [RemType|TypeNames], Site = RemType, t_from_form(Form, NewTypeNames, ET, Site, MR, TmpVarDict, D, L1); @@ -4318,8 +4319,8 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> case can_unfold_more(RemType, TypeNames) of true -> NewTypeNames = [RemType|TypeNames], - {ArgTypes, L1} = - list_from_form(Args, TypeNames, ET, S, MR, V, D, L), + {ArgTypes, L1} = list_from_form(Args, NewTypeNames, + ET, S, MR, V, D, L), List = lists:zip(ArgNames, ArgTypes), TmpVarDict = dict:from_list(List), Site = RemType, @@ -4328,7 +4329,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> TmpVarDict, D, L1), NewRep1 = choose_opaque_type(NewRep, Type), NewRep2 = - case cannot_have_opaque(NewRep1, RemType, TypeNames) of + case + cannot_have_opaque(NewRep1, RemType, TypeNames) + of true -> NewRep1; false -> ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), -- cgit v1.2.3 From a9f3424c8a04247a96e8bb5aed19b30276fcbad7 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 21 Aug 2015 15:06:56 +0200 Subject: dialyzer: Correct the timing of the phase called 'remote' --- lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index 76b43b6ff0..c57a22129c 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -167,9 +167,12 @@ analysis_start(Parent, Analysis, LegalWarnings) -> TmpCServer2 = dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes, TmpCServer1), - TmpCServer3 = dialyzer_utils:process_record_remote_types(TmpCServer2), ?timing(State#analysis_state.timing_server, "remote", - dialyzer_contracts:process_contract_remote_types(TmpCServer3)) + begin + TmpCServer3 = + dialyzer_utils:process_record_remote_types(TmpCServer2), + dialyzer_contracts:process_contract_remote_types(TmpCServer3) + end) catch throw:{error, _ErrorMsg} = Error -> exit(Error) end, -- cgit v1.2.3 From 363b2038feb3c668395c6c145d83910a04cebea5 Mon Sep 17 00:00:00 2001 From: Constantin Rack Date: Tue, 25 Aug 2015 10:35:03 +0200 Subject: Fix typo --- lib/compiler/src/genop.tab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab index 8f7b5add1d..ab227e5452 100755 --- a/lib/compiler/src/genop.tab +++ b/lib/compiler/src/genop.tab @@ -316,7 +316,7 @@ BEAM_FORMAT_NUMBER=0 66: get_tuple_element/3 ## @spec set_tuple_element NewElement Tuple Position -## @doc Update the element at postition Position of the tuple Tuple +## @doc Update the element at position Position of the tuple Tuple ## with the new element NewElement. 67: set_tuple_element/3 -- cgit v1.2.3 From 2564e317e34fe7f928bf6e234998b295848a5c91 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 20 Aug 2015 14:40:39 +0200 Subject: ssh: add extra random length padding in packets A new experimental option 'max_random_length_padding', not documented so it might change... --- lib/ssh/src/ssh.erl | 5 +++++ lib/ssh/src/ssh.hrl | 1 + lib/ssh/src/ssh_connection_handler.erl | 10 ++++++++-- lib/ssh/src/ssh_transport.erl | 15 +++++++++++---- lib/ssh/test/ssh_basic_SUITE.erl | 2 ++ 5 files changed, 27 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 5b2e0a988c..132de71aed 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -397,6 +397,8 @@ handle_option([{id_string, _ID} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{profile, _ID} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{max_random_length_padding, _Bool} = Opt|Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions). @@ -515,6 +517,9 @@ handle_ssh_option({id_string, random}) -> {id_string, {random,2,5}}; %% 2 - 5 random characters handle_ssh_option({id_string, ID} = Opt) when is_list(ID) -> Opt; +handle_ssh_option({max_random_length_padding, Value} = Opt) when is_integer(Value), + Value =< 255 -> + Opt; handle_ssh_option({profile, Value} = Opt) when is_atom(Value) -> Opt; handle_ssh_option(Opt) -> diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 8df5ee820c..462c98f503 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -124,6 +124,7 @@ recv_sequence = 0, keyex_key, keyex_info, + random_length_padding = 255, % From RFC 4253 section 6. %% User auth user, diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index c059834b27..180698d741 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1187,7 +1187,10 @@ init_ssh(client = Role, Vsn, Version, Options, Socket) -> opts = Options, userauth_supported_methods = AuthMethods, peer = {PeerName, PeerAddr}, - available_host_keys = supported_host_keys(Role, KeyCb, Options) + available_host_keys = supported_host_keys(Role, KeyCb, Options), + random_length_padding = proplists:get_value(max_random_length_padding, + Options, + (#ssh{})#ssh.random_length_padding) }; init_ssh(server = Role, Vsn, Version, Options, Socket) -> @@ -1207,7 +1210,10 @@ init_ssh(server = Role, Vsn, Version, Options, Socket) -> userauth_methods = AuthMethodsAsList, kb_tries_left = 3, peer = {undefined, PeerAddr}, - available_host_keys = supported_host_keys(Role, KeyCb, Options) + available_host_keys = supported_host_keys(Role, KeyCb, Options), + random_length_padding = proplists:get_value(max_random_length_padding, + Options, + (#ssh{})#ssh.random_length_padding) }. supported_host_keys(client, _, Options) -> diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 38a0b7ec7c..9ed6c85ff7 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -745,13 +745,20 @@ ssh_packet(Msg, Ssh) -> pack(Data0, #ssh{encrypt_block_size = BlockSize, send_sequence = SeqNum, send_mac = MacAlg, - send_mac_key = MacKey} + send_mac_key = MacKey, + random_length_padding = RandomLengthPadding} = Ssh0) when is_binary(Data0) -> {Ssh1, Data} = compress(Ssh0, Data0), PL = (BlockSize - ((4 + 1 + size(Data)) rem BlockSize)) rem BlockSize, - PaddingLen = if PL < 4 -> PL + BlockSize; - true -> PL - end, + MinPaddingLen = if PL < 4 -> PL + BlockSize; + true -> PL + end, + PadBlockSize = max(BlockSize,4), + MaxExtraBlocks = (max(RandomLengthPadding,MinPaddingLen) - MinPaddingLen) div PadBlockSize, + ExtraPaddingLen = try crypto:rand_uniform(0,MaxExtraBlocks)*PadBlockSize + catch _:_ -> 0 + end, + PaddingLen = MinPaddingLen + ExtraPaddingLen, Padding = ssh_bits:random(PaddingLen), PacketLen = 1 + PaddingLen + size(Data), PacketData = < DataFile = filename:join(UserDir, "rekey.data"), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {max_random_length_padding, 0}, {user_dir, UserDir}, {user_passwords, [{"simon", "says"}]}]), @@ -475,6 +476,7 @@ rekey_limit(Config) -> {user, "simon"}, {password, "says"}, {rekey_limit, 2500}, + {max_random_length_padding, 0}, {user_interaction, false}, {silently_accept_hosts, true}]), -- cgit v1.2.3 From 16d57dfa1ace44e0cc6b6bd04e0819ca8566da41 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Fri, 28 Aug 2015 12:51:45 +0200 Subject: wx: Add missing aui functionality --- lib/wx/api_gen/Makefile | 2 +- lib/wx/api_gen/wx_extra/func30.h | 8 + lib/wx/api_gen/wx_gen.erl | 5 +- lib/wx/api_gen/wx_gen_cpp.erl | 22 +- lib/wx/api_gen/wxapi.conf | 12 +- lib/wx/c_src/gen/wxe_events.cpp | 575 +++++------ lib/wx/c_src/gen/wxe_funcs.cpp | 145 ++- lib/wx/c_src/gen/wxe_macros.h | 1774 +++++++++++++++++----------------- lib/wx/examples/demo/ex_aui.erl | 81 +- lib/wx/include/wx.hrl | 2 +- lib/wx/src/gen/wxAuiDockArt.erl | 59 +- lib/wx/src/gen/wxAuiManagerEvent.erl | 4 +- lib/wx/src/gen/wxAuiSimpleTabArt.erl | 67 ++ lib/wx/src/gen/wxAuiTabArt.erl | 59 +- lib/wx/src/gen/wxe_debug.hrl | 1774 +++++++++++++++++----------------- lib/wx/src/gen/wxe_funcs.hrl | 1774 +++++++++++++++++----------------- 16 files changed, 3376 insertions(+), 2987 deletions(-) create mode 100644 lib/wx/api_gen/wx_extra/func30.h create mode 100644 lib/wx/src/gen/wxAuiSimpleTabArt.erl (limited to 'lib') diff --git a/lib/wx/api_gen/Makefile b/lib/wx/api_gen/Makefile index d605f3d8d8..29ff185760 100644 --- a/lib/wx/api_gen/Makefile +++ b/lib/wx/api_gen/Makefile @@ -49,7 +49,7 @@ opt: $(WX) $(GL) $(WX): wxxml_generated $(COMPILER_T) wxapi.conf $(wildcard wx_extra/wx*.c_src) $(wildcard wx_extra/wx*.erl) erl -noshell -run wx_gen code && touch wx_code_generated -wxxml_generated: wx_doxygen.conf wx_extra/bugs.h wx_extra/wxe_evth.h +wxxml_generated: wx_doxygen.conf wx_extra/bugs.h wx_extra/wxe_evth.h wx_extra/func30.h sed -e 's|@WXGTK_DIR@|$(WXGTK_DIR)|g' wx_doxygen.conf > wx_doxygen doxygen wx_doxygen && touch wxxml_generated diff --git a/lib/wx/api_gen/wx_extra/func30.h b/lib/wx/api_gen/wx_extra/func30.h new file mode 100644 index 0000000000..383ea08b93 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/func30.h @@ -0,0 +1,8 @@ +// Added 3.0 functionality + +class WXDLLIMPEXP_AUI wxAuiTabArt +{ +public: + virtual void SetColour(const wxColour& colour) = 0; + virtual void SetActiveColour(const wxColour& colour) = 0; +} diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl index 114b3e561e..e6fc6570f9 100644 --- a/lib/wx/api_gen/wx_gen.erl +++ b/lib/wx/api_gen/wx_gen.erl @@ -777,8 +777,9 @@ parse_type2([N="wxRect"|R],Info,Opts,T) -> parse_type2([N="wxColour"|R],Info,Opts,T) -> parse_type2(R,Info,Opts,T#type{name=N, base={comp,N,[{int,"R"},{int,"G"},{int,"B"},{int,"A"}]}}); -parse_type2([N="wxColor"|R],Info,Opts,T) -> - parse_type2(R,Info,Opts,T#type{name="wxColour", +parse_type2(["wxColor"|R],Info,Opts,T) -> + N = "wxColour", + parse_type2(R,Info,Opts,T#type{name=N, base={comp,N,[{int,"R"},{int,"G"},{int,"B"},{int,"A"}]}}); parse_type2([N="wxPoint2DDouble"|R],Info,Opts,T) -> diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index 2ce6295078..5ce60391c1 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -235,7 +235,8 @@ gen_funcs(Defs) -> w("}} /* The End */~n~n~n"), UglySkipList = ["wxCaret", "wxCalendarDateAttr", - "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject" + "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject", + "wxAuiSimpleTabArt" ], w("bool WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []), @@ -323,12 +324,8 @@ gen_method(CName, M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId put(current_func, N), put(bin_count,-1), ?WTC("gen_method"), - Endif = case lists:keysearch(deprecated, 1, FOpts) of - {value, {deprecated, IfDef}} -> - w("#if ~s~n", [IfDef]), - true; - _ -> false - end, + Endif1 = gen_if(deprecated, FOpts), + Endif2 = gen_if(test_if, FOpts), w("case ~s: { // ~s::~s~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]), Ps1 = declare_variables(void, Ps0), {Ps2,Align} = decode_arguments(Ps1), @@ -347,10 +344,19 @@ gen_method(CName, M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId free_args(), build_return_vals(T,Ps3), w(" break;~n}~n", []), - Endif andalso w("#endif~n", []), + Endif1 andalso w("#endif~n", []), + Endif2 andalso w("#endif~n", []), erase(current_func), M. +gen_if(What, Opts) -> + case lists:keysearch(What, 1, Opts) of + {value, {What, IfDef}} -> + w("#if ~s~n", [IfDef]), + true; + _ -> false + end. + declare_variables(void,Ps) -> [declare_var(P) || P <- Ps]; declare_variables(T, Ps) -> diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index 0d1fef6272..2ca254ef74 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -1282,15 +1282,22 @@ %'Clone','DrawBackground','DrawButton','DrawTab','GetBestTabCtrlSize', %'GetIndentSize','GetTabSize','SetFlags','SetMeasuringFont', %'SetNormalFont','SetSelectedFont','SetSizingInfo'%,'ShowWindowList' + 'SetFlags', 'SetMeasuringFont', 'SetNormalFont', 'SetSelectedFont', + {'SetColour', [{test_if, "wxCHECK_VERSION(3,0,0)"}]}, + {'SetActiveColour', [{test_if, "wxCHECK_VERSION(3,0,0)"}]} ]}. {class,wxAuiDockArt, root, [{ifdef, wxUSE_AUI}], [%% 'wxAuiDockArt','~wxAuiDockArt' %, %%'DrawBackground','DrawBorder','DrawCaption', %% Pure virtual funcs %%'DrawGripper','DrawPaneButton','DrawSash', - %%'GetColor','GetColour','GetFont','GetMetric','SetColor','SetColour','SetFont','SetMetric' + 'GetColour','GetFont','GetMetric','SetColour','SetFont','SetMetric' ]}. +{class,wxAuiSimpleTabArt, wxAuiTabArt, [{ifdef, wxUSE_AUI}], + [wxAuiSimpleTabArt]}. + + {class, wxMDIParentFrame, wxFrame, [], [ 'wxMDIParentFrame', @@ -1870,7 +1877,7 @@ ]}. -{class, wxAuiManagerEvent, wxEvent, +{class, wxAuiManagerEvent, wxEvent, [{acc, [{button, "GetButton()"}, {dc, "GetDC()"}, {pane, "GetPane()"}, @@ -1880,6 +1887,7 @@ wxEVT_AUI_PANE_CLOSE, wxEVT_AUI_PANE_MAXIMIZE, wxEVT_AUI_PANE_RESTORE, + {wxEVT_AUI_PANE_ACTIVATED, {test_if, "wxCHECK_VERSION(2,9,5)"}}, wxEVT_AUI_RENDER, wxEVT_AUI_FIND_MANAGER ]}], diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp index f6a5868b48..a532ee985d 100644 --- a/lib/wx/c_src/gen/wxe_events.cpp +++ b/lib/wx/c_src/gen/wxe_events.cpp @@ -54,255 +54,258 @@ void initEventTable() struct { int ev_type; int class_id; const char * ev_name;} event_types[] = { {wxEVT_NULL, 0, "null"}, - {wxEVT_COMMAND_BUTTON_CLICKED, 164, "command_button_clicked"}, - {wxEVT_COMMAND_CHECKBOX_CLICKED, 164, "command_checkbox_clicked"}, - {wxEVT_COMMAND_CHOICE_SELECTED, 164, "command_choice_selected"}, - {wxEVT_COMMAND_LISTBOX_SELECTED, 164, "command_listbox_selected"}, - {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 164, "command_listbox_doubleclicked"}, - {wxEVT_COMMAND_TEXT_UPDATED, 164, "command_text_updated"}, - {wxEVT_COMMAND_TEXT_ENTER, 164, "command_text_enter"}, - {wxEVT_COMMAND_MENU_SELECTED, 164, "command_menu_selected"}, - {wxEVT_COMMAND_SLIDER_UPDATED, 164, "command_slider_updated"}, - {wxEVT_COMMAND_RADIOBOX_SELECTED, 164, "command_radiobox_selected"}, - {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 164, "command_radiobutton_selected"}, - {wxEVT_COMMAND_SCROLLBAR_UPDATED, 164, "command_scrollbar_updated"}, - {wxEVT_COMMAND_VLBOX_SELECTED, 164, "command_vlbox_selected"}, - {wxEVT_COMMAND_COMBOBOX_SELECTED, 164, "command_combobox_selected"}, - {wxEVT_COMMAND_TOOL_RCLICKED, 164, "command_tool_rclicked"}, - {wxEVT_COMMAND_TOOL_ENTER, 164, "command_tool_enter"}, - {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 164, "command_checklistbox_toggled"}, - {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 164, "command_togglebutton_clicked"}, - {wxEVT_COMMAND_LEFT_CLICK, 164, "command_left_click"}, - {wxEVT_COMMAND_LEFT_DCLICK, 164, "command_left_dclick"}, - {wxEVT_COMMAND_RIGHT_CLICK, 164, "command_right_click"}, - {wxEVT_COMMAND_SET_FOCUS, 164, "command_set_focus"}, - {wxEVT_COMMAND_KILL_FOCUS, 164, "command_kill_focus"}, - {wxEVT_COMMAND_ENTER, 164, "command_enter"}, - {wxEVT_SCROLL_TOP, 165, "scroll_top"}, - {wxEVT_SCROLL_BOTTOM, 165, "scroll_bottom"}, - {wxEVT_SCROLL_LINEUP, 165, "scroll_lineup"}, - {wxEVT_SCROLL_LINEDOWN, 165, "scroll_linedown"}, - {wxEVT_SCROLL_PAGEUP, 165, "scroll_pageup"}, - {wxEVT_SCROLL_PAGEDOWN, 165, "scroll_pagedown"}, - {wxEVT_SCROLL_THUMBTRACK, 165, "scroll_thumbtrack"}, - {wxEVT_SCROLL_THUMBRELEASE, 165, "scroll_thumbrelease"}, - {wxEVT_SCROLL_CHANGED, 165, "scroll_changed"}, - {wxEVT_SCROLLWIN_TOP, 166, "scrollwin_top"}, - {wxEVT_SCROLLWIN_BOTTOM, 166, "scrollwin_bottom"}, - {wxEVT_SCROLLWIN_LINEUP, 166, "scrollwin_lineup"}, - {wxEVT_SCROLLWIN_LINEDOWN, 166, "scrollwin_linedown"}, - {wxEVT_SCROLLWIN_PAGEUP, 166, "scrollwin_pageup"}, - {wxEVT_SCROLLWIN_PAGEDOWN, 166, "scrollwin_pagedown"}, - {wxEVT_SCROLLWIN_THUMBTRACK, 166, "scrollwin_thumbtrack"}, - {wxEVT_SCROLLWIN_THUMBRELEASE, 166, "scrollwin_thumbrelease"}, - {wxEVT_LEFT_DOWN, 167, "left_down"}, - {wxEVT_LEFT_UP, 167, "left_up"}, - {wxEVT_MIDDLE_DOWN, 167, "middle_down"}, - {wxEVT_MIDDLE_UP, 167, "middle_up"}, - {wxEVT_RIGHT_DOWN, 167, "right_down"}, - {wxEVT_RIGHT_UP, 167, "right_up"}, - {wxEVT_MOTION, 167, "motion"}, - {wxEVT_ENTER_WINDOW, 167, "enter_window"}, - {wxEVT_LEAVE_WINDOW, 167, "leave_window"}, - {wxEVT_LEFT_DCLICK, 167, "left_dclick"}, - {wxEVT_MIDDLE_DCLICK, 167, "middle_dclick"}, - {wxEVT_RIGHT_DCLICK, 167, "right_dclick"}, - {wxEVT_MOUSEWHEEL, 167, "mousewheel"}, - {wxEVT_SET_CURSOR, 168, "set_cursor"}, - {wxEVT_CHAR, 169, "char"}, - {wxEVT_CHAR_HOOK, 169, "char_hook"}, - {wxEVT_KEY_DOWN, 169, "key_down"}, - {wxEVT_KEY_UP, 169, "key_up"}, - {wxEVT_SIZE, 170, "size"}, - {wxEVT_MOVE, 171, "move"}, - {wxEVT_PAINT, 172, "paint"}, - {wxEVT_ERASE_BACKGROUND, 173, "erase_background"}, - {wxEVT_SET_FOCUS, 174, "set_focus"}, - {wxEVT_KILL_FOCUS, 174, "kill_focus"}, - {wxEVT_CHILD_FOCUS, 175, "child_focus"}, - {wxEVT_MENU_OPEN, 176, "menu_open"}, - {wxEVT_MENU_CLOSE, 176, "menu_close"}, - {wxEVT_MENU_HIGHLIGHT, 176, "menu_highlight"}, - {wxEVT_CLOSE_WINDOW, 177, "close_window"}, - {wxEVT_END_SESSION, 177, "end_session"}, - {wxEVT_QUERY_END_SESSION, 177, "query_end_session"}, - {wxEVT_SHOW, 178, "show"}, - {wxEVT_ICONIZE, 179, "iconize"}, - {wxEVT_MAXIMIZE, 180, "maximize"}, - {wxEVT_JOY_BUTTON_DOWN, 181, "joy_button_down"}, - {wxEVT_JOY_BUTTON_UP, 181, "joy_button_up"}, - {wxEVT_JOY_MOVE, 181, "joy_move"}, - {wxEVT_JOY_ZMOVE, 181, "joy_zmove"}, - {wxEVT_UPDATE_UI, 182, "update_ui"}, - {wxEVT_SYS_COLOUR_CHANGED, 183, "sys_colour_changed"}, - {wxEVT_MOUSE_CAPTURE_CHANGED, 184, "mouse_capture_changed"}, - {wxEVT_DISPLAY_CHANGED, 185, "display_changed"}, - {wxEVT_PALETTE_CHANGED, 186, "palette_changed"}, - {wxEVT_QUERY_NEW_PALETTE, 187, "query_new_palette"}, - {wxEVT_NAVIGATION_KEY, 188, "navigation_key"}, - {wxEVT_CREATE, 189, "create"}, - {wxEVT_DESTROY, 190, "destroy"}, - {wxEVT_HELP, 191, "help"}, - {wxEVT_DETAILED_HELP, 191, "detailed_help"}, - {wxEVT_CONTEXT_MENU, 192, "context_menu"}, - {wxEVT_IDLE, 193, "idle"}, - {wxEVT_GRID_CELL_LEFT_CLICK, 194, "grid_cell_left_click"}, - {wxEVT_GRID_CELL_RIGHT_CLICK, 194, "grid_cell_right_click"}, - {wxEVT_GRID_CELL_LEFT_DCLICK, 194, "grid_cell_left_dclick"}, - {wxEVT_GRID_CELL_RIGHT_DCLICK, 194, "grid_cell_right_dclick"}, - {wxEVT_GRID_LABEL_LEFT_CLICK, 194, "grid_label_left_click"}, - {wxEVT_GRID_LABEL_RIGHT_CLICK, 194, "grid_label_right_click"}, - {wxEVT_GRID_LABEL_LEFT_DCLICK, 194, "grid_label_left_dclick"}, - {wxEVT_GRID_LABEL_RIGHT_DCLICK, 194, "grid_label_right_dclick"}, - {wxEVT_GRID_ROW_SIZE, 194, "grid_row_size"}, - {wxEVT_GRID_COL_SIZE, 194, "grid_col_size"}, - {wxEVT_GRID_RANGE_SELECT, 194, "grid_range_select"}, - {wxEVT_GRID_CELL_CHANGE, 194, "grid_cell_change"}, - {wxEVT_GRID_SELECT_CELL, 194, "grid_select_cell"}, - {wxEVT_GRID_EDITOR_SHOWN, 194, "grid_editor_shown"}, - {wxEVT_GRID_EDITOR_HIDDEN, 194, "grid_editor_hidden"}, - {wxEVT_GRID_EDITOR_CREATED, 194, "grid_editor_created"}, - {wxEVT_GRID_CELL_BEGIN_DRAG, 194, "grid_cell_begin_drag"}, - {wxEVT_SASH_DRAGGED, 196, "sash_dragged"}, - {wxEVT_COMMAND_LIST_BEGIN_DRAG, 197, "command_list_begin_drag"}, - {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 197, "command_list_begin_rdrag"}, - {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 197, "command_list_begin_label_edit"}, - {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 197, "command_list_end_label_edit"}, - {wxEVT_COMMAND_LIST_DELETE_ITEM, 197, "command_list_delete_item"}, - {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 197, "command_list_delete_all_items"}, - {wxEVT_COMMAND_LIST_KEY_DOWN, 197, "command_list_key_down"}, - {wxEVT_COMMAND_LIST_INSERT_ITEM, 197, "command_list_insert_item"}, - {wxEVT_COMMAND_LIST_COL_CLICK, 197, "command_list_col_click"}, - {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 197, "command_list_col_right_click"}, - {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 197, "command_list_col_begin_drag"}, - {wxEVT_COMMAND_LIST_COL_DRAGGING, 197, "command_list_col_dragging"}, - {wxEVT_COMMAND_LIST_COL_END_DRAG, 197, "command_list_col_end_drag"}, - {wxEVT_COMMAND_LIST_ITEM_SELECTED, 197, "command_list_item_selected"}, - {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 197, "command_list_item_deselected"}, - {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 197, "command_list_item_right_click"}, - {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 197, "command_list_item_middle_click"}, - {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 197, "command_list_item_activated"}, - {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 197, "command_list_item_focused"}, - {wxEVT_COMMAND_LIST_CACHE_HINT, 197, "command_list_cache_hint"}, - {wxEVT_DATE_CHANGED, 198, "date_changed"}, - {wxEVT_CALENDAR_SEL_CHANGED, 199, "calendar_sel_changed"}, - {wxEVT_CALENDAR_DAY_CHANGED, 199, "calendar_day_changed"}, - {wxEVT_CALENDAR_MONTH_CHANGED, 199, "calendar_month_changed"}, - {wxEVT_CALENDAR_YEAR_CHANGED, 199, "calendar_year_changed"}, - {wxEVT_CALENDAR_DOUBLECLICKED, 199, "calendar_doubleclicked"}, - {wxEVT_CALENDAR_WEEKDAY_CLICKED, 199, "calendar_weekday_clicked"}, - {wxEVT_COMMAND_FILEPICKER_CHANGED, 200, "command_filepicker_changed"}, - {wxEVT_COMMAND_DIRPICKER_CHANGED, 200, "command_dirpicker_changed"}, - {wxEVT_COMMAND_COLOURPICKER_CHANGED, 201, "command_colourpicker_changed"}, - {wxEVT_COMMAND_FONTPICKER_CHANGED, 202, "command_fontpicker_changed"}, - {wxEVT_STC_CHANGE, 203, "stc_change"}, - {wxEVT_STC_STYLENEEDED, 203, "stc_styleneeded"}, - {wxEVT_STC_CHARADDED, 203, "stc_charadded"}, - {wxEVT_STC_SAVEPOINTREACHED, 203, "stc_savepointreached"}, - {wxEVT_STC_SAVEPOINTLEFT, 203, "stc_savepointleft"}, - {wxEVT_STC_ROMODIFYATTEMPT, 203, "stc_romodifyattempt"}, - {wxEVT_STC_KEY, 203, "stc_key"}, - {wxEVT_STC_DOUBLECLICK, 203, "stc_doubleclick"}, - {wxEVT_STC_UPDATEUI, 203, "stc_updateui"}, - {wxEVT_STC_MODIFIED, 203, "stc_modified"}, - {wxEVT_STC_MACRORECORD, 203, "stc_macrorecord"}, - {wxEVT_STC_MARGINCLICK, 203, "stc_marginclick"}, - {wxEVT_STC_NEEDSHOWN, 203, "stc_needshown"}, - {wxEVT_STC_PAINTED, 203, "stc_painted"}, - {wxEVT_STC_USERLISTSELECTION, 203, "stc_userlistselection"}, - {wxEVT_STC_URIDROPPED, 203, "stc_uridropped"}, - {wxEVT_STC_DWELLSTART, 203, "stc_dwellstart"}, - {wxEVT_STC_DWELLEND, 203, "stc_dwellend"}, - {wxEVT_STC_START_DRAG, 203, "stc_start_drag"}, - {wxEVT_STC_DRAG_OVER, 203, "stc_drag_over"}, - {wxEVT_STC_DO_DROP, 203, "stc_do_drop"}, - {wxEVT_STC_ZOOM, 203, "stc_zoom"}, - {wxEVT_STC_HOTSPOT_CLICK, 203, "stc_hotspot_click"}, - {wxEVT_STC_HOTSPOT_DCLICK, 203, "stc_hotspot_dclick"}, - {wxEVT_STC_CALLTIP_CLICK, 203, "stc_calltip_click"}, - {wxEVT_STC_AUTOCOMP_SELECTION, 203, "stc_autocomp_selection"}, - {wxEVT_COMMAND_TREE_BEGIN_DRAG, 209, "command_tree_begin_drag"}, - {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 209, "command_tree_begin_rdrag"}, - {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 209, "command_tree_begin_label_edit"}, - {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 209, "command_tree_end_label_edit"}, - {wxEVT_COMMAND_TREE_DELETE_ITEM, 209, "command_tree_delete_item"}, - {wxEVT_COMMAND_TREE_GET_INFO, 209, "command_tree_get_info"}, - {wxEVT_COMMAND_TREE_SET_INFO, 209, "command_tree_set_info"}, - {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 209, "command_tree_item_expanded"}, - {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 209, "command_tree_item_expanding"}, - {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 209, "command_tree_item_collapsed"}, - {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 209, "command_tree_item_collapsing"}, - {wxEVT_COMMAND_TREE_SEL_CHANGED, 209, "command_tree_sel_changed"}, - {wxEVT_COMMAND_TREE_SEL_CHANGING, 209, "command_tree_sel_changing"}, - {wxEVT_COMMAND_TREE_KEY_DOWN, 209, "command_tree_key_down"}, - {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 209, "command_tree_item_activated"}, - {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 209, "command_tree_item_right_click"}, - {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 209, "command_tree_item_middle_click"}, - {wxEVT_COMMAND_TREE_END_DRAG, 209, "command_tree_end_drag"}, - {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 209, "command_tree_state_image_click"}, - {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 209, "command_tree_item_gettooltip"}, - {wxEVT_COMMAND_TREE_ITEM_MENU, 209, "command_tree_item_menu"}, - {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 210, "command_notebook_page_changed"}, - {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 210, "command_notebook_page_changing"}, - {wxEVT_COMMAND_TEXT_COPY, 216, "command_text_copy"}, - {wxEVT_COMMAND_TEXT_CUT, 216, "command_text_cut"}, - {wxEVT_COMMAND_TEXT_PASTE, 216, "command_text_paste"}, - {wxEVT_COMMAND_SPINCTRL_UPDATED, 217, "command_spinctrl_updated"}, - {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 165, "spin_up"}, - {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 165, "spin_down"}, - {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 165, "spin"}, - {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 219, "command_splitter_sash_pos_changed"}, - {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 219, "command_splitter_sash_pos_changing"}, - {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 219, "command_splitter_doubleclicked"}, - {wxEVT_COMMAND_SPLITTER_UNSPLIT, 219, "command_splitter_unsplit"}, - {wxEVT_COMMAND_HTML_LINK_CLICKED, 221, "command_html_link_clicked"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 224, "command_auinotebook_page_close"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 224, "command_auinotebook_page_changed"}, - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 224, "command_auinotebook_page_changing"}, - {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 224, "command_auinotebook_button"}, - {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 224, "command_auinotebook_begin_drag"}, - {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 224, "command_auinotebook_end_drag"}, - {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 224, "command_auinotebook_drag_motion"}, - {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 224, "command_auinotebook_allow_dnd"}, + {wxEVT_COMMAND_BUTTON_CLICKED, 165, "command_button_clicked"}, + {wxEVT_COMMAND_CHECKBOX_CLICKED, 165, "command_checkbox_clicked"}, + {wxEVT_COMMAND_CHOICE_SELECTED, 165, "command_choice_selected"}, + {wxEVT_COMMAND_LISTBOX_SELECTED, 165, "command_listbox_selected"}, + {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 165, "command_listbox_doubleclicked"}, + {wxEVT_COMMAND_TEXT_UPDATED, 165, "command_text_updated"}, + {wxEVT_COMMAND_TEXT_ENTER, 165, "command_text_enter"}, + {wxEVT_COMMAND_MENU_SELECTED, 165, "command_menu_selected"}, + {wxEVT_COMMAND_SLIDER_UPDATED, 165, "command_slider_updated"}, + {wxEVT_COMMAND_RADIOBOX_SELECTED, 165, "command_radiobox_selected"}, + {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 165, "command_radiobutton_selected"}, + {wxEVT_COMMAND_SCROLLBAR_UPDATED, 165, "command_scrollbar_updated"}, + {wxEVT_COMMAND_VLBOX_SELECTED, 165, "command_vlbox_selected"}, + {wxEVT_COMMAND_COMBOBOX_SELECTED, 165, "command_combobox_selected"}, + {wxEVT_COMMAND_TOOL_RCLICKED, 165, "command_tool_rclicked"}, + {wxEVT_COMMAND_TOOL_ENTER, 165, "command_tool_enter"}, + {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 165, "command_checklistbox_toggled"}, + {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 165, "command_togglebutton_clicked"}, + {wxEVT_COMMAND_LEFT_CLICK, 165, "command_left_click"}, + {wxEVT_COMMAND_LEFT_DCLICK, 165, "command_left_dclick"}, + {wxEVT_COMMAND_RIGHT_CLICK, 165, "command_right_click"}, + {wxEVT_COMMAND_SET_FOCUS, 165, "command_set_focus"}, + {wxEVT_COMMAND_KILL_FOCUS, 165, "command_kill_focus"}, + {wxEVT_COMMAND_ENTER, 165, "command_enter"}, + {wxEVT_SCROLL_TOP, 166, "scroll_top"}, + {wxEVT_SCROLL_BOTTOM, 166, "scroll_bottom"}, + {wxEVT_SCROLL_LINEUP, 166, "scroll_lineup"}, + {wxEVT_SCROLL_LINEDOWN, 166, "scroll_linedown"}, + {wxEVT_SCROLL_PAGEUP, 166, "scroll_pageup"}, + {wxEVT_SCROLL_PAGEDOWN, 166, "scroll_pagedown"}, + {wxEVT_SCROLL_THUMBTRACK, 166, "scroll_thumbtrack"}, + {wxEVT_SCROLL_THUMBRELEASE, 166, "scroll_thumbrelease"}, + {wxEVT_SCROLL_CHANGED, 166, "scroll_changed"}, + {wxEVT_SCROLLWIN_TOP, 167, "scrollwin_top"}, + {wxEVT_SCROLLWIN_BOTTOM, 167, "scrollwin_bottom"}, + {wxEVT_SCROLLWIN_LINEUP, 167, "scrollwin_lineup"}, + {wxEVT_SCROLLWIN_LINEDOWN, 167, "scrollwin_linedown"}, + {wxEVT_SCROLLWIN_PAGEUP, 167, "scrollwin_pageup"}, + {wxEVT_SCROLLWIN_PAGEDOWN, 167, "scrollwin_pagedown"}, + {wxEVT_SCROLLWIN_THUMBTRACK, 167, "scrollwin_thumbtrack"}, + {wxEVT_SCROLLWIN_THUMBRELEASE, 167, "scrollwin_thumbrelease"}, + {wxEVT_LEFT_DOWN, 168, "left_down"}, + {wxEVT_LEFT_UP, 168, "left_up"}, + {wxEVT_MIDDLE_DOWN, 168, "middle_down"}, + {wxEVT_MIDDLE_UP, 168, "middle_up"}, + {wxEVT_RIGHT_DOWN, 168, "right_down"}, + {wxEVT_RIGHT_UP, 168, "right_up"}, + {wxEVT_MOTION, 168, "motion"}, + {wxEVT_ENTER_WINDOW, 168, "enter_window"}, + {wxEVT_LEAVE_WINDOW, 168, "leave_window"}, + {wxEVT_LEFT_DCLICK, 168, "left_dclick"}, + {wxEVT_MIDDLE_DCLICK, 168, "middle_dclick"}, + {wxEVT_RIGHT_DCLICK, 168, "right_dclick"}, + {wxEVT_MOUSEWHEEL, 168, "mousewheel"}, + {wxEVT_SET_CURSOR, 169, "set_cursor"}, + {wxEVT_CHAR, 170, "char"}, + {wxEVT_CHAR_HOOK, 170, "char_hook"}, + {wxEVT_KEY_DOWN, 170, "key_down"}, + {wxEVT_KEY_UP, 170, "key_up"}, + {wxEVT_SIZE, 171, "size"}, + {wxEVT_MOVE, 172, "move"}, + {wxEVT_PAINT, 173, "paint"}, + {wxEVT_ERASE_BACKGROUND, 174, "erase_background"}, + {wxEVT_SET_FOCUS, 175, "set_focus"}, + {wxEVT_KILL_FOCUS, 175, "kill_focus"}, + {wxEVT_CHILD_FOCUS, 176, "child_focus"}, + {wxEVT_MENU_OPEN, 177, "menu_open"}, + {wxEVT_MENU_CLOSE, 177, "menu_close"}, + {wxEVT_MENU_HIGHLIGHT, 177, "menu_highlight"}, + {wxEVT_CLOSE_WINDOW, 178, "close_window"}, + {wxEVT_END_SESSION, 178, "end_session"}, + {wxEVT_QUERY_END_SESSION, 178, "query_end_session"}, + {wxEVT_SHOW, 179, "show"}, + {wxEVT_ICONIZE, 180, "iconize"}, + {wxEVT_MAXIMIZE, 181, "maximize"}, + {wxEVT_JOY_BUTTON_DOWN, 182, "joy_button_down"}, + {wxEVT_JOY_BUTTON_UP, 182, "joy_button_up"}, + {wxEVT_JOY_MOVE, 182, "joy_move"}, + {wxEVT_JOY_ZMOVE, 182, "joy_zmove"}, + {wxEVT_UPDATE_UI, 183, "update_ui"}, + {wxEVT_SYS_COLOUR_CHANGED, 184, "sys_colour_changed"}, + {wxEVT_MOUSE_CAPTURE_CHANGED, 185, "mouse_capture_changed"}, + {wxEVT_DISPLAY_CHANGED, 186, "display_changed"}, + {wxEVT_PALETTE_CHANGED, 187, "palette_changed"}, + {wxEVT_QUERY_NEW_PALETTE, 188, "query_new_palette"}, + {wxEVT_NAVIGATION_KEY, 189, "navigation_key"}, + {wxEVT_CREATE, 190, "create"}, + {wxEVT_DESTROY, 191, "destroy"}, + {wxEVT_HELP, 192, "help"}, + {wxEVT_DETAILED_HELP, 192, "detailed_help"}, + {wxEVT_CONTEXT_MENU, 193, "context_menu"}, + {wxEVT_IDLE, 194, "idle"}, + {wxEVT_GRID_CELL_LEFT_CLICK, 195, "grid_cell_left_click"}, + {wxEVT_GRID_CELL_RIGHT_CLICK, 195, "grid_cell_right_click"}, + {wxEVT_GRID_CELL_LEFT_DCLICK, 195, "grid_cell_left_dclick"}, + {wxEVT_GRID_CELL_RIGHT_DCLICK, 195, "grid_cell_right_dclick"}, + {wxEVT_GRID_LABEL_LEFT_CLICK, 195, "grid_label_left_click"}, + {wxEVT_GRID_LABEL_RIGHT_CLICK, 195, "grid_label_right_click"}, + {wxEVT_GRID_LABEL_LEFT_DCLICK, 195, "grid_label_left_dclick"}, + {wxEVT_GRID_LABEL_RIGHT_DCLICK, 195, "grid_label_right_dclick"}, + {wxEVT_GRID_ROW_SIZE, 195, "grid_row_size"}, + {wxEVT_GRID_COL_SIZE, 195, "grid_col_size"}, + {wxEVT_GRID_RANGE_SELECT, 195, "grid_range_select"}, + {wxEVT_GRID_CELL_CHANGE, 195, "grid_cell_change"}, + {wxEVT_GRID_SELECT_CELL, 195, "grid_select_cell"}, + {wxEVT_GRID_EDITOR_SHOWN, 195, "grid_editor_shown"}, + {wxEVT_GRID_EDITOR_HIDDEN, 195, "grid_editor_hidden"}, + {wxEVT_GRID_EDITOR_CREATED, 195, "grid_editor_created"}, + {wxEVT_GRID_CELL_BEGIN_DRAG, 195, "grid_cell_begin_drag"}, + {wxEVT_SASH_DRAGGED, 197, "sash_dragged"}, + {wxEVT_COMMAND_LIST_BEGIN_DRAG, 198, "command_list_begin_drag"}, + {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 198, "command_list_begin_rdrag"}, + {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 198, "command_list_begin_label_edit"}, + {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 198, "command_list_end_label_edit"}, + {wxEVT_COMMAND_LIST_DELETE_ITEM, 198, "command_list_delete_item"}, + {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 198, "command_list_delete_all_items"}, + {wxEVT_COMMAND_LIST_KEY_DOWN, 198, "command_list_key_down"}, + {wxEVT_COMMAND_LIST_INSERT_ITEM, 198, "command_list_insert_item"}, + {wxEVT_COMMAND_LIST_COL_CLICK, 198, "command_list_col_click"}, + {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 198, "command_list_col_right_click"}, + {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 198, "command_list_col_begin_drag"}, + {wxEVT_COMMAND_LIST_COL_DRAGGING, 198, "command_list_col_dragging"}, + {wxEVT_COMMAND_LIST_COL_END_DRAG, 198, "command_list_col_end_drag"}, + {wxEVT_COMMAND_LIST_ITEM_SELECTED, 198, "command_list_item_selected"}, + {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 198, "command_list_item_deselected"}, + {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 198, "command_list_item_right_click"}, + {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 198, "command_list_item_middle_click"}, + {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 198, "command_list_item_activated"}, + {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 198, "command_list_item_focused"}, + {wxEVT_COMMAND_LIST_CACHE_HINT, 198, "command_list_cache_hint"}, + {wxEVT_DATE_CHANGED, 199, "date_changed"}, + {wxEVT_CALENDAR_SEL_CHANGED, 200, "calendar_sel_changed"}, + {wxEVT_CALENDAR_DAY_CHANGED, 200, "calendar_day_changed"}, + {wxEVT_CALENDAR_MONTH_CHANGED, 200, "calendar_month_changed"}, + {wxEVT_CALENDAR_YEAR_CHANGED, 200, "calendar_year_changed"}, + {wxEVT_CALENDAR_DOUBLECLICKED, 200, "calendar_doubleclicked"}, + {wxEVT_CALENDAR_WEEKDAY_CLICKED, 200, "calendar_weekday_clicked"}, + {wxEVT_COMMAND_FILEPICKER_CHANGED, 201, "command_filepicker_changed"}, + {wxEVT_COMMAND_DIRPICKER_CHANGED, 201, "command_dirpicker_changed"}, + {wxEVT_COMMAND_COLOURPICKER_CHANGED, 202, "command_colourpicker_changed"}, + {wxEVT_COMMAND_FONTPICKER_CHANGED, 203, "command_fontpicker_changed"}, + {wxEVT_STC_CHANGE, 204, "stc_change"}, + {wxEVT_STC_STYLENEEDED, 204, "stc_styleneeded"}, + {wxEVT_STC_CHARADDED, 204, "stc_charadded"}, + {wxEVT_STC_SAVEPOINTREACHED, 204, "stc_savepointreached"}, + {wxEVT_STC_SAVEPOINTLEFT, 204, "stc_savepointleft"}, + {wxEVT_STC_ROMODIFYATTEMPT, 204, "stc_romodifyattempt"}, + {wxEVT_STC_KEY, 204, "stc_key"}, + {wxEVT_STC_DOUBLECLICK, 204, "stc_doubleclick"}, + {wxEVT_STC_UPDATEUI, 204, "stc_updateui"}, + {wxEVT_STC_MODIFIED, 204, "stc_modified"}, + {wxEVT_STC_MACRORECORD, 204, "stc_macrorecord"}, + {wxEVT_STC_MARGINCLICK, 204, "stc_marginclick"}, + {wxEVT_STC_NEEDSHOWN, 204, "stc_needshown"}, + {wxEVT_STC_PAINTED, 204, "stc_painted"}, + {wxEVT_STC_USERLISTSELECTION, 204, "stc_userlistselection"}, + {wxEVT_STC_URIDROPPED, 204, "stc_uridropped"}, + {wxEVT_STC_DWELLSTART, 204, "stc_dwellstart"}, + {wxEVT_STC_DWELLEND, 204, "stc_dwellend"}, + {wxEVT_STC_START_DRAG, 204, "stc_start_drag"}, + {wxEVT_STC_DRAG_OVER, 204, "stc_drag_over"}, + {wxEVT_STC_DO_DROP, 204, "stc_do_drop"}, + {wxEVT_STC_ZOOM, 204, "stc_zoom"}, + {wxEVT_STC_HOTSPOT_CLICK, 204, "stc_hotspot_click"}, + {wxEVT_STC_HOTSPOT_DCLICK, 204, "stc_hotspot_dclick"}, + {wxEVT_STC_CALLTIP_CLICK, 204, "stc_calltip_click"}, + {wxEVT_STC_AUTOCOMP_SELECTION, 204, "stc_autocomp_selection"}, + {wxEVT_COMMAND_TREE_BEGIN_DRAG, 210, "command_tree_begin_drag"}, + {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 210, "command_tree_begin_rdrag"}, + {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 210, "command_tree_begin_label_edit"}, + {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 210, "command_tree_end_label_edit"}, + {wxEVT_COMMAND_TREE_DELETE_ITEM, 210, "command_tree_delete_item"}, + {wxEVT_COMMAND_TREE_GET_INFO, 210, "command_tree_get_info"}, + {wxEVT_COMMAND_TREE_SET_INFO, 210, "command_tree_set_info"}, + {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 210, "command_tree_item_expanded"}, + {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 210, "command_tree_item_expanding"}, + {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 210, "command_tree_item_collapsed"}, + {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 210, "command_tree_item_collapsing"}, + {wxEVT_COMMAND_TREE_SEL_CHANGED, 210, "command_tree_sel_changed"}, + {wxEVT_COMMAND_TREE_SEL_CHANGING, 210, "command_tree_sel_changing"}, + {wxEVT_COMMAND_TREE_KEY_DOWN, 210, "command_tree_key_down"}, + {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 210, "command_tree_item_activated"}, + {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 210, "command_tree_item_right_click"}, + {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 210, "command_tree_item_middle_click"}, + {wxEVT_COMMAND_TREE_END_DRAG, 210, "command_tree_end_drag"}, + {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 210, "command_tree_state_image_click"}, + {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 210, "command_tree_item_gettooltip"}, + {wxEVT_COMMAND_TREE_ITEM_MENU, 210, "command_tree_item_menu"}, + {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 211, "command_notebook_page_changed"}, + {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 211, "command_notebook_page_changing"}, + {wxEVT_COMMAND_TEXT_COPY, 217, "command_text_copy"}, + {wxEVT_COMMAND_TEXT_CUT, 217, "command_text_cut"}, + {wxEVT_COMMAND_TEXT_PASTE, 217, "command_text_paste"}, + {wxEVT_COMMAND_SPINCTRL_UPDATED, 218, "command_spinctrl_updated"}, + {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 166, "spin_up"}, + {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 166, "spin_down"}, + {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 166, "spin"}, + {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 220, "command_splitter_sash_pos_changed"}, + {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 220, "command_splitter_sash_pos_changing"}, + {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 220, "command_splitter_doubleclicked"}, + {wxEVT_COMMAND_SPLITTER_UNSPLIT, 220, "command_splitter_unsplit"}, + {wxEVT_COMMAND_HTML_LINK_CLICKED, 222, "command_html_link_clicked"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 225, "command_auinotebook_page_close"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 225, "command_auinotebook_page_changed"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 225, "command_auinotebook_page_changing"}, + {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 225, "command_auinotebook_button"}, + {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 225, "command_auinotebook_begin_drag"}, + {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 225, "command_auinotebook_end_drag"}, + {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 225, "command_auinotebook_drag_motion"}, + {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 225, "command_auinotebook_allow_dnd"}, #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 224, "command_auinotebook_tab_middle_down"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 225, "command_auinotebook_tab_middle_down"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 224, "command_auinotebook_tab_middle_up"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 225, "command_auinotebook_tab_middle_up"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 224, "command_auinotebook_tab_right_down"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 225, "command_auinotebook_tab_right_down"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 224, "command_auinotebook_tab_right_up"}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 225, "command_auinotebook_tab_right_up"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 224, "command_auinotebook_page_closed"}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 225, "command_auinotebook_page_closed"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 224, "command_auinotebook_drag_done"}, + {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 225, "command_auinotebook_drag_done"}, #endif #if wxCHECK_VERSION(2,8,5) - {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 224, "command_auinotebook_bg_dclick"}, + {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 225, "command_auinotebook_bg_dclick"}, #endif - {wxEVT_AUI_PANE_BUTTON, 225, "aui_pane_button"}, - {wxEVT_AUI_PANE_CLOSE, 225, "aui_pane_close"}, - {wxEVT_AUI_PANE_MAXIMIZE, 225, "aui_pane_maximize"}, - {wxEVT_AUI_PANE_RESTORE, 225, "aui_pane_restore"}, - {wxEVT_AUI_RENDER, 225, "aui_render"}, - {wxEVT_AUI_FIND_MANAGER, 225, "aui_find_manager"}, - {wxEVT_TASKBAR_MOVE, 228, "taskbar_move"}, - {wxEVT_TASKBAR_LEFT_DOWN, 228, "taskbar_left_down"}, - {wxEVT_TASKBAR_LEFT_UP, 228, "taskbar_left_up"}, - {wxEVT_TASKBAR_RIGHT_DOWN, 228, "taskbar_right_down"}, - {wxEVT_TASKBAR_RIGHT_UP, 228, "taskbar_right_up"}, - {wxEVT_TASKBAR_LEFT_DCLICK, 228, "taskbar_left_dclick"}, - {wxEVT_TASKBAR_RIGHT_DCLICK, 228, "taskbar_right_dclick"}, - {wxEVT_INIT_DIALOG, 229, "init_dialog"}, - {wxEVT_ACTIVATE, 231, "activate"}, - {wxEVT_ACTIVATE_APP, 231, "activate_app"}, - {wxEVT_HIBERNATE, 231, "hibernate"}, - {wxEVT_MOUSE_CAPTURE_LOST, 234, "mouse_capture_lost"}, + {wxEVT_AUI_PANE_BUTTON, 226, "aui_pane_button"}, + {wxEVT_AUI_PANE_CLOSE, 226, "aui_pane_close"}, + {wxEVT_AUI_PANE_MAXIMIZE, 226, "aui_pane_maximize"}, + {wxEVT_AUI_PANE_RESTORE, 226, "aui_pane_restore"}, +#if wxCHECK_VERSION(2,9,5) + {wxEVT_AUI_PANE_ACTIVATED, 226, "aui_pane_activated"}, +#endif + {wxEVT_AUI_RENDER, 226, "aui_render"}, + {wxEVT_AUI_FIND_MANAGER, 226, "aui_find_manager"}, + {wxEVT_TASKBAR_MOVE, 229, "taskbar_move"}, + {wxEVT_TASKBAR_LEFT_DOWN, 229, "taskbar_left_down"}, + {wxEVT_TASKBAR_LEFT_UP, 229, "taskbar_left_up"}, + {wxEVT_TASKBAR_RIGHT_DOWN, 229, "taskbar_right_down"}, + {wxEVT_TASKBAR_RIGHT_UP, 229, "taskbar_right_up"}, + {wxEVT_TASKBAR_LEFT_DCLICK, 229, "taskbar_left_dclick"}, + {wxEVT_TASKBAR_RIGHT_DCLICK, 229, "taskbar_right_dclick"}, + {wxEVT_INIT_DIALOG, 230, "init_dialog"}, + {wxEVT_ACTIVATE, 232, "activate"}, + {wxEVT_ACTIVATE_APP, 232, "activate_app"}, + {wxEVT_HIBERNATE, 232, "hibernate"}, + {wxEVT_MOUSE_CAPTURE_LOST, 235, "mouse_capture_lost"}, {-1, 0, } }; for(int i=0; event_types[i].ev_type != -1; i++) { @@ -345,7 +348,7 @@ bool sendevent(wxEvent *event, ErlDrvTermData port) rt.addRef(cb->obj, cb->class_name); rt.addExt2Term(cb->user_data); switch(Etype->cID) { -case 164: {// wxCommandEvent +case 165: {// wxCommandEvent wxCommandEvent * ev = (wxCommandEvent *) event; evClass = (char*)"wxCommandEvent"; rt.addAtom((char*)"wxCommand"); @@ -356,7 +359,7 @@ case 164: {// wxCommandEvent rt.addTupleCount(5); break; } -case 165: {// wxScrollEvent or wxSpinEvent +case 166: {// wxScrollEvent or wxSpinEvent if(event->IsKindOf(CLASSINFO(wxScrollEvent))) { wxScrollEvent * ev = (wxScrollEvent *) event; evClass = (char*)"wxScrollEvent"; @@ -376,7 +379,7 @@ case 165: {// wxScrollEvent or wxSpinEvent } break; } -case 166: {// wxScrollWinEvent +case 167: {// wxScrollWinEvent wxScrollWinEvent * ev = (wxScrollWinEvent *) event; evClass = (char*)"wxScrollWinEvent"; rt.addAtom((char*)"wxScrollWin"); @@ -386,7 +389,7 @@ case 166: {// wxScrollWinEvent rt.addTupleCount(4); break; } -case 167: {// wxMouseEvent +case 168: {// wxMouseEvent wxMouseEvent * ev = (wxMouseEvent *) event; evClass = (char*)"wxMouseEvent"; rt.addAtom((char*)"wxMouse"); @@ -410,7 +413,7 @@ case 167: {// wxMouseEvent rt.addTupleCount(14); break; } -case 168: {// wxSetCursorEvent +case 169: {// wxSetCursorEvent wxSetCursorEvent * ev = (wxSetCursorEvent *) event; wxCursor * GetCursor = new wxCursor(ev->GetCursor()); app->newPtr((void *) GetCursor,3, memenv); @@ -423,7 +426,7 @@ case 168: {// wxSetCursorEvent rt.addTupleCount(5); break; } -case 169: {// wxKeyEvent +case 170: {// wxKeyEvent wxKeyEvent * ev = (wxKeyEvent *) event; evClass = (char*)"wxKeyEvent"; rt.addAtom((char*)"wxKey"); @@ -450,7 +453,7 @@ case 169: {// wxKeyEvent rt.addTupleCount(13); break; } -case 170: {// wxSizeEvent +case 171: {// wxSizeEvent wxSizeEvent * ev = (wxSizeEvent *) event; evClass = (char*)"wxSizeEvent"; rt.addAtom((char*)"wxSize"); @@ -460,7 +463,7 @@ case 170: {// wxSizeEvent rt.addTupleCount(4); break; } -case 171: {// wxMoveEvent +case 172: {// wxMoveEvent wxMoveEvent * ev = (wxMoveEvent *) event; evClass = (char*)"wxMoveEvent"; rt.addAtom((char*)"wxMove"); @@ -470,14 +473,14 @@ case 171: {// wxMoveEvent rt.addTupleCount(4); break; } -case 172: {// wxPaintEvent +case 173: {// wxPaintEvent evClass = (char*)"wxPaintEvent"; rt.addAtom((char*)"wxPaint"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 173: {// wxEraseEvent +case 174: {// wxEraseEvent wxEraseEvent * ev = (wxEraseEvent *) event; wxDC * GetDC = ev->GetDC(); evClass = (char*)"wxEraseEvent"; @@ -487,7 +490,7 @@ case 173: {// wxEraseEvent rt.addTupleCount(3); break; } -case 174: {// wxFocusEvent +case 175: {// wxFocusEvent wxFocusEvent * ev = (wxFocusEvent *) event; wxWindow * GetWindow = ev->GetWindow(); evClass = (char*)"wxFocusEvent"; @@ -497,14 +500,14 @@ case 174: {// wxFocusEvent rt.addTupleCount(3); break; } -case 175: {// wxChildFocusEvent +case 176: {// wxChildFocusEvent evClass = (char*)"wxChildFocusEvent"; rt.addAtom((char*)"wxChildFocus"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 176: {// wxMenuEvent +case 177: {// wxMenuEvent wxMenuEvent * ev = (wxMenuEvent *) event; wxMenu * GetMenu = ev->GetMenu(); evClass = (char*)"wxMenuEvent"; @@ -515,14 +518,14 @@ case 176: {// wxMenuEvent rt.addTupleCount(4); break; } -case 177: {// wxCloseEvent +case 178: {// wxCloseEvent evClass = (char*)"wxCloseEvent"; rt.addAtom((char*)"wxClose"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 178: {// wxShowEvent +case 179: {// wxShowEvent wxShowEvent * ev = (wxShowEvent *) event; evClass = (char*)"wxShowEvent"; rt.addAtom((char*)"wxShow"); @@ -531,7 +534,7 @@ case 178: {// wxShowEvent rt.addTupleCount(3); break; } -case 179: {// wxIconizeEvent +case 180: {// wxIconizeEvent wxIconizeEvent * ev = (wxIconizeEvent *) event; evClass = (char*)"wxIconizeEvent"; rt.addAtom((char*)"wxIconize"); @@ -540,14 +543,14 @@ case 179: {// wxIconizeEvent rt.addTupleCount(3); break; } -case 180: {// wxMaximizeEvent +case 181: {// wxMaximizeEvent evClass = (char*)"wxMaximizeEvent"; rt.addAtom((char*)"wxMaximize"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 181: {// wxJoystickEvent +case 182: {// wxJoystickEvent wxJoystickEvent * ev = (wxJoystickEvent *) event; evClass = (char*)"wxJoystickEvent"; rt.addAtom((char*)"wxJoystick"); @@ -560,49 +563,49 @@ case 181: {// wxJoystickEvent rt.addTupleCount(7); break; } -case 182: {// wxUpdateUIEvent +case 183: {// wxUpdateUIEvent evClass = (char*)"wxUpdateUIEvent"; rt.addAtom((char*)"wxUpdateUI"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 183: {// wxSysColourChangedEvent +case 184: {// wxSysColourChangedEvent evClass = (char*)"wxSysColourChangedEvent"; rt.addAtom((char*)"wxSysColourChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 184: {// wxMouseCaptureChangedEvent +case 185: {// wxMouseCaptureChangedEvent evClass = (char*)"wxMouseCaptureChangedEvent"; rt.addAtom((char*)"wxMouseCaptureChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 185: {// wxDisplayChangedEvent +case 186: {// wxDisplayChangedEvent evClass = (char*)"wxDisplayChangedEvent"; rt.addAtom((char*)"wxDisplayChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 186: {// wxPaletteChangedEvent +case 187: {// wxPaletteChangedEvent evClass = (char*)"wxPaletteChangedEvent"; rt.addAtom((char*)"wxPaletteChanged"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 187: {// wxQueryNewPaletteEvent +case 188: {// wxQueryNewPaletteEvent evClass = (char*)"wxQueryNewPaletteEvent"; rt.addAtom((char*)"wxQueryNewPalette"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 188: {// wxNavigationKeyEvent +case 189: {// wxNavigationKeyEvent wxNavigationKeyEvent * ev = (wxNavigationKeyEvent *) event; evClass = (char*)"wxNavigationKeyEvent"; rt.addAtom((char*)"wxNavigationKey"); @@ -612,28 +615,28 @@ case 188: {// wxNavigationKeyEvent rt.addTupleCount(4); break; } -case 189: {// wxWindowCreateEvent +case 190: {// wxWindowCreateEvent evClass = (char*)"wxWindowCreateEvent"; rt.addAtom((char*)"wxWindowCreate"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 190: {// wxWindowDestroyEvent +case 191: {// wxWindowDestroyEvent evClass = (char*)"wxWindowDestroyEvent"; rt.addAtom((char*)"wxWindowDestroy"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 191: {// wxHelpEvent +case 192: {// wxHelpEvent evClass = (char*)"wxHelpEvent"; rt.addAtom((char*)"wxHelp"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 192: {// wxContextMenuEvent +case 193: {// wxContextMenuEvent wxContextMenuEvent * ev = (wxContextMenuEvent *) event; evClass = (char*)"wxContextMenuEvent"; rt.addAtom((char*)"wxContextMenu"); @@ -642,14 +645,14 @@ case 192: {// wxContextMenuEvent rt.addTupleCount(3); break; } -case 193: {// wxIdleEvent +case 194: {// wxIdleEvent evClass = (char*)"wxIdleEvent"; rt.addAtom((char*)"wxIdle"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 194: {// wxGridEvent +case 195: {// wxGridEvent wxGridEvent * ev = (wxGridEvent *) event; evClass = (char*)"wxGridEvent"; rt.addAtom((char*)"wxGrid"); @@ -666,7 +669,7 @@ case 194: {// wxGridEvent rt.addTupleCount(11); break; } -case 196: {// wxSashEvent +case 197: {// wxSashEvent wxSashEvent * ev = (wxSashEvent *) event; evClass = (char*)"wxSashEvent"; rt.addAtom((char*)"wxSash"); @@ -677,7 +680,7 @@ case 196: {// wxSashEvent rt.addTupleCount(5); break; } -case 197: {// wxListEvent +case 198: {// wxListEvent wxListEvent * ev = (wxListEvent *) event; evClass = (char*)"wxListEvent"; rt.addAtom((char*)"wxList"); @@ -690,7 +693,7 @@ case 197: {// wxListEvent rt.addTupleCount(7); break; } -case 198: {// wxDateEvent +case 199: {// wxDateEvent wxDateEvent * ev = (wxDateEvent *) event; evClass = (char*)"wxDateEvent"; rt.addAtom((char*)"wxDate"); @@ -699,7 +702,7 @@ case 198: {// wxDateEvent rt.addTupleCount(3); break; } -case 199: {// wxCalendarEvent +case 200: {// wxCalendarEvent wxCalendarEvent * ev = (wxCalendarEvent *) event; evClass = (char*)"wxCalendarEvent"; rt.addAtom((char*)"wxCalendar"); @@ -709,7 +712,7 @@ case 199: {// wxCalendarEvent rt.addTupleCount(4); break; } -case 200: {// wxFileDirPickerEvent +case 201: {// wxFileDirPickerEvent wxFileDirPickerEvent * ev = (wxFileDirPickerEvent *) event; evClass = (char*)"wxFileDirPickerEvent"; rt.addAtom((char*)"wxFileDirPicker"); @@ -718,7 +721,7 @@ case 200: {// wxFileDirPickerEvent rt.addTupleCount(3); break; } -case 201: {// wxColourPickerEvent +case 202: {// wxColourPickerEvent wxColourPickerEvent * ev = (wxColourPickerEvent *) event; evClass = (char*)"wxColourPickerEvent"; rt.addAtom((char*)"wxColourPicker"); @@ -727,7 +730,7 @@ case 201: {// wxColourPickerEvent rt.addTupleCount(3); break; } -case 202: {// wxFontPickerEvent +case 203: {// wxFontPickerEvent wxFontPickerEvent * ev = (wxFontPickerEvent *) event; wxFont * GetFont = new wxFont(ev->GetFont()); app->newPtr((void *) GetFont,3, memenv); @@ -738,7 +741,7 @@ case 202: {// wxFontPickerEvent rt.addTupleCount(3); break; } -case 203: {// wxStyledTextEvent +case 204: {// wxStyledTextEvent wxStyledTextEvent * ev = (wxStyledTextEvent *) event; evClass = (char*)"wxStyledTextEvent"; rt.addAtom((char*)"wxStyledText"); @@ -766,7 +769,7 @@ case 203: {// wxStyledTextEvent rt.addTupleCount(22); break; } -case 209: {// wxTreeEvent +case 210: {// wxTreeEvent wxTreeEvent * ev = (wxTreeEvent *) event; evClass = (char*)"wxTreeEvent"; rt.addAtom((char*)"wxTree"); @@ -777,7 +780,7 @@ case 209: {// wxTreeEvent rt.addTupleCount(5); break; } -case 210: {// wxNotebookEvent +case 211: {// wxNotebookEvent wxNotebookEvent * ev = (wxNotebookEvent *) event; evClass = (char*)"wxNotebookEvent"; rt.addAtom((char*)"wxNotebook"); @@ -787,14 +790,14 @@ case 210: {// wxNotebookEvent rt.addTupleCount(4); break; } -case 216: {// wxClipboardTextEvent +case 217: {// wxClipboardTextEvent evClass = (char*)"wxClipboardTextEvent"; rt.addAtom((char*)"wxClipboardText"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 217: {// wxSpinEvent +case 218: {// wxSpinEvent wxSpinEvent * ev = (wxSpinEvent *) event; evClass = (char*)"wxSpinEvent"; rt.addAtom((char*)"wxSpin"); @@ -803,14 +806,14 @@ case 217: {// wxSpinEvent rt.addTupleCount(3); break; } -case 219: {// wxSplitterEvent +case 220: {// wxSplitterEvent evClass = (char*)"wxSplitterEvent"; rt.addAtom((char*)"wxSplitter"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 221: {// wxHtmlLinkEvent +case 222: {// wxHtmlLinkEvent wxHtmlLinkEvent * ev = (wxHtmlLinkEvent *) event; evClass = (char*)"wxHtmlLinkEvent"; rt.addAtom((char*)"wxHtmlLink"); @@ -819,7 +822,7 @@ case 221: {// wxHtmlLinkEvent rt.addTupleCount(3); break; } -case 224: {// wxAuiNotebookEvent +case 225: {// wxAuiNotebookEvent wxAuiNotebookEvent * ev = (wxAuiNotebookEvent *) event; wxAuiNotebook * GetDragSource = ev->GetDragSource(); evClass = (char*)"wxAuiNotebookEvent"; @@ -831,7 +834,7 @@ case 224: {// wxAuiNotebookEvent rt.addTupleCount(5); break; } -case 225: {// wxAuiManagerEvent +case 226: {// wxAuiManagerEvent wxAuiManagerEvent * ev = (wxAuiManagerEvent *) event; wxAuiManager * GetManager = ev->GetManager(); wxAuiPaneInfo * GetPane = ev->GetPane(); @@ -848,21 +851,21 @@ case 225: {// wxAuiManagerEvent rt.addTupleCount(8); break; } -case 228: {// wxTaskBarIconEvent +case 229: {// wxTaskBarIconEvent evClass = (char*)"wxTaskBarIconEvent"; rt.addAtom((char*)"wxTaskBarIcon"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 229: {// wxInitDialogEvent +case 230: {// wxInitDialogEvent evClass = (char*)"wxInitDialogEvent"; rt.addAtom((char*)"wxInitDialog"); rt.addAtom(Etype->eName); rt.addTupleCount(2); break; } -case 231: {// wxActivateEvent +case 232: {// wxActivateEvent wxActivateEvent * ev = (wxActivateEvent *) event; evClass = (char*)"wxActivateEvent"; rt.addAtom((char*)"wxActivate"); @@ -871,7 +874,7 @@ case 231: {// wxActivateEvent rt.addTupleCount(3); break; } -case 234: {// wxMouseCaptureLostEvent +case 235: {// wxMouseCaptureLostEvent evClass = (char*)"wxMouseCaptureLostEvent"; rt.addAtom((char*)"wxMouseCaptureLost"); rt.addAtom(Etype->eName); diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index b440de6cae..70b3c6add1 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -24840,8 +24840,128 @@ case wxAuiNotebook_SetUniformBitmapSize: { // wxAuiNotebook::SetUniformBitmapSiz } #endif // wxUSE_AUI #if wxUSE_AUI +case wxAuiTabArt_SetFlags: { // wxAuiTabArt::SetFlags + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + unsigned int * flags = (unsigned int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + This->SetFlags(*flags); + break; +} +case wxAuiTabArt_SetMeasuringFont: { // wxAuiTabArt::SetMeasuringFont + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetMeasuringFont(*font); + break; +} +case wxAuiTabArt_SetNormalFont: { // wxAuiTabArt::SetNormalFont + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetNormalFont(*font); + break; +} +case wxAuiTabArt_SetSelectedFont: { // wxAuiTabArt::SetSelectedFont + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetSelectedFont(*font); + break; +} +#if wxCHECK_VERSION(3,0,0) +case wxAuiTabArt_SetColour: { // wxAuiTabArt::SetColour + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + int * colourR = (int *) bp; bp += 4; + int * colourG = (int *) bp; bp += 4; + int * colourB = (int *) bp; bp += 4; + int * colourA = (int *) bp; bp += 4; + wxColour colour = wxColour(*colourR,*colourG,*colourB,*colourA); + if(!This) throw wxe_badarg(0); + This->SetColour(colour); + break; +} +#endif +#if wxCHECK_VERSION(3,0,0) +case wxAuiTabArt_SetActiveColour: { // wxAuiTabArt::SetActiveColour + wxAuiTabArt *This = (wxAuiTabArt *) getPtr(bp,memenv); bp += 4; + int * colourR = (int *) bp; bp += 4; + int * colourG = (int *) bp; bp += 4; + int * colourB = (int *) bp; bp += 4; + int * colourA = (int *) bp; bp += 4; + wxColour colour = wxColour(*colourR,*colourG,*colourB,*colourA); + if(!This) throw wxe_badarg(0); + This->SetActiveColour(colour); + break; +} +#endif +#endif // wxUSE_AUI +#if wxUSE_AUI +case wxAuiDockArt_GetColour: { // wxAuiDockArt::GetColour + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + wxColour Result = This->GetColour(*id); + rt.add(Result); + break; +} +case wxAuiDockArt_GetFont: { // wxAuiDockArt::GetFont + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + wxFont * Result = new wxFont(This->GetFont(*id)); newPtr((void *) Result,3, memenv);; + rt.addRef(getRef((void *)Result,memenv), "wxFont"); + break; +} +case wxAuiDockArt_GetMetric: { // wxAuiDockArt::GetMetric + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + int Result = This->GetMetric(*id); + rt.addInt(Result); + break; +} +case wxAuiDockArt_SetColour: { // wxAuiDockArt::SetColour + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + int * colourR = (int *) bp; bp += 4; + int * colourG = (int *) bp; bp += 4; + int * colourB = (int *) bp; bp += 4; + int * colourA = (int *) bp; bp += 4; + wxColour colour = wxColour(*colourR,*colourG,*colourB,*colourA); + if(!This) throw wxe_badarg(0); + This->SetColour(*id,colour); + break; +} +case wxAuiDockArt_SetFont: { // wxAuiDockArt::SetFont + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->SetFont(*id,*font); + break; +} +case wxAuiDockArt_SetMetric: { // wxAuiDockArt::SetMetric + wxAuiDockArt *This = (wxAuiDockArt *) getPtr(bp,memenv); bp += 4; + int * id = (int *) bp; bp += 4; + int * new_val = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + This->SetMetric(*id,*new_val); + break; +} #endif // wxUSE_AUI #if wxUSE_AUI +case wxAuiSimpleTabArt_new: { // wxAuiSimpleTabArt::wxAuiSimpleTabArt + wxAuiSimpleTabArt * Result = new wxAuiSimpleTabArt(); + newPtr((void *) Result, 159, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxAuiSimpleTabArt"); + break; +} +case wxAuiSimpleTabArt_destroy: { // wxAuiSimpleTabArt::destroy + wxAuiSimpleTabArt *This = (wxAuiSimpleTabArt *) getPtr(bp,memenv); bp += 4; + if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This); + delete This;} + break; +} #endif // wxUSE_AUI case wxMDIParentFrame_new_0: { // wxMDIParentFrame::wxMDIParentFrame wxMDIParentFrame * Result = new EwxMDIParentFrame(); @@ -30473,7 +30593,7 @@ case wxNotebookEvent_SetSelection: { // wxNotebookEvent::SetSelection } case wxFileDataObject_new: { // wxFileDataObject::wxFileDataObject wxFileDataObject * Result = new wxFileDataObject(); - newPtr((void *) Result, 212, memenv); + newPtr((void *) Result, 213, memenv); rt.addRef(getRef((void *)Result,memenv), "wxFileDataObject"); break; } @@ -30509,7 +30629,7 @@ case wxTextDataObject_new: { // wxTextDataObject::wxTextDataObject } break; }}; wxTextDataObject * Result = new wxTextDataObject(text); - newPtr((void *) Result, 213, memenv); + newPtr((void *) Result, 214, memenv); rt.addRef(getRef((void *)Result,memenv), "wxTextDataObject"); break; } @@ -30545,7 +30665,7 @@ case wxTextDataObject_destroy: { // wxTextDataObject::destroy case wxBitmapDataObject_new_1_1: { // wxBitmapDataObject::wxBitmapDataObject wxBitmap *bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4; wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap); - newPtr((void *) Result, 214, memenv); + newPtr((void *) Result, 215, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject"); break; } @@ -30557,7 +30677,7 @@ bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4; } break; }}; wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap); - newPtr((void *) Result, 214, memenv); + newPtr((void *) Result, 215, memenv); rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject"); break; } @@ -31390,7 +31510,7 @@ case wxAuiManagerEvent_CanVeto: { // wxAuiManagerEvent::CanVeto } case wxLogNull_new: { // wxLogNull::wxLogNull wxLogNull * Result = new wxLogNull(); - newPtr((void *) Result, 226, memenv); + newPtr((void *) Result, 227, memenv); rt.addRef(getRef((void *)Result,memenv), "wxLogNull"); break; } @@ -31439,7 +31559,7 @@ case wxTaskBarIcon_SetIcon: { // wxTaskBarIcon::SetIcon } case wxLocale_new_0: { // wxLocale::wxLocale wxLocale * Result = new EwxLocale(); - newPtr((void *) Result, 230, memenv); + newPtr((void *) Result, 231, memenv); rt.addRef(getRef((void *)Result,memenv), "wxLocale"); break; } @@ -31453,7 +31573,7 @@ case wxLocale_new_2: { // wxLocale::wxLocale } break; }}; wxLocale * Result = new EwxLocale(*language,flags); - newPtr((void *) Result, 230, memenv); + newPtr((void *) Result, 231, memenv); rt.addRef(getRef((void *)Result,memenv), "wxLocale"); break; } @@ -31780,11 +31900,12 @@ bool WxeApp::delete_object(void *ptr, wxeRefData *refd) { case 101: delete (wxListItemAttr *) ptr; break; case 103: delete (wxTextAttr *) ptr; break; case 155: delete (wxAuiPaneInfo *) ptr; break; - case 212: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break; - case 213: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break; - case 214: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break; - case 226: delete (wxLogNull *) ptr; break; - case 230: delete (EwxLocale *) ptr; return false; + case 159: /* delete (wxAuiSimpleTabArt *) ptr;These objects must be deleted by owner object */ break; + case 213: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break; + case 214: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break; + case 215: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break; + case 227: delete (wxLogNull *) ptr; break; + case 231: delete (EwxLocale *) ptr; return false; default: delete (wxObject *) ptr; return false; } return true; diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h index 50ceb01623..858cdc2029 100644 --- a/lib/wx/c_src/gen/wxe_macros.h +++ b/lib/wx/c_src/gen/wxe_macros.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2008-2014. All Rights Reserved. + * Copyright Ericsson AB 2008-2015. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -2510,884 +2510,898 @@ #define wxAuiNotebook_SetTabCtrlHeight 2672 #define wxAuiNotebook_SetUniformBitmapSize 2673 #define wxAuiNotebook_destroy 2674 -#define wxMDIParentFrame_new_0 2675 -#define wxMDIParentFrame_new_4 2676 -#define wxMDIParentFrame_destruct 2677 -#define wxMDIParentFrame_ActivateNext 2678 -#define wxMDIParentFrame_ActivatePrevious 2679 -#define wxMDIParentFrame_ArrangeIcons 2680 -#define wxMDIParentFrame_Cascade 2681 -#define wxMDIParentFrame_Create 2682 -#define wxMDIParentFrame_GetActiveChild 2683 -#define wxMDIParentFrame_GetClientWindow 2684 -#define wxMDIParentFrame_Tile 2685 -#define wxMDIChildFrame_new_0 2686 -#define wxMDIChildFrame_new_4 2687 -#define wxMDIChildFrame_destruct 2688 -#define wxMDIChildFrame_Activate 2689 -#define wxMDIChildFrame_Create 2690 -#define wxMDIChildFrame_Maximize 2691 -#define wxMDIChildFrame_Restore 2692 -#define wxMDIClientWindow_new_0 2693 -#define wxMDIClientWindow_new_2 2694 -#define wxMDIClientWindow_destruct 2695 -#define wxMDIClientWindow_CreateClient 2696 -#define wxLayoutAlgorithm_new 2697 -#define wxLayoutAlgorithm_LayoutFrame 2698 -#define wxLayoutAlgorithm_LayoutMDIFrame 2699 -#define wxLayoutAlgorithm_LayoutWindow 2700 -#define wxLayoutAlgorithm_destroy 2701 -#define wxEvent_GetId 2702 -#define wxEvent_GetSkipped 2703 -#define wxEvent_GetTimestamp 2704 -#define wxEvent_IsCommandEvent 2705 -#define wxEvent_ResumePropagation 2706 -#define wxEvent_ShouldPropagate 2707 -#define wxEvent_Skip 2708 -#define wxEvent_StopPropagation 2709 -#define wxCommandEvent_getClientData 2710 -#define wxCommandEvent_GetExtraLong 2711 -#define wxCommandEvent_GetInt 2712 -#define wxCommandEvent_GetSelection 2713 -#define wxCommandEvent_GetString 2714 -#define wxCommandEvent_IsChecked 2715 -#define wxCommandEvent_IsSelection 2716 -#define wxCommandEvent_SetInt 2717 -#define wxCommandEvent_SetString 2718 -#define wxScrollEvent_GetOrientation 2719 -#define wxScrollEvent_GetPosition 2720 -#define wxScrollWinEvent_GetOrientation 2721 -#define wxScrollWinEvent_GetPosition 2722 -#define wxMouseEvent_AltDown 2723 -#define wxMouseEvent_Button 2724 -#define wxMouseEvent_ButtonDClick 2725 -#define wxMouseEvent_ButtonDown 2726 -#define wxMouseEvent_ButtonUp 2727 -#define wxMouseEvent_CmdDown 2728 -#define wxMouseEvent_ControlDown 2729 -#define wxMouseEvent_Dragging 2730 -#define wxMouseEvent_Entering 2731 -#define wxMouseEvent_GetButton 2732 -#define wxMouseEvent_GetPosition 2735 -#define wxMouseEvent_GetLogicalPosition 2736 -#define wxMouseEvent_GetLinesPerAction 2737 -#define wxMouseEvent_GetWheelRotation 2738 -#define wxMouseEvent_GetWheelDelta 2739 -#define wxMouseEvent_GetX 2740 -#define wxMouseEvent_GetY 2741 -#define wxMouseEvent_IsButton 2742 -#define wxMouseEvent_IsPageScroll 2743 -#define wxMouseEvent_Leaving 2744 -#define wxMouseEvent_LeftDClick 2745 -#define wxMouseEvent_LeftDown 2746 -#define wxMouseEvent_LeftIsDown 2747 -#define wxMouseEvent_LeftUp 2748 -#define wxMouseEvent_MetaDown 2749 -#define wxMouseEvent_MiddleDClick 2750 -#define wxMouseEvent_MiddleDown 2751 -#define wxMouseEvent_MiddleIsDown 2752 -#define wxMouseEvent_MiddleUp 2753 -#define wxMouseEvent_Moving 2754 -#define wxMouseEvent_RightDClick 2755 -#define wxMouseEvent_RightDown 2756 -#define wxMouseEvent_RightIsDown 2757 -#define wxMouseEvent_RightUp 2758 -#define wxMouseEvent_ShiftDown 2759 -#define wxSetCursorEvent_GetCursor 2760 -#define wxSetCursorEvent_GetX 2761 -#define wxSetCursorEvent_GetY 2762 -#define wxSetCursorEvent_HasCursor 2763 -#define wxSetCursorEvent_SetCursor 2764 -#define wxKeyEvent_AltDown 2765 -#define wxKeyEvent_CmdDown 2766 -#define wxKeyEvent_ControlDown 2767 -#define wxKeyEvent_GetKeyCode 2768 -#define wxKeyEvent_GetModifiers 2769 -#define wxKeyEvent_GetPosition 2772 -#define wxKeyEvent_GetRawKeyCode 2773 -#define wxKeyEvent_GetRawKeyFlags 2774 -#define wxKeyEvent_GetUnicodeKey 2775 -#define wxKeyEvent_GetX 2776 -#define wxKeyEvent_GetY 2777 -#define wxKeyEvent_HasModifiers 2778 -#define wxKeyEvent_MetaDown 2779 -#define wxKeyEvent_ShiftDown 2780 -#define wxSizeEvent_GetSize 2781 -#define wxMoveEvent_GetPosition 2782 -#define wxEraseEvent_GetDC 2783 -#define wxFocusEvent_GetWindow 2784 -#define wxChildFocusEvent_GetWindow 2785 -#define wxMenuEvent_GetMenu 2786 -#define wxMenuEvent_GetMenuId 2787 -#define wxMenuEvent_IsPopup 2788 -#define wxCloseEvent_CanVeto 2789 -#define wxCloseEvent_GetLoggingOff 2790 -#define wxCloseEvent_SetCanVeto 2791 -#define wxCloseEvent_SetLoggingOff 2792 -#define wxCloseEvent_Veto 2793 -#define wxShowEvent_SetShow 2794 -#define wxShowEvent_GetShow 2795 -#define wxIconizeEvent_Iconized 2796 -#define wxJoystickEvent_ButtonDown 2797 -#define wxJoystickEvent_ButtonIsDown 2798 -#define wxJoystickEvent_ButtonUp 2799 -#define wxJoystickEvent_GetButtonChange 2800 -#define wxJoystickEvent_GetButtonState 2801 -#define wxJoystickEvent_GetJoystick 2802 -#define wxJoystickEvent_GetPosition 2803 -#define wxJoystickEvent_GetZPosition 2804 -#define wxJoystickEvent_IsButton 2805 -#define wxJoystickEvent_IsMove 2806 -#define wxJoystickEvent_IsZMove 2807 -#define wxUpdateUIEvent_CanUpdate 2808 -#define wxUpdateUIEvent_Check 2809 -#define wxUpdateUIEvent_Enable 2810 -#define wxUpdateUIEvent_Show 2811 -#define wxUpdateUIEvent_GetChecked 2812 -#define wxUpdateUIEvent_GetEnabled 2813 -#define wxUpdateUIEvent_GetShown 2814 -#define wxUpdateUIEvent_GetSetChecked 2815 -#define wxUpdateUIEvent_GetSetEnabled 2816 -#define wxUpdateUIEvent_GetSetShown 2817 -#define wxUpdateUIEvent_GetSetText 2818 -#define wxUpdateUIEvent_GetText 2819 -#define wxUpdateUIEvent_GetMode 2820 -#define wxUpdateUIEvent_GetUpdateInterval 2821 -#define wxUpdateUIEvent_ResetUpdateTime 2822 -#define wxUpdateUIEvent_SetMode 2823 -#define wxUpdateUIEvent_SetText 2824 -#define wxUpdateUIEvent_SetUpdateInterval 2825 -#define wxMouseCaptureChangedEvent_GetCapturedWindow 2826 -#define wxPaletteChangedEvent_SetChangedWindow 2827 -#define wxPaletteChangedEvent_GetChangedWindow 2828 -#define wxQueryNewPaletteEvent_SetPaletteRealized 2829 -#define wxQueryNewPaletteEvent_GetPaletteRealized 2830 -#define wxNavigationKeyEvent_GetDirection 2831 -#define wxNavigationKeyEvent_SetDirection 2832 -#define wxNavigationKeyEvent_IsWindowChange 2833 -#define wxNavigationKeyEvent_SetWindowChange 2834 -#define wxNavigationKeyEvent_IsFromTab 2835 -#define wxNavigationKeyEvent_SetFromTab 2836 -#define wxNavigationKeyEvent_GetCurrentFocus 2837 -#define wxNavigationKeyEvent_SetCurrentFocus 2838 -#define wxHelpEvent_GetOrigin 2839 -#define wxHelpEvent_GetPosition 2840 -#define wxHelpEvent_SetOrigin 2841 -#define wxHelpEvent_SetPosition 2842 -#define wxContextMenuEvent_GetPosition 2843 -#define wxContextMenuEvent_SetPosition 2844 -#define wxIdleEvent_CanSend 2845 -#define wxIdleEvent_GetMode 2846 -#define wxIdleEvent_RequestMore 2847 -#define wxIdleEvent_MoreRequested 2848 -#define wxIdleEvent_SetMode 2849 -#define wxGridEvent_AltDown 2850 -#define wxGridEvent_ControlDown 2851 -#define wxGridEvent_GetCol 2852 -#define wxGridEvent_GetPosition 2853 -#define wxGridEvent_GetRow 2854 -#define wxGridEvent_MetaDown 2855 -#define wxGridEvent_Selecting 2856 -#define wxGridEvent_ShiftDown 2857 -#define wxNotifyEvent_Allow 2858 -#define wxNotifyEvent_IsAllowed 2859 -#define wxNotifyEvent_Veto 2860 -#define wxSashEvent_GetEdge 2861 -#define wxSashEvent_GetDragRect 2862 -#define wxSashEvent_GetDragStatus 2863 -#define wxListEvent_GetCacheFrom 2864 -#define wxListEvent_GetCacheTo 2865 -#define wxListEvent_GetKeyCode 2866 -#define wxListEvent_GetIndex 2867 -#define wxListEvent_GetColumn 2868 -#define wxListEvent_GetPoint 2869 -#define wxListEvent_GetLabel 2870 -#define wxListEvent_GetText 2871 -#define wxListEvent_GetImage 2872 -#define wxListEvent_GetData 2873 -#define wxListEvent_GetMask 2874 -#define wxListEvent_GetItem 2875 -#define wxListEvent_IsEditCancelled 2876 -#define wxDateEvent_GetDate 2877 -#define wxCalendarEvent_GetWeekDay 2878 -#define wxFileDirPickerEvent_GetPath 2879 -#define wxColourPickerEvent_GetColour 2880 -#define wxFontPickerEvent_GetFont 2881 -#define wxStyledTextEvent_GetPosition 2882 -#define wxStyledTextEvent_GetKey 2883 -#define wxStyledTextEvent_GetModifiers 2884 -#define wxStyledTextEvent_GetModificationType 2885 -#define wxStyledTextEvent_GetText 2886 -#define wxStyledTextEvent_GetLength 2887 -#define wxStyledTextEvent_GetLinesAdded 2888 -#define wxStyledTextEvent_GetLine 2889 -#define wxStyledTextEvent_GetFoldLevelNow 2890 -#define wxStyledTextEvent_GetFoldLevelPrev 2891 -#define wxStyledTextEvent_GetMargin 2892 -#define wxStyledTextEvent_GetMessage 2893 -#define wxStyledTextEvent_GetWParam 2894 -#define wxStyledTextEvent_GetLParam 2895 -#define wxStyledTextEvent_GetListType 2896 -#define wxStyledTextEvent_GetX 2897 -#define wxStyledTextEvent_GetY 2898 -#define wxStyledTextEvent_GetDragText 2899 -#define wxStyledTextEvent_GetDragAllowMove 2900 -#define wxStyledTextEvent_GetDragResult 2901 -#define wxStyledTextEvent_GetShift 2902 -#define wxStyledTextEvent_GetControl 2903 -#define wxStyledTextEvent_GetAlt 2904 -#define utils_wxGetKeyState 2905 -#define utils_wxGetMousePosition 2906 -#define utils_wxGetMouseState 2907 -#define utils_wxSetDetectableAutoRepeat 2908 -#define utils_wxBell 2909 -#define utils_wxFindMenuItemId 2910 -#define utils_wxGenericFindWindowAtPoint 2911 -#define utils_wxFindWindowAtPoint 2912 -#define utils_wxBeginBusyCursor 2913 -#define utils_wxEndBusyCursor 2914 -#define utils_wxIsBusy 2915 -#define utils_wxShutdown 2916 -#define utils_wxShell 2917 -#define utils_wxLaunchDefaultBrowser 2918 -#define utils_wxGetEmailAddress 2919 -#define utils_wxGetUserId 2920 -#define utils_wxGetHomeDir 2921 -#define utils_wxNewId 2922 -#define utils_wxRegisterId 2923 -#define utils_wxGetCurrentId 2924 -#define utils_wxGetOsDescription 2925 -#define utils_wxIsPlatformLittleEndian 2926 -#define utils_wxIsPlatform64Bit 2927 -#define gdicmn_wxDisplaySize 2928 -#define gdicmn_wxSetCursor 2929 -#define wxPrintout_new 2930 -#define wxPrintout_destruct 2931 -#define wxPrintout_GetDC 2932 -#define wxPrintout_GetPageSizeMM 2933 -#define wxPrintout_GetPageSizePixels 2934 -#define wxPrintout_GetPaperRectPixels 2935 -#define wxPrintout_GetPPIPrinter 2936 -#define wxPrintout_GetPPIScreen 2937 -#define wxPrintout_GetTitle 2938 -#define wxPrintout_IsPreview 2939 -#define wxPrintout_FitThisSizeToPaper 2940 -#define wxPrintout_FitThisSizeToPage 2941 -#define wxPrintout_FitThisSizeToPageMargins 2942 -#define wxPrintout_MapScreenSizeToPaper 2943 -#define wxPrintout_MapScreenSizeToPage 2944 -#define wxPrintout_MapScreenSizeToPageMargins 2945 -#define wxPrintout_MapScreenSizeToDevice 2946 -#define wxPrintout_GetLogicalPaperRect 2947 -#define wxPrintout_GetLogicalPageRect 2948 -#define wxPrintout_GetLogicalPageMarginsRect 2949 -#define wxPrintout_SetLogicalOrigin 2950 -#define wxPrintout_OffsetLogicalOrigin 2951 -#define wxStyledTextCtrl_new_2 2952 -#define wxStyledTextCtrl_new_0 2953 -#define wxStyledTextCtrl_destruct 2954 -#define wxStyledTextCtrl_Create 2955 -#define wxStyledTextCtrl_AddText 2956 -#define wxStyledTextCtrl_AddStyledText 2957 -#define wxStyledTextCtrl_InsertText 2958 -#define wxStyledTextCtrl_ClearAll 2959 -#define wxStyledTextCtrl_ClearDocumentStyle 2960 -#define wxStyledTextCtrl_GetLength 2961 -#define wxStyledTextCtrl_GetCharAt 2962 -#define wxStyledTextCtrl_GetCurrentPos 2963 -#define wxStyledTextCtrl_GetAnchor 2964 -#define wxStyledTextCtrl_GetStyleAt 2965 -#define wxStyledTextCtrl_Redo 2966 -#define wxStyledTextCtrl_SetUndoCollection 2967 -#define wxStyledTextCtrl_SelectAll 2968 -#define wxStyledTextCtrl_SetSavePoint 2969 -#define wxStyledTextCtrl_GetStyledText 2970 -#define wxStyledTextCtrl_CanRedo 2971 -#define wxStyledTextCtrl_MarkerLineFromHandle 2972 -#define wxStyledTextCtrl_MarkerDeleteHandle 2973 -#define wxStyledTextCtrl_GetUndoCollection 2974 -#define wxStyledTextCtrl_GetViewWhiteSpace 2975 -#define wxStyledTextCtrl_SetViewWhiteSpace 2976 -#define wxStyledTextCtrl_PositionFromPoint 2977 -#define wxStyledTextCtrl_PositionFromPointClose 2978 -#define wxStyledTextCtrl_GotoLine 2979 -#define wxStyledTextCtrl_GotoPos 2980 -#define wxStyledTextCtrl_SetAnchor 2981 -#define wxStyledTextCtrl_GetCurLine 2982 -#define wxStyledTextCtrl_GetEndStyled 2983 -#define wxStyledTextCtrl_ConvertEOLs 2984 -#define wxStyledTextCtrl_GetEOLMode 2985 -#define wxStyledTextCtrl_SetEOLMode 2986 -#define wxStyledTextCtrl_StartStyling 2987 -#define wxStyledTextCtrl_SetStyling 2988 -#define wxStyledTextCtrl_GetBufferedDraw 2989 -#define wxStyledTextCtrl_SetBufferedDraw 2990 -#define wxStyledTextCtrl_SetTabWidth 2991 -#define wxStyledTextCtrl_GetTabWidth 2992 -#define wxStyledTextCtrl_SetCodePage 2993 -#define wxStyledTextCtrl_MarkerDefine 2994 -#define wxStyledTextCtrl_MarkerSetForeground 2995 -#define wxStyledTextCtrl_MarkerSetBackground 2996 -#define wxStyledTextCtrl_MarkerAdd 2997 -#define wxStyledTextCtrl_MarkerDelete 2998 -#define wxStyledTextCtrl_MarkerDeleteAll 2999 -#define wxStyledTextCtrl_MarkerGet 3000 -#define wxStyledTextCtrl_MarkerNext 3001 -#define wxStyledTextCtrl_MarkerPrevious 3002 -#define wxStyledTextCtrl_MarkerDefineBitmap 3003 -#define wxStyledTextCtrl_MarkerAddSet 3004 -#define wxStyledTextCtrl_MarkerSetAlpha 3005 -#define wxStyledTextCtrl_SetMarginType 3006 -#define wxStyledTextCtrl_GetMarginType 3007 -#define wxStyledTextCtrl_SetMarginWidth 3008 -#define wxStyledTextCtrl_GetMarginWidth 3009 -#define wxStyledTextCtrl_SetMarginMask 3010 -#define wxStyledTextCtrl_GetMarginMask 3011 -#define wxStyledTextCtrl_SetMarginSensitive 3012 -#define wxStyledTextCtrl_GetMarginSensitive 3013 -#define wxStyledTextCtrl_StyleClearAll 3014 -#define wxStyledTextCtrl_StyleSetForeground 3015 -#define wxStyledTextCtrl_StyleSetBackground 3016 -#define wxStyledTextCtrl_StyleSetBold 3017 -#define wxStyledTextCtrl_StyleSetItalic 3018 -#define wxStyledTextCtrl_StyleSetSize 3019 -#define wxStyledTextCtrl_StyleSetFaceName 3020 -#define wxStyledTextCtrl_StyleSetEOLFilled 3021 -#define wxStyledTextCtrl_StyleResetDefault 3022 -#define wxStyledTextCtrl_StyleSetUnderline 3023 -#define wxStyledTextCtrl_StyleSetCase 3024 -#define wxStyledTextCtrl_StyleSetHotSpot 3025 -#define wxStyledTextCtrl_SetSelForeground 3026 -#define wxStyledTextCtrl_SetSelBackground 3027 -#define wxStyledTextCtrl_GetSelAlpha 3028 -#define wxStyledTextCtrl_SetSelAlpha 3029 -#define wxStyledTextCtrl_SetCaretForeground 3030 -#define wxStyledTextCtrl_CmdKeyAssign 3031 -#define wxStyledTextCtrl_CmdKeyClear 3032 -#define wxStyledTextCtrl_CmdKeyClearAll 3033 -#define wxStyledTextCtrl_SetStyleBytes 3034 -#define wxStyledTextCtrl_StyleSetVisible 3035 -#define wxStyledTextCtrl_GetCaretPeriod 3036 -#define wxStyledTextCtrl_SetCaretPeriod 3037 -#define wxStyledTextCtrl_SetWordChars 3038 -#define wxStyledTextCtrl_BeginUndoAction 3039 -#define wxStyledTextCtrl_EndUndoAction 3040 -#define wxStyledTextCtrl_IndicatorSetStyle 3041 -#define wxStyledTextCtrl_IndicatorGetStyle 3042 -#define wxStyledTextCtrl_IndicatorSetForeground 3043 -#define wxStyledTextCtrl_IndicatorGetForeground 3044 -#define wxStyledTextCtrl_SetWhitespaceForeground 3045 -#define wxStyledTextCtrl_SetWhitespaceBackground 3046 -#define wxStyledTextCtrl_GetStyleBits 3047 -#define wxStyledTextCtrl_SetLineState 3048 -#define wxStyledTextCtrl_GetLineState 3049 -#define wxStyledTextCtrl_GetMaxLineState 3050 -#define wxStyledTextCtrl_GetCaretLineVisible 3051 -#define wxStyledTextCtrl_SetCaretLineVisible 3052 -#define wxStyledTextCtrl_GetCaretLineBackground 3053 -#define wxStyledTextCtrl_SetCaretLineBackground 3054 -#define wxStyledTextCtrl_AutoCompShow 3055 -#define wxStyledTextCtrl_AutoCompCancel 3056 -#define wxStyledTextCtrl_AutoCompActive 3057 -#define wxStyledTextCtrl_AutoCompPosStart 3058 -#define wxStyledTextCtrl_AutoCompComplete 3059 -#define wxStyledTextCtrl_AutoCompStops 3060 -#define wxStyledTextCtrl_AutoCompSetSeparator 3061 -#define wxStyledTextCtrl_AutoCompGetSeparator 3062 -#define wxStyledTextCtrl_AutoCompSelect 3063 -#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3064 -#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3065 -#define wxStyledTextCtrl_AutoCompSetFillUps 3066 -#define wxStyledTextCtrl_AutoCompSetChooseSingle 3067 -#define wxStyledTextCtrl_AutoCompGetChooseSingle 3068 -#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3069 -#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3070 -#define wxStyledTextCtrl_UserListShow 3071 -#define wxStyledTextCtrl_AutoCompSetAutoHide 3072 -#define wxStyledTextCtrl_AutoCompGetAutoHide 3073 -#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3074 -#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3075 -#define wxStyledTextCtrl_RegisterImage 3076 -#define wxStyledTextCtrl_ClearRegisteredImages 3077 -#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3078 -#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3079 -#define wxStyledTextCtrl_AutoCompSetMaxWidth 3080 -#define wxStyledTextCtrl_AutoCompGetMaxWidth 3081 -#define wxStyledTextCtrl_AutoCompSetMaxHeight 3082 -#define wxStyledTextCtrl_AutoCompGetMaxHeight 3083 -#define wxStyledTextCtrl_SetIndent 3084 -#define wxStyledTextCtrl_GetIndent 3085 -#define wxStyledTextCtrl_SetUseTabs 3086 -#define wxStyledTextCtrl_GetUseTabs 3087 -#define wxStyledTextCtrl_SetLineIndentation 3088 -#define wxStyledTextCtrl_GetLineIndentation 3089 -#define wxStyledTextCtrl_GetLineIndentPosition 3090 -#define wxStyledTextCtrl_GetColumn 3091 -#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3092 -#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3093 -#define wxStyledTextCtrl_SetIndentationGuides 3094 -#define wxStyledTextCtrl_GetIndentationGuides 3095 -#define wxStyledTextCtrl_SetHighlightGuide 3096 -#define wxStyledTextCtrl_GetHighlightGuide 3097 -#define wxStyledTextCtrl_GetLineEndPosition 3098 -#define wxStyledTextCtrl_GetCodePage 3099 -#define wxStyledTextCtrl_GetCaretForeground 3100 -#define wxStyledTextCtrl_GetReadOnly 3101 -#define wxStyledTextCtrl_SetCurrentPos 3102 -#define wxStyledTextCtrl_SetSelectionStart 3103 -#define wxStyledTextCtrl_GetSelectionStart 3104 -#define wxStyledTextCtrl_SetSelectionEnd 3105 -#define wxStyledTextCtrl_GetSelectionEnd 3106 -#define wxStyledTextCtrl_SetPrintMagnification 3107 -#define wxStyledTextCtrl_GetPrintMagnification 3108 -#define wxStyledTextCtrl_SetPrintColourMode 3109 -#define wxStyledTextCtrl_GetPrintColourMode 3110 -#define wxStyledTextCtrl_FindText 3111 -#define wxStyledTextCtrl_FormatRange 3112 -#define wxStyledTextCtrl_GetFirstVisibleLine 3113 -#define wxStyledTextCtrl_GetLine 3114 -#define wxStyledTextCtrl_GetLineCount 3115 -#define wxStyledTextCtrl_SetMarginLeft 3116 -#define wxStyledTextCtrl_GetMarginLeft 3117 -#define wxStyledTextCtrl_SetMarginRight 3118 -#define wxStyledTextCtrl_GetMarginRight 3119 -#define wxStyledTextCtrl_GetModify 3120 -#define wxStyledTextCtrl_SetSelection 3121 -#define wxStyledTextCtrl_GetSelectedText 3122 -#define wxStyledTextCtrl_GetTextRange 3123 -#define wxStyledTextCtrl_HideSelection 3124 -#define wxStyledTextCtrl_LineFromPosition 3125 -#define wxStyledTextCtrl_PositionFromLine 3126 -#define wxStyledTextCtrl_LineScroll 3127 -#define wxStyledTextCtrl_EnsureCaretVisible 3128 -#define wxStyledTextCtrl_ReplaceSelection 3129 -#define wxStyledTextCtrl_SetReadOnly 3130 -#define wxStyledTextCtrl_CanPaste 3131 -#define wxStyledTextCtrl_CanUndo 3132 -#define wxStyledTextCtrl_EmptyUndoBuffer 3133 -#define wxStyledTextCtrl_Undo 3134 -#define wxStyledTextCtrl_Cut 3135 -#define wxStyledTextCtrl_Copy 3136 -#define wxStyledTextCtrl_Paste 3137 -#define wxStyledTextCtrl_Clear 3138 -#define wxStyledTextCtrl_SetText 3139 -#define wxStyledTextCtrl_GetText 3140 -#define wxStyledTextCtrl_GetTextLength 3141 -#define wxStyledTextCtrl_GetOvertype 3142 -#define wxStyledTextCtrl_SetCaretWidth 3143 -#define wxStyledTextCtrl_GetCaretWidth 3144 -#define wxStyledTextCtrl_SetTargetStart 3145 -#define wxStyledTextCtrl_GetTargetStart 3146 -#define wxStyledTextCtrl_SetTargetEnd 3147 -#define wxStyledTextCtrl_GetTargetEnd 3148 -#define wxStyledTextCtrl_ReplaceTarget 3149 -#define wxStyledTextCtrl_SearchInTarget 3150 -#define wxStyledTextCtrl_SetSearchFlags 3151 -#define wxStyledTextCtrl_GetSearchFlags 3152 -#define wxStyledTextCtrl_CallTipShow 3153 -#define wxStyledTextCtrl_CallTipCancel 3154 -#define wxStyledTextCtrl_CallTipActive 3155 -#define wxStyledTextCtrl_CallTipPosAtStart 3156 -#define wxStyledTextCtrl_CallTipSetHighlight 3157 -#define wxStyledTextCtrl_CallTipSetBackground 3158 -#define wxStyledTextCtrl_CallTipSetForeground 3159 -#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3160 -#define wxStyledTextCtrl_CallTipUseStyle 3161 -#define wxStyledTextCtrl_VisibleFromDocLine 3162 -#define wxStyledTextCtrl_DocLineFromVisible 3163 -#define wxStyledTextCtrl_WrapCount 3164 -#define wxStyledTextCtrl_SetFoldLevel 3165 -#define wxStyledTextCtrl_GetFoldLevel 3166 -#define wxStyledTextCtrl_GetLastChild 3167 -#define wxStyledTextCtrl_GetFoldParent 3168 -#define wxStyledTextCtrl_ShowLines 3169 -#define wxStyledTextCtrl_HideLines 3170 -#define wxStyledTextCtrl_GetLineVisible 3171 -#define wxStyledTextCtrl_SetFoldExpanded 3172 -#define wxStyledTextCtrl_GetFoldExpanded 3173 -#define wxStyledTextCtrl_ToggleFold 3174 -#define wxStyledTextCtrl_EnsureVisible 3175 -#define wxStyledTextCtrl_SetFoldFlags 3176 -#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3177 -#define wxStyledTextCtrl_SetTabIndents 3178 -#define wxStyledTextCtrl_GetTabIndents 3179 -#define wxStyledTextCtrl_SetBackSpaceUnIndents 3180 -#define wxStyledTextCtrl_GetBackSpaceUnIndents 3181 -#define wxStyledTextCtrl_SetMouseDwellTime 3182 -#define wxStyledTextCtrl_GetMouseDwellTime 3183 -#define wxStyledTextCtrl_WordStartPosition 3184 -#define wxStyledTextCtrl_WordEndPosition 3185 -#define wxStyledTextCtrl_SetWrapMode 3186 -#define wxStyledTextCtrl_GetWrapMode 3187 -#define wxStyledTextCtrl_SetWrapVisualFlags 3188 -#define wxStyledTextCtrl_GetWrapVisualFlags 3189 -#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3190 -#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3191 -#define wxStyledTextCtrl_SetWrapStartIndent 3192 -#define wxStyledTextCtrl_GetWrapStartIndent 3193 -#define wxStyledTextCtrl_SetLayoutCache 3194 -#define wxStyledTextCtrl_GetLayoutCache 3195 -#define wxStyledTextCtrl_SetScrollWidth 3196 -#define wxStyledTextCtrl_GetScrollWidth 3197 -#define wxStyledTextCtrl_TextWidth 3198 -#define wxStyledTextCtrl_GetEndAtLastLine 3199 -#define wxStyledTextCtrl_TextHeight 3200 -#define wxStyledTextCtrl_SetUseVerticalScrollBar 3201 -#define wxStyledTextCtrl_GetUseVerticalScrollBar 3202 -#define wxStyledTextCtrl_AppendText 3203 -#define wxStyledTextCtrl_GetTwoPhaseDraw 3204 -#define wxStyledTextCtrl_SetTwoPhaseDraw 3205 -#define wxStyledTextCtrl_TargetFromSelection 3206 -#define wxStyledTextCtrl_LinesJoin 3207 -#define wxStyledTextCtrl_LinesSplit 3208 -#define wxStyledTextCtrl_SetFoldMarginColour 3209 -#define wxStyledTextCtrl_SetFoldMarginHiColour 3210 -#define wxStyledTextCtrl_LineDown 3211 -#define wxStyledTextCtrl_LineDownExtend 3212 -#define wxStyledTextCtrl_LineUp 3213 -#define wxStyledTextCtrl_LineUpExtend 3214 -#define wxStyledTextCtrl_CharLeft 3215 -#define wxStyledTextCtrl_CharLeftExtend 3216 -#define wxStyledTextCtrl_CharRight 3217 -#define wxStyledTextCtrl_CharRightExtend 3218 -#define wxStyledTextCtrl_WordLeft 3219 -#define wxStyledTextCtrl_WordLeftExtend 3220 -#define wxStyledTextCtrl_WordRight 3221 -#define wxStyledTextCtrl_WordRightExtend 3222 -#define wxStyledTextCtrl_Home 3223 -#define wxStyledTextCtrl_HomeExtend 3224 -#define wxStyledTextCtrl_LineEnd 3225 -#define wxStyledTextCtrl_LineEndExtend 3226 -#define wxStyledTextCtrl_DocumentStart 3227 -#define wxStyledTextCtrl_DocumentStartExtend 3228 -#define wxStyledTextCtrl_DocumentEnd 3229 -#define wxStyledTextCtrl_DocumentEndExtend 3230 -#define wxStyledTextCtrl_PageUp 3231 -#define wxStyledTextCtrl_PageUpExtend 3232 -#define wxStyledTextCtrl_PageDown 3233 -#define wxStyledTextCtrl_PageDownExtend 3234 -#define wxStyledTextCtrl_EditToggleOvertype 3235 -#define wxStyledTextCtrl_Cancel 3236 -#define wxStyledTextCtrl_DeleteBack 3237 -#define wxStyledTextCtrl_Tab 3238 -#define wxStyledTextCtrl_BackTab 3239 -#define wxStyledTextCtrl_NewLine 3240 -#define wxStyledTextCtrl_FormFeed 3241 -#define wxStyledTextCtrl_VCHome 3242 -#define wxStyledTextCtrl_VCHomeExtend 3243 -#define wxStyledTextCtrl_ZoomIn 3244 -#define wxStyledTextCtrl_ZoomOut 3245 -#define wxStyledTextCtrl_DelWordLeft 3246 -#define wxStyledTextCtrl_DelWordRight 3247 -#define wxStyledTextCtrl_LineCut 3248 -#define wxStyledTextCtrl_LineDelete 3249 -#define wxStyledTextCtrl_LineTranspose 3250 -#define wxStyledTextCtrl_LineDuplicate 3251 -#define wxStyledTextCtrl_LowerCase 3252 -#define wxStyledTextCtrl_UpperCase 3253 -#define wxStyledTextCtrl_LineScrollDown 3254 -#define wxStyledTextCtrl_LineScrollUp 3255 -#define wxStyledTextCtrl_DeleteBackNotLine 3256 -#define wxStyledTextCtrl_HomeDisplay 3257 -#define wxStyledTextCtrl_HomeDisplayExtend 3258 -#define wxStyledTextCtrl_LineEndDisplay 3259 -#define wxStyledTextCtrl_LineEndDisplayExtend 3260 -#define wxStyledTextCtrl_HomeWrapExtend 3261 -#define wxStyledTextCtrl_LineEndWrap 3262 -#define wxStyledTextCtrl_LineEndWrapExtend 3263 -#define wxStyledTextCtrl_VCHomeWrap 3264 -#define wxStyledTextCtrl_VCHomeWrapExtend 3265 -#define wxStyledTextCtrl_LineCopy 3266 -#define wxStyledTextCtrl_MoveCaretInsideView 3267 -#define wxStyledTextCtrl_LineLength 3268 -#define wxStyledTextCtrl_BraceHighlight 3269 -#define wxStyledTextCtrl_BraceBadLight 3270 -#define wxStyledTextCtrl_BraceMatch 3271 -#define wxStyledTextCtrl_GetViewEOL 3272 -#define wxStyledTextCtrl_SetViewEOL 3273 -#define wxStyledTextCtrl_SetModEventMask 3274 -#define wxStyledTextCtrl_GetEdgeColumn 3275 -#define wxStyledTextCtrl_SetEdgeColumn 3276 -#define wxStyledTextCtrl_SetEdgeMode 3277 -#define wxStyledTextCtrl_GetEdgeMode 3278 -#define wxStyledTextCtrl_GetEdgeColour 3279 -#define wxStyledTextCtrl_SetEdgeColour 3280 -#define wxStyledTextCtrl_SearchAnchor 3281 -#define wxStyledTextCtrl_SearchNext 3282 -#define wxStyledTextCtrl_SearchPrev 3283 -#define wxStyledTextCtrl_LinesOnScreen 3284 -#define wxStyledTextCtrl_UsePopUp 3285 -#define wxStyledTextCtrl_SelectionIsRectangle 3286 -#define wxStyledTextCtrl_SetZoom 3287 -#define wxStyledTextCtrl_GetZoom 3288 -#define wxStyledTextCtrl_GetModEventMask 3289 -#define wxStyledTextCtrl_SetSTCFocus 3290 -#define wxStyledTextCtrl_GetSTCFocus 3291 -#define wxStyledTextCtrl_SetStatus 3292 -#define wxStyledTextCtrl_GetStatus 3293 -#define wxStyledTextCtrl_SetMouseDownCaptures 3294 -#define wxStyledTextCtrl_GetMouseDownCaptures 3295 -#define wxStyledTextCtrl_SetSTCCursor 3296 -#define wxStyledTextCtrl_GetSTCCursor 3297 -#define wxStyledTextCtrl_SetControlCharSymbol 3298 -#define wxStyledTextCtrl_GetControlCharSymbol 3299 -#define wxStyledTextCtrl_WordPartLeft 3300 -#define wxStyledTextCtrl_WordPartLeftExtend 3301 -#define wxStyledTextCtrl_WordPartRight 3302 -#define wxStyledTextCtrl_WordPartRightExtend 3303 -#define wxStyledTextCtrl_SetVisiblePolicy 3304 -#define wxStyledTextCtrl_DelLineLeft 3305 -#define wxStyledTextCtrl_DelLineRight 3306 -#define wxStyledTextCtrl_GetXOffset 3307 -#define wxStyledTextCtrl_ChooseCaretX 3308 -#define wxStyledTextCtrl_SetXCaretPolicy 3309 -#define wxStyledTextCtrl_SetYCaretPolicy 3310 -#define wxStyledTextCtrl_GetPrintWrapMode 3311 -#define wxStyledTextCtrl_SetHotspotActiveForeground 3312 -#define wxStyledTextCtrl_SetHotspotActiveBackground 3313 -#define wxStyledTextCtrl_SetHotspotActiveUnderline 3314 -#define wxStyledTextCtrl_SetHotspotSingleLine 3315 -#define wxStyledTextCtrl_ParaDownExtend 3316 -#define wxStyledTextCtrl_ParaUp 3317 -#define wxStyledTextCtrl_ParaUpExtend 3318 -#define wxStyledTextCtrl_PositionBefore 3319 -#define wxStyledTextCtrl_PositionAfter 3320 -#define wxStyledTextCtrl_CopyRange 3321 -#define wxStyledTextCtrl_CopyText 3322 -#define wxStyledTextCtrl_SetSelectionMode 3323 -#define wxStyledTextCtrl_GetSelectionMode 3324 -#define wxStyledTextCtrl_LineDownRectExtend 3325 -#define wxStyledTextCtrl_LineUpRectExtend 3326 -#define wxStyledTextCtrl_CharLeftRectExtend 3327 -#define wxStyledTextCtrl_CharRightRectExtend 3328 -#define wxStyledTextCtrl_HomeRectExtend 3329 -#define wxStyledTextCtrl_VCHomeRectExtend 3330 -#define wxStyledTextCtrl_LineEndRectExtend 3331 -#define wxStyledTextCtrl_PageUpRectExtend 3332 -#define wxStyledTextCtrl_PageDownRectExtend 3333 -#define wxStyledTextCtrl_StutteredPageUp 3334 -#define wxStyledTextCtrl_StutteredPageUpExtend 3335 -#define wxStyledTextCtrl_StutteredPageDown 3336 -#define wxStyledTextCtrl_StutteredPageDownExtend 3337 -#define wxStyledTextCtrl_WordLeftEnd 3338 -#define wxStyledTextCtrl_WordLeftEndExtend 3339 -#define wxStyledTextCtrl_WordRightEnd 3340 -#define wxStyledTextCtrl_WordRightEndExtend 3341 -#define wxStyledTextCtrl_SetWhitespaceChars 3342 -#define wxStyledTextCtrl_SetCharsDefault 3343 -#define wxStyledTextCtrl_AutoCompGetCurrent 3344 -#define wxStyledTextCtrl_Allocate 3345 -#define wxStyledTextCtrl_FindColumn 3346 -#define wxStyledTextCtrl_GetCaretSticky 3347 -#define wxStyledTextCtrl_SetCaretSticky 3348 -#define wxStyledTextCtrl_ToggleCaretSticky 3349 -#define wxStyledTextCtrl_SetPasteConvertEndings 3350 -#define wxStyledTextCtrl_GetPasteConvertEndings 3351 -#define wxStyledTextCtrl_SelectionDuplicate 3352 -#define wxStyledTextCtrl_SetCaretLineBackAlpha 3353 -#define wxStyledTextCtrl_GetCaretLineBackAlpha 3354 -#define wxStyledTextCtrl_StartRecord 3355 -#define wxStyledTextCtrl_StopRecord 3356 -#define wxStyledTextCtrl_SetLexer 3357 -#define wxStyledTextCtrl_GetLexer 3358 -#define wxStyledTextCtrl_Colourise 3359 -#define wxStyledTextCtrl_SetProperty 3360 -#define wxStyledTextCtrl_SetKeyWords 3361 -#define wxStyledTextCtrl_SetLexerLanguage 3362 -#define wxStyledTextCtrl_GetProperty 3363 -#define wxStyledTextCtrl_GetStyleBitsNeeded 3364 -#define wxStyledTextCtrl_GetCurrentLine 3365 -#define wxStyledTextCtrl_StyleSetSpec 3366 -#define wxStyledTextCtrl_StyleSetFont 3367 -#define wxStyledTextCtrl_StyleSetFontAttr 3368 -#define wxStyledTextCtrl_StyleSetCharacterSet 3369 -#define wxStyledTextCtrl_StyleSetFontEncoding 3370 -#define wxStyledTextCtrl_CmdKeyExecute 3371 -#define wxStyledTextCtrl_SetMargins 3372 -#define wxStyledTextCtrl_GetSelection 3373 -#define wxStyledTextCtrl_PointFromPosition 3374 -#define wxStyledTextCtrl_ScrollToLine 3375 -#define wxStyledTextCtrl_ScrollToColumn 3376 -#define wxStyledTextCtrl_SetVScrollBar 3377 -#define wxStyledTextCtrl_SetHScrollBar 3378 -#define wxStyledTextCtrl_GetLastKeydownProcessed 3379 -#define wxStyledTextCtrl_SetLastKeydownProcessed 3380 -#define wxStyledTextCtrl_SaveFile 3381 -#define wxStyledTextCtrl_LoadFile 3382 -#define wxStyledTextCtrl_DoDragOver 3383 -#define wxStyledTextCtrl_DoDropText 3384 -#define wxStyledTextCtrl_GetUseAntiAliasing 3385 -#define wxStyledTextCtrl_AddTextRaw 3386 -#define wxStyledTextCtrl_InsertTextRaw 3387 -#define wxStyledTextCtrl_GetCurLineRaw 3388 -#define wxStyledTextCtrl_GetLineRaw 3389 -#define wxStyledTextCtrl_GetSelectedTextRaw 3390 -#define wxStyledTextCtrl_GetTextRangeRaw 3391 -#define wxStyledTextCtrl_SetTextRaw 3392 -#define wxStyledTextCtrl_GetTextRaw 3393 -#define wxStyledTextCtrl_AppendTextRaw 3394 -#define wxArtProvider_GetBitmap 3395 -#define wxArtProvider_GetIcon 3396 -#define wxTreeEvent_GetKeyCode 3397 -#define wxTreeEvent_GetItem 3398 -#define wxTreeEvent_GetKeyEvent 3399 -#define wxTreeEvent_GetLabel 3400 -#define wxTreeEvent_GetOldItem 3401 -#define wxTreeEvent_GetPoint 3402 -#define wxTreeEvent_IsEditCancelled 3403 -#define wxTreeEvent_SetToolTip 3404 -#define wxNotebookEvent_GetOldSelection 3405 -#define wxNotebookEvent_GetSelection 3406 -#define wxNotebookEvent_SetOldSelection 3407 -#define wxNotebookEvent_SetSelection 3408 -#define wxFileDataObject_new 3409 -#define wxFileDataObject_AddFile 3410 -#define wxFileDataObject_GetFilenames 3411 -#define wxFileDataObject_destroy 3412 -#define wxTextDataObject_new 3413 -#define wxTextDataObject_GetTextLength 3414 -#define wxTextDataObject_GetText 3415 -#define wxTextDataObject_SetText 3416 -#define wxTextDataObject_destroy 3417 -#define wxBitmapDataObject_new_1_1 3418 -#define wxBitmapDataObject_new_1_0 3419 -#define wxBitmapDataObject_GetBitmap 3420 -#define wxBitmapDataObject_SetBitmap 3421 -#define wxBitmapDataObject_destroy 3422 -#define wxClipboard_new 3424 -#define wxClipboard_destruct 3425 -#define wxClipboard_AddData 3426 -#define wxClipboard_Clear 3427 -#define wxClipboard_Close 3428 -#define wxClipboard_Flush 3429 -#define wxClipboard_GetData 3430 -#define wxClipboard_IsOpened 3431 -#define wxClipboard_Open 3432 -#define wxClipboard_SetData 3433 -#define wxClipboard_UsePrimarySelection 3435 -#define wxClipboard_IsSupported 3436 -#define wxClipboard_Get 3437 -#define wxSpinEvent_GetPosition 3438 -#define wxSpinEvent_SetPosition 3439 -#define wxSplitterWindow_new_0 3440 -#define wxSplitterWindow_new_2 3441 -#define wxSplitterWindow_destruct 3442 -#define wxSplitterWindow_Create 3443 -#define wxSplitterWindow_GetMinimumPaneSize 3444 -#define wxSplitterWindow_GetSashGravity 3445 -#define wxSplitterWindow_GetSashPosition 3446 -#define wxSplitterWindow_GetSplitMode 3447 -#define wxSplitterWindow_GetWindow1 3448 -#define wxSplitterWindow_GetWindow2 3449 -#define wxSplitterWindow_Initialize 3450 -#define wxSplitterWindow_IsSplit 3451 -#define wxSplitterWindow_ReplaceWindow 3452 -#define wxSplitterWindow_SetSashGravity 3453 -#define wxSplitterWindow_SetSashPosition 3454 -#define wxSplitterWindow_SetSashSize 3455 -#define wxSplitterWindow_SetMinimumPaneSize 3456 -#define wxSplitterWindow_SetSplitMode 3457 -#define wxSplitterWindow_SplitHorizontally 3458 -#define wxSplitterWindow_SplitVertically 3459 -#define wxSplitterWindow_Unsplit 3460 -#define wxSplitterWindow_UpdateSize 3461 -#define wxSplitterEvent_GetSashPosition 3462 -#define wxSplitterEvent_GetX 3463 -#define wxSplitterEvent_GetY 3464 -#define wxSplitterEvent_GetWindowBeingRemoved 3465 -#define wxSplitterEvent_SetSashPosition 3466 -#define wxHtmlWindow_new_0 3467 -#define wxHtmlWindow_new_2 3468 -#define wxHtmlWindow_AppendToPage 3469 -#define wxHtmlWindow_GetOpenedAnchor 3470 -#define wxHtmlWindow_GetOpenedPage 3471 -#define wxHtmlWindow_GetOpenedPageTitle 3472 -#define wxHtmlWindow_GetRelatedFrame 3473 -#define wxHtmlWindow_HistoryBack 3474 -#define wxHtmlWindow_HistoryCanBack 3475 -#define wxHtmlWindow_HistoryCanForward 3476 -#define wxHtmlWindow_HistoryClear 3477 -#define wxHtmlWindow_HistoryForward 3478 -#define wxHtmlWindow_LoadFile 3479 -#define wxHtmlWindow_LoadPage 3480 -#define wxHtmlWindow_SelectAll 3481 -#define wxHtmlWindow_SelectionToText 3482 -#define wxHtmlWindow_SelectLine 3483 -#define wxHtmlWindow_SelectWord 3484 -#define wxHtmlWindow_SetBorders 3485 -#define wxHtmlWindow_SetFonts 3486 -#define wxHtmlWindow_SetPage 3487 -#define wxHtmlWindow_SetRelatedFrame 3488 -#define wxHtmlWindow_SetRelatedStatusBar 3489 -#define wxHtmlWindow_ToText 3490 -#define wxHtmlWindow_destroy 3491 -#define wxHtmlLinkEvent_GetLinkInfo 3492 -#define wxSystemSettings_GetColour 3493 -#define wxSystemSettings_GetFont 3494 -#define wxSystemSettings_GetMetric 3495 -#define wxSystemSettings_GetScreenType 3496 -#define wxSystemOptions_GetOption 3497 -#define wxSystemOptions_GetOptionInt 3498 -#define wxSystemOptions_HasOption 3499 -#define wxSystemOptions_IsFalse 3500 -#define wxSystemOptions_SetOption_2_1 3501 -#define wxSystemOptions_SetOption_2_0 3502 -#define wxAuiNotebookEvent_SetSelection 3503 -#define wxAuiNotebookEvent_GetSelection 3504 -#define wxAuiNotebookEvent_SetOldSelection 3505 -#define wxAuiNotebookEvent_GetOldSelection 3506 -#define wxAuiNotebookEvent_SetDragSource 3507 -#define wxAuiNotebookEvent_GetDragSource 3508 -#define wxAuiManagerEvent_SetManager 3509 -#define wxAuiManagerEvent_GetManager 3510 -#define wxAuiManagerEvent_SetPane 3511 -#define wxAuiManagerEvent_GetPane 3512 -#define wxAuiManagerEvent_SetButton 3513 -#define wxAuiManagerEvent_GetButton 3514 -#define wxAuiManagerEvent_SetDC 3515 -#define wxAuiManagerEvent_GetDC 3516 -#define wxAuiManagerEvent_Veto 3517 -#define wxAuiManagerEvent_GetVeto 3518 -#define wxAuiManagerEvent_SetCanVeto 3519 -#define wxAuiManagerEvent_CanVeto 3520 -#define wxLogNull_new 3521 -#define wxLogNull_destroy 3522 -#define wxTaskBarIcon_new 3523 -#define wxTaskBarIcon_destruct 3524 -#define wxTaskBarIcon_PopupMenu 3525 -#define wxTaskBarIcon_RemoveIcon 3526 -#define wxTaskBarIcon_SetIcon 3527 -#define wxLocale_new_0 3528 -#define wxLocale_new_2 3530 -#define wxLocale_destruct 3531 -#define wxLocale_Init 3533 -#define wxLocale_AddCatalog_1 3534 -#define wxLocale_AddCatalog_3 3535 -#define wxLocale_AddCatalogLookupPathPrefix 3536 -#define wxLocale_GetCanonicalName 3537 -#define wxLocale_GetLanguage 3538 -#define wxLocale_GetLanguageName 3539 -#define wxLocale_GetLocale 3540 -#define wxLocale_GetName 3541 -#define wxLocale_GetString_2 3542 -#define wxLocale_GetString_4 3543 -#define wxLocale_GetHeaderValue 3544 -#define wxLocale_GetSysName 3545 -#define wxLocale_GetSystemEncoding 3546 -#define wxLocale_GetSystemEncodingName 3547 -#define wxLocale_GetSystemLanguage 3548 -#define wxLocale_IsLoaded 3549 -#define wxLocale_IsOk 3550 -#define wxActivateEvent_GetActive 3551 -#define wxPopupWindow_new_2 3553 -#define wxPopupWindow_new_0 3554 -#define wxPopupWindow_destruct 3556 -#define wxPopupWindow_Create 3557 -#define wxPopupWindow_Position 3558 -#define wxPopupTransientWindow_new_0 3559 -#define wxPopupTransientWindow_new_2 3560 -#define wxPopupTransientWindow_destruct 3561 -#define wxPopupTransientWindow_Popup 3562 -#define wxPopupTransientWindow_Dismiss 3563 +#define wxAuiTabArt_SetFlags 2675 +#define wxAuiTabArt_SetMeasuringFont 2676 +#define wxAuiTabArt_SetNormalFont 2677 +#define wxAuiTabArt_SetSelectedFont 2678 +#define wxAuiTabArt_SetColour 2679 +#define wxAuiTabArt_SetActiveColour 2680 +#define wxAuiDockArt_GetColour 2681 +#define wxAuiDockArt_GetFont 2682 +#define wxAuiDockArt_GetMetric 2683 +#define wxAuiDockArt_SetColour 2684 +#define wxAuiDockArt_SetFont 2685 +#define wxAuiDockArt_SetMetric 2686 +#define wxAuiSimpleTabArt_new 2687 +#define wxAuiSimpleTabArt_destroy 2688 +#define wxMDIParentFrame_new_0 2689 +#define wxMDIParentFrame_new_4 2690 +#define wxMDIParentFrame_destruct 2691 +#define wxMDIParentFrame_ActivateNext 2692 +#define wxMDIParentFrame_ActivatePrevious 2693 +#define wxMDIParentFrame_ArrangeIcons 2694 +#define wxMDIParentFrame_Cascade 2695 +#define wxMDIParentFrame_Create 2696 +#define wxMDIParentFrame_GetActiveChild 2697 +#define wxMDIParentFrame_GetClientWindow 2698 +#define wxMDIParentFrame_Tile 2699 +#define wxMDIChildFrame_new_0 2700 +#define wxMDIChildFrame_new_4 2701 +#define wxMDIChildFrame_destruct 2702 +#define wxMDIChildFrame_Activate 2703 +#define wxMDIChildFrame_Create 2704 +#define wxMDIChildFrame_Maximize 2705 +#define wxMDIChildFrame_Restore 2706 +#define wxMDIClientWindow_new_0 2707 +#define wxMDIClientWindow_new_2 2708 +#define wxMDIClientWindow_destruct 2709 +#define wxMDIClientWindow_CreateClient 2710 +#define wxLayoutAlgorithm_new 2711 +#define wxLayoutAlgorithm_LayoutFrame 2712 +#define wxLayoutAlgorithm_LayoutMDIFrame 2713 +#define wxLayoutAlgorithm_LayoutWindow 2714 +#define wxLayoutAlgorithm_destroy 2715 +#define wxEvent_GetId 2716 +#define wxEvent_GetSkipped 2717 +#define wxEvent_GetTimestamp 2718 +#define wxEvent_IsCommandEvent 2719 +#define wxEvent_ResumePropagation 2720 +#define wxEvent_ShouldPropagate 2721 +#define wxEvent_Skip 2722 +#define wxEvent_StopPropagation 2723 +#define wxCommandEvent_getClientData 2724 +#define wxCommandEvent_GetExtraLong 2725 +#define wxCommandEvent_GetInt 2726 +#define wxCommandEvent_GetSelection 2727 +#define wxCommandEvent_GetString 2728 +#define wxCommandEvent_IsChecked 2729 +#define wxCommandEvent_IsSelection 2730 +#define wxCommandEvent_SetInt 2731 +#define wxCommandEvent_SetString 2732 +#define wxScrollEvent_GetOrientation 2733 +#define wxScrollEvent_GetPosition 2734 +#define wxScrollWinEvent_GetOrientation 2735 +#define wxScrollWinEvent_GetPosition 2736 +#define wxMouseEvent_AltDown 2737 +#define wxMouseEvent_Button 2738 +#define wxMouseEvent_ButtonDClick 2739 +#define wxMouseEvent_ButtonDown 2740 +#define wxMouseEvent_ButtonUp 2741 +#define wxMouseEvent_CmdDown 2742 +#define wxMouseEvent_ControlDown 2743 +#define wxMouseEvent_Dragging 2744 +#define wxMouseEvent_Entering 2745 +#define wxMouseEvent_GetButton 2746 +#define wxMouseEvent_GetPosition 2749 +#define wxMouseEvent_GetLogicalPosition 2750 +#define wxMouseEvent_GetLinesPerAction 2751 +#define wxMouseEvent_GetWheelRotation 2752 +#define wxMouseEvent_GetWheelDelta 2753 +#define wxMouseEvent_GetX 2754 +#define wxMouseEvent_GetY 2755 +#define wxMouseEvent_IsButton 2756 +#define wxMouseEvent_IsPageScroll 2757 +#define wxMouseEvent_Leaving 2758 +#define wxMouseEvent_LeftDClick 2759 +#define wxMouseEvent_LeftDown 2760 +#define wxMouseEvent_LeftIsDown 2761 +#define wxMouseEvent_LeftUp 2762 +#define wxMouseEvent_MetaDown 2763 +#define wxMouseEvent_MiddleDClick 2764 +#define wxMouseEvent_MiddleDown 2765 +#define wxMouseEvent_MiddleIsDown 2766 +#define wxMouseEvent_MiddleUp 2767 +#define wxMouseEvent_Moving 2768 +#define wxMouseEvent_RightDClick 2769 +#define wxMouseEvent_RightDown 2770 +#define wxMouseEvent_RightIsDown 2771 +#define wxMouseEvent_RightUp 2772 +#define wxMouseEvent_ShiftDown 2773 +#define wxSetCursorEvent_GetCursor 2774 +#define wxSetCursorEvent_GetX 2775 +#define wxSetCursorEvent_GetY 2776 +#define wxSetCursorEvent_HasCursor 2777 +#define wxSetCursorEvent_SetCursor 2778 +#define wxKeyEvent_AltDown 2779 +#define wxKeyEvent_CmdDown 2780 +#define wxKeyEvent_ControlDown 2781 +#define wxKeyEvent_GetKeyCode 2782 +#define wxKeyEvent_GetModifiers 2783 +#define wxKeyEvent_GetPosition 2786 +#define wxKeyEvent_GetRawKeyCode 2787 +#define wxKeyEvent_GetRawKeyFlags 2788 +#define wxKeyEvent_GetUnicodeKey 2789 +#define wxKeyEvent_GetX 2790 +#define wxKeyEvent_GetY 2791 +#define wxKeyEvent_HasModifiers 2792 +#define wxKeyEvent_MetaDown 2793 +#define wxKeyEvent_ShiftDown 2794 +#define wxSizeEvent_GetSize 2795 +#define wxMoveEvent_GetPosition 2796 +#define wxEraseEvent_GetDC 2797 +#define wxFocusEvent_GetWindow 2798 +#define wxChildFocusEvent_GetWindow 2799 +#define wxMenuEvent_GetMenu 2800 +#define wxMenuEvent_GetMenuId 2801 +#define wxMenuEvent_IsPopup 2802 +#define wxCloseEvent_CanVeto 2803 +#define wxCloseEvent_GetLoggingOff 2804 +#define wxCloseEvent_SetCanVeto 2805 +#define wxCloseEvent_SetLoggingOff 2806 +#define wxCloseEvent_Veto 2807 +#define wxShowEvent_SetShow 2808 +#define wxShowEvent_GetShow 2809 +#define wxIconizeEvent_Iconized 2810 +#define wxJoystickEvent_ButtonDown 2811 +#define wxJoystickEvent_ButtonIsDown 2812 +#define wxJoystickEvent_ButtonUp 2813 +#define wxJoystickEvent_GetButtonChange 2814 +#define wxJoystickEvent_GetButtonState 2815 +#define wxJoystickEvent_GetJoystick 2816 +#define wxJoystickEvent_GetPosition 2817 +#define wxJoystickEvent_GetZPosition 2818 +#define wxJoystickEvent_IsButton 2819 +#define wxJoystickEvent_IsMove 2820 +#define wxJoystickEvent_IsZMove 2821 +#define wxUpdateUIEvent_CanUpdate 2822 +#define wxUpdateUIEvent_Check 2823 +#define wxUpdateUIEvent_Enable 2824 +#define wxUpdateUIEvent_Show 2825 +#define wxUpdateUIEvent_GetChecked 2826 +#define wxUpdateUIEvent_GetEnabled 2827 +#define wxUpdateUIEvent_GetShown 2828 +#define wxUpdateUIEvent_GetSetChecked 2829 +#define wxUpdateUIEvent_GetSetEnabled 2830 +#define wxUpdateUIEvent_GetSetShown 2831 +#define wxUpdateUIEvent_GetSetText 2832 +#define wxUpdateUIEvent_GetText 2833 +#define wxUpdateUIEvent_GetMode 2834 +#define wxUpdateUIEvent_GetUpdateInterval 2835 +#define wxUpdateUIEvent_ResetUpdateTime 2836 +#define wxUpdateUIEvent_SetMode 2837 +#define wxUpdateUIEvent_SetText 2838 +#define wxUpdateUIEvent_SetUpdateInterval 2839 +#define wxMouseCaptureChangedEvent_GetCapturedWindow 2840 +#define wxPaletteChangedEvent_SetChangedWindow 2841 +#define wxPaletteChangedEvent_GetChangedWindow 2842 +#define wxQueryNewPaletteEvent_SetPaletteRealized 2843 +#define wxQueryNewPaletteEvent_GetPaletteRealized 2844 +#define wxNavigationKeyEvent_GetDirection 2845 +#define wxNavigationKeyEvent_SetDirection 2846 +#define wxNavigationKeyEvent_IsWindowChange 2847 +#define wxNavigationKeyEvent_SetWindowChange 2848 +#define wxNavigationKeyEvent_IsFromTab 2849 +#define wxNavigationKeyEvent_SetFromTab 2850 +#define wxNavigationKeyEvent_GetCurrentFocus 2851 +#define wxNavigationKeyEvent_SetCurrentFocus 2852 +#define wxHelpEvent_GetOrigin 2853 +#define wxHelpEvent_GetPosition 2854 +#define wxHelpEvent_SetOrigin 2855 +#define wxHelpEvent_SetPosition 2856 +#define wxContextMenuEvent_GetPosition 2857 +#define wxContextMenuEvent_SetPosition 2858 +#define wxIdleEvent_CanSend 2859 +#define wxIdleEvent_GetMode 2860 +#define wxIdleEvent_RequestMore 2861 +#define wxIdleEvent_MoreRequested 2862 +#define wxIdleEvent_SetMode 2863 +#define wxGridEvent_AltDown 2864 +#define wxGridEvent_ControlDown 2865 +#define wxGridEvent_GetCol 2866 +#define wxGridEvent_GetPosition 2867 +#define wxGridEvent_GetRow 2868 +#define wxGridEvent_MetaDown 2869 +#define wxGridEvent_Selecting 2870 +#define wxGridEvent_ShiftDown 2871 +#define wxNotifyEvent_Allow 2872 +#define wxNotifyEvent_IsAllowed 2873 +#define wxNotifyEvent_Veto 2874 +#define wxSashEvent_GetEdge 2875 +#define wxSashEvent_GetDragRect 2876 +#define wxSashEvent_GetDragStatus 2877 +#define wxListEvent_GetCacheFrom 2878 +#define wxListEvent_GetCacheTo 2879 +#define wxListEvent_GetKeyCode 2880 +#define wxListEvent_GetIndex 2881 +#define wxListEvent_GetColumn 2882 +#define wxListEvent_GetPoint 2883 +#define wxListEvent_GetLabel 2884 +#define wxListEvent_GetText 2885 +#define wxListEvent_GetImage 2886 +#define wxListEvent_GetData 2887 +#define wxListEvent_GetMask 2888 +#define wxListEvent_GetItem 2889 +#define wxListEvent_IsEditCancelled 2890 +#define wxDateEvent_GetDate 2891 +#define wxCalendarEvent_GetWeekDay 2892 +#define wxFileDirPickerEvent_GetPath 2893 +#define wxColourPickerEvent_GetColour 2894 +#define wxFontPickerEvent_GetFont 2895 +#define wxStyledTextEvent_GetPosition 2896 +#define wxStyledTextEvent_GetKey 2897 +#define wxStyledTextEvent_GetModifiers 2898 +#define wxStyledTextEvent_GetModificationType 2899 +#define wxStyledTextEvent_GetText 2900 +#define wxStyledTextEvent_GetLength 2901 +#define wxStyledTextEvent_GetLinesAdded 2902 +#define wxStyledTextEvent_GetLine 2903 +#define wxStyledTextEvent_GetFoldLevelNow 2904 +#define wxStyledTextEvent_GetFoldLevelPrev 2905 +#define wxStyledTextEvent_GetMargin 2906 +#define wxStyledTextEvent_GetMessage 2907 +#define wxStyledTextEvent_GetWParam 2908 +#define wxStyledTextEvent_GetLParam 2909 +#define wxStyledTextEvent_GetListType 2910 +#define wxStyledTextEvent_GetX 2911 +#define wxStyledTextEvent_GetY 2912 +#define wxStyledTextEvent_GetDragText 2913 +#define wxStyledTextEvent_GetDragAllowMove 2914 +#define wxStyledTextEvent_GetDragResult 2915 +#define wxStyledTextEvent_GetShift 2916 +#define wxStyledTextEvent_GetControl 2917 +#define wxStyledTextEvent_GetAlt 2918 +#define utils_wxGetKeyState 2919 +#define utils_wxGetMousePosition 2920 +#define utils_wxGetMouseState 2921 +#define utils_wxSetDetectableAutoRepeat 2922 +#define utils_wxBell 2923 +#define utils_wxFindMenuItemId 2924 +#define utils_wxGenericFindWindowAtPoint 2925 +#define utils_wxFindWindowAtPoint 2926 +#define utils_wxBeginBusyCursor 2927 +#define utils_wxEndBusyCursor 2928 +#define utils_wxIsBusy 2929 +#define utils_wxShutdown 2930 +#define utils_wxShell 2931 +#define utils_wxLaunchDefaultBrowser 2932 +#define utils_wxGetEmailAddress 2933 +#define utils_wxGetUserId 2934 +#define utils_wxGetHomeDir 2935 +#define utils_wxNewId 2936 +#define utils_wxRegisterId 2937 +#define utils_wxGetCurrentId 2938 +#define utils_wxGetOsDescription 2939 +#define utils_wxIsPlatformLittleEndian 2940 +#define utils_wxIsPlatform64Bit 2941 +#define gdicmn_wxDisplaySize 2942 +#define gdicmn_wxSetCursor 2943 +#define wxPrintout_new 2944 +#define wxPrintout_destruct 2945 +#define wxPrintout_GetDC 2946 +#define wxPrintout_GetPageSizeMM 2947 +#define wxPrintout_GetPageSizePixels 2948 +#define wxPrintout_GetPaperRectPixels 2949 +#define wxPrintout_GetPPIPrinter 2950 +#define wxPrintout_GetPPIScreen 2951 +#define wxPrintout_GetTitle 2952 +#define wxPrintout_IsPreview 2953 +#define wxPrintout_FitThisSizeToPaper 2954 +#define wxPrintout_FitThisSizeToPage 2955 +#define wxPrintout_FitThisSizeToPageMargins 2956 +#define wxPrintout_MapScreenSizeToPaper 2957 +#define wxPrintout_MapScreenSizeToPage 2958 +#define wxPrintout_MapScreenSizeToPageMargins 2959 +#define wxPrintout_MapScreenSizeToDevice 2960 +#define wxPrintout_GetLogicalPaperRect 2961 +#define wxPrintout_GetLogicalPageRect 2962 +#define wxPrintout_GetLogicalPageMarginsRect 2963 +#define wxPrintout_SetLogicalOrigin 2964 +#define wxPrintout_OffsetLogicalOrigin 2965 +#define wxStyledTextCtrl_new_2 2966 +#define wxStyledTextCtrl_new_0 2967 +#define wxStyledTextCtrl_destruct 2968 +#define wxStyledTextCtrl_Create 2969 +#define wxStyledTextCtrl_AddText 2970 +#define wxStyledTextCtrl_AddStyledText 2971 +#define wxStyledTextCtrl_InsertText 2972 +#define wxStyledTextCtrl_ClearAll 2973 +#define wxStyledTextCtrl_ClearDocumentStyle 2974 +#define wxStyledTextCtrl_GetLength 2975 +#define wxStyledTextCtrl_GetCharAt 2976 +#define wxStyledTextCtrl_GetCurrentPos 2977 +#define wxStyledTextCtrl_GetAnchor 2978 +#define wxStyledTextCtrl_GetStyleAt 2979 +#define wxStyledTextCtrl_Redo 2980 +#define wxStyledTextCtrl_SetUndoCollection 2981 +#define wxStyledTextCtrl_SelectAll 2982 +#define wxStyledTextCtrl_SetSavePoint 2983 +#define wxStyledTextCtrl_GetStyledText 2984 +#define wxStyledTextCtrl_CanRedo 2985 +#define wxStyledTextCtrl_MarkerLineFromHandle 2986 +#define wxStyledTextCtrl_MarkerDeleteHandle 2987 +#define wxStyledTextCtrl_GetUndoCollection 2988 +#define wxStyledTextCtrl_GetViewWhiteSpace 2989 +#define wxStyledTextCtrl_SetViewWhiteSpace 2990 +#define wxStyledTextCtrl_PositionFromPoint 2991 +#define wxStyledTextCtrl_PositionFromPointClose 2992 +#define wxStyledTextCtrl_GotoLine 2993 +#define wxStyledTextCtrl_GotoPos 2994 +#define wxStyledTextCtrl_SetAnchor 2995 +#define wxStyledTextCtrl_GetCurLine 2996 +#define wxStyledTextCtrl_GetEndStyled 2997 +#define wxStyledTextCtrl_ConvertEOLs 2998 +#define wxStyledTextCtrl_GetEOLMode 2999 +#define wxStyledTextCtrl_SetEOLMode 3000 +#define wxStyledTextCtrl_StartStyling 3001 +#define wxStyledTextCtrl_SetStyling 3002 +#define wxStyledTextCtrl_GetBufferedDraw 3003 +#define wxStyledTextCtrl_SetBufferedDraw 3004 +#define wxStyledTextCtrl_SetTabWidth 3005 +#define wxStyledTextCtrl_GetTabWidth 3006 +#define wxStyledTextCtrl_SetCodePage 3007 +#define wxStyledTextCtrl_MarkerDefine 3008 +#define wxStyledTextCtrl_MarkerSetForeground 3009 +#define wxStyledTextCtrl_MarkerSetBackground 3010 +#define wxStyledTextCtrl_MarkerAdd 3011 +#define wxStyledTextCtrl_MarkerDelete 3012 +#define wxStyledTextCtrl_MarkerDeleteAll 3013 +#define wxStyledTextCtrl_MarkerGet 3014 +#define wxStyledTextCtrl_MarkerNext 3015 +#define wxStyledTextCtrl_MarkerPrevious 3016 +#define wxStyledTextCtrl_MarkerDefineBitmap 3017 +#define wxStyledTextCtrl_MarkerAddSet 3018 +#define wxStyledTextCtrl_MarkerSetAlpha 3019 +#define wxStyledTextCtrl_SetMarginType 3020 +#define wxStyledTextCtrl_GetMarginType 3021 +#define wxStyledTextCtrl_SetMarginWidth 3022 +#define wxStyledTextCtrl_GetMarginWidth 3023 +#define wxStyledTextCtrl_SetMarginMask 3024 +#define wxStyledTextCtrl_GetMarginMask 3025 +#define wxStyledTextCtrl_SetMarginSensitive 3026 +#define wxStyledTextCtrl_GetMarginSensitive 3027 +#define wxStyledTextCtrl_StyleClearAll 3028 +#define wxStyledTextCtrl_StyleSetForeground 3029 +#define wxStyledTextCtrl_StyleSetBackground 3030 +#define wxStyledTextCtrl_StyleSetBold 3031 +#define wxStyledTextCtrl_StyleSetItalic 3032 +#define wxStyledTextCtrl_StyleSetSize 3033 +#define wxStyledTextCtrl_StyleSetFaceName 3034 +#define wxStyledTextCtrl_StyleSetEOLFilled 3035 +#define wxStyledTextCtrl_StyleResetDefault 3036 +#define wxStyledTextCtrl_StyleSetUnderline 3037 +#define wxStyledTextCtrl_StyleSetCase 3038 +#define wxStyledTextCtrl_StyleSetHotSpot 3039 +#define wxStyledTextCtrl_SetSelForeground 3040 +#define wxStyledTextCtrl_SetSelBackground 3041 +#define wxStyledTextCtrl_GetSelAlpha 3042 +#define wxStyledTextCtrl_SetSelAlpha 3043 +#define wxStyledTextCtrl_SetCaretForeground 3044 +#define wxStyledTextCtrl_CmdKeyAssign 3045 +#define wxStyledTextCtrl_CmdKeyClear 3046 +#define wxStyledTextCtrl_CmdKeyClearAll 3047 +#define wxStyledTextCtrl_SetStyleBytes 3048 +#define wxStyledTextCtrl_StyleSetVisible 3049 +#define wxStyledTextCtrl_GetCaretPeriod 3050 +#define wxStyledTextCtrl_SetCaretPeriod 3051 +#define wxStyledTextCtrl_SetWordChars 3052 +#define wxStyledTextCtrl_BeginUndoAction 3053 +#define wxStyledTextCtrl_EndUndoAction 3054 +#define wxStyledTextCtrl_IndicatorSetStyle 3055 +#define wxStyledTextCtrl_IndicatorGetStyle 3056 +#define wxStyledTextCtrl_IndicatorSetForeground 3057 +#define wxStyledTextCtrl_IndicatorGetForeground 3058 +#define wxStyledTextCtrl_SetWhitespaceForeground 3059 +#define wxStyledTextCtrl_SetWhitespaceBackground 3060 +#define wxStyledTextCtrl_GetStyleBits 3061 +#define wxStyledTextCtrl_SetLineState 3062 +#define wxStyledTextCtrl_GetLineState 3063 +#define wxStyledTextCtrl_GetMaxLineState 3064 +#define wxStyledTextCtrl_GetCaretLineVisible 3065 +#define wxStyledTextCtrl_SetCaretLineVisible 3066 +#define wxStyledTextCtrl_GetCaretLineBackground 3067 +#define wxStyledTextCtrl_SetCaretLineBackground 3068 +#define wxStyledTextCtrl_AutoCompShow 3069 +#define wxStyledTextCtrl_AutoCompCancel 3070 +#define wxStyledTextCtrl_AutoCompActive 3071 +#define wxStyledTextCtrl_AutoCompPosStart 3072 +#define wxStyledTextCtrl_AutoCompComplete 3073 +#define wxStyledTextCtrl_AutoCompStops 3074 +#define wxStyledTextCtrl_AutoCompSetSeparator 3075 +#define wxStyledTextCtrl_AutoCompGetSeparator 3076 +#define wxStyledTextCtrl_AutoCompSelect 3077 +#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3078 +#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3079 +#define wxStyledTextCtrl_AutoCompSetFillUps 3080 +#define wxStyledTextCtrl_AutoCompSetChooseSingle 3081 +#define wxStyledTextCtrl_AutoCompGetChooseSingle 3082 +#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3083 +#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3084 +#define wxStyledTextCtrl_UserListShow 3085 +#define wxStyledTextCtrl_AutoCompSetAutoHide 3086 +#define wxStyledTextCtrl_AutoCompGetAutoHide 3087 +#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3088 +#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3089 +#define wxStyledTextCtrl_RegisterImage 3090 +#define wxStyledTextCtrl_ClearRegisteredImages 3091 +#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3092 +#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3093 +#define wxStyledTextCtrl_AutoCompSetMaxWidth 3094 +#define wxStyledTextCtrl_AutoCompGetMaxWidth 3095 +#define wxStyledTextCtrl_AutoCompSetMaxHeight 3096 +#define wxStyledTextCtrl_AutoCompGetMaxHeight 3097 +#define wxStyledTextCtrl_SetIndent 3098 +#define wxStyledTextCtrl_GetIndent 3099 +#define wxStyledTextCtrl_SetUseTabs 3100 +#define wxStyledTextCtrl_GetUseTabs 3101 +#define wxStyledTextCtrl_SetLineIndentation 3102 +#define wxStyledTextCtrl_GetLineIndentation 3103 +#define wxStyledTextCtrl_GetLineIndentPosition 3104 +#define wxStyledTextCtrl_GetColumn 3105 +#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3106 +#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3107 +#define wxStyledTextCtrl_SetIndentationGuides 3108 +#define wxStyledTextCtrl_GetIndentationGuides 3109 +#define wxStyledTextCtrl_SetHighlightGuide 3110 +#define wxStyledTextCtrl_GetHighlightGuide 3111 +#define wxStyledTextCtrl_GetLineEndPosition 3112 +#define wxStyledTextCtrl_GetCodePage 3113 +#define wxStyledTextCtrl_GetCaretForeground 3114 +#define wxStyledTextCtrl_GetReadOnly 3115 +#define wxStyledTextCtrl_SetCurrentPos 3116 +#define wxStyledTextCtrl_SetSelectionStart 3117 +#define wxStyledTextCtrl_GetSelectionStart 3118 +#define wxStyledTextCtrl_SetSelectionEnd 3119 +#define wxStyledTextCtrl_GetSelectionEnd 3120 +#define wxStyledTextCtrl_SetPrintMagnification 3121 +#define wxStyledTextCtrl_GetPrintMagnification 3122 +#define wxStyledTextCtrl_SetPrintColourMode 3123 +#define wxStyledTextCtrl_GetPrintColourMode 3124 +#define wxStyledTextCtrl_FindText 3125 +#define wxStyledTextCtrl_FormatRange 3126 +#define wxStyledTextCtrl_GetFirstVisibleLine 3127 +#define wxStyledTextCtrl_GetLine 3128 +#define wxStyledTextCtrl_GetLineCount 3129 +#define wxStyledTextCtrl_SetMarginLeft 3130 +#define wxStyledTextCtrl_GetMarginLeft 3131 +#define wxStyledTextCtrl_SetMarginRight 3132 +#define wxStyledTextCtrl_GetMarginRight 3133 +#define wxStyledTextCtrl_GetModify 3134 +#define wxStyledTextCtrl_SetSelection 3135 +#define wxStyledTextCtrl_GetSelectedText 3136 +#define wxStyledTextCtrl_GetTextRange 3137 +#define wxStyledTextCtrl_HideSelection 3138 +#define wxStyledTextCtrl_LineFromPosition 3139 +#define wxStyledTextCtrl_PositionFromLine 3140 +#define wxStyledTextCtrl_LineScroll 3141 +#define wxStyledTextCtrl_EnsureCaretVisible 3142 +#define wxStyledTextCtrl_ReplaceSelection 3143 +#define wxStyledTextCtrl_SetReadOnly 3144 +#define wxStyledTextCtrl_CanPaste 3145 +#define wxStyledTextCtrl_CanUndo 3146 +#define wxStyledTextCtrl_EmptyUndoBuffer 3147 +#define wxStyledTextCtrl_Undo 3148 +#define wxStyledTextCtrl_Cut 3149 +#define wxStyledTextCtrl_Copy 3150 +#define wxStyledTextCtrl_Paste 3151 +#define wxStyledTextCtrl_Clear 3152 +#define wxStyledTextCtrl_SetText 3153 +#define wxStyledTextCtrl_GetText 3154 +#define wxStyledTextCtrl_GetTextLength 3155 +#define wxStyledTextCtrl_GetOvertype 3156 +#define wxStyledTextCtrl_SetCaretWidth 3157 +#define wxStyledTextCtrl_GetCaretWidth 3158 +#define wxStyledTextCtrl_SetTargetStart 3159 +#define wxStyledTextCtrl_GetTargetStart 3160 +#define wxStyledTextCtrl_SetTargetEnd 3161 +#define wxStyledTextCtrl_GetTargetEnd 3162 +#define wxStyledTextCtrl_ReplaceTarget 3163 +#define wxStyledTextCtrl_SearchInTarget 3164 +#define wxStyledTextCtrl_SetSearchFlags 3165 +#define wxStyledTextCtrl_GetSearchFlags 3166 +#define wxStyledTextCtrl_CallTipShow 3167 +#define wxStyledTextCtrl_CallTipCancel 3168 +#define wxStyledTextCtrl_CallTipActive 3169 +#define wxStyledTextCtrl_CallTipPosAtStart 3170 +#define wxStyledTextCtrl_CallTipSetHighlight 3171 +#define wxStyledTextCtrl_CallTipSetBackground 3172 +#define wxStyledTextCtrl_CallTipSetForeground 3173 +#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3174 +#define wxStyledTextCtrl_CallTipUseStyle 3175 +#define wxStyledTextCtrl_VisibleFromDocLine 3176 +#define wxStyledTextCtrl_DocLineFromVisible 3177 +#define wxStyledTextCtrl_WrapCount 3178 +#define wxStyledTextCtrl_SetFoldLevel 3179 +#define wxStyledTextCtrl_GetFoldLevel 3180 +#define wxStyledTextCtrl_GetLastChild 3181 +#define wxStyledTextCtrl_GetFoldParent 3182 +#define wxStyledTextCtrl_ShowLines 3183 +#define wxStyledTextCtrl_HideLines 3184 +#define wxStyledTextCtrl_GetLineVisible 3185 +#define wxStyledTextCtrl_SetFoldExpanded 3186 +#define wxStyledTextCtrl_GetFoldExpanded 3187 +#define wxStyledTextCtrl_ToggleFold 3188 +#define wxStyledTextCtrl_EnsureVisible 3189 +#define wxStyledTextCtrl_SetFoldFlags 3190 +#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3191 +#define wxStyledTextCtrl_SetTabIndents 3192 +#define wxStyledTextCtrl_GetTabIndents 3193 +#define wxStyledTextCtrl_SetBackSpaceUnIndents 3194 +#define wxStyledTextCtrl_GetBackSpaceUnIndents 3195 +#define wxStyledTextCtrl_SetMouseDwellTime 3196 +#define wxStyledTextCtrl_GetMouseDwellTime 3197 +#define wxStyledTextCtrl_WordStartPosition 3198 +#define wxStyledTextCtrl_WordEndPosition 3199 +#define wxStyledTextCtrl_SetWrapMode 3200 +#define wxStyledTextCtrl_GetWrapMode 3201 +#define wxStyledTextCtrl_SetWrapVisualFlags 3202 +#define wxStyledTextCtrl_GetWrapVisualFlags 3203 +#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3204 +#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3205 +#define wxStyledTextCtrl_SetWrapStartIndent 3206 +#define wxStyledTextCtrl_GetWrapStartIndent 3207 +#define wxStyledTextCtrl_SetLayoutCache 3208 +#define wxStyledTextCtrl_GetLayoutCache 3209 +#define wxStyledTextCtrl_SetScrollWidth 3210 +#define wxStyledTextCtrl_GetScrollWidth 3211 +#define wxStyledTextCtrl_TextWidth 3212 +#define wxStyledTextCtrl_GetEndAtLastLine 3213 +#define wxStyledTextCtrl_TextHeight 3214 +#define wxStyledTextCtrl_SetUseVerticalScrollBar 3215 +#define wxStyledTextCtrl_GetUseVerticalScrollBar 3216 +#define wxStyledTextCtrl_AppendText 3217 +#define wxStyledTextCtrl_GetTwoPhaseDraw 3218 +#define wxStyledTextCtrl_SetTwoPhaseDraw 3219 +#define wxStyledTextCtrl_TargetFromSelection 3220 +#define wxStyledTextCtrl_LinesJoin 3221 +#define wxStyledTextCtrl_LinesSplit 3222 +#define wxStyledTextCtrl_SetFoldMarginColour 3223 +#define wxStyledTextCtrl_SetFoldMarginHiColour 3224 +#define wxStyledTextCtrl_LineDown 3225 +#define wxStyledTextCtrl_LineDownExtend 3226 +#define wxStyledTextCtrl_LineUp 3227 +#define wxStyledTextCtrl_LineUpExtend 3228 +#define wxStyledTextCtrl_CharLeft 3229 +#define wxStyledTextCtrl_CharLeftExtend 3230 +#define wxStyledTextCtrl_CharRight 3231 +#define wxStyledTextCtrl_CharRightExtend 3232 +#define wxStyledTextCtrl_WordLeft 3233 +#define wxStyledTextCtrl_WordLeftExtend 3234 +#define wxStyledTextCtrl_WordRight 3235 +#define wxStyledTextCtrl_WordRightExtend 3236 +#define wxStyledTextCtrl_Home 3237 +#define wxStyledTextCtrl_HomeExtend 3238 +#define wxStyledTextCtrl_LineEnd 3239 +#define wxStyledTextCtrl_LineEndExtend 3240 +#define wxStyledTextCtrl_DocumentStart 3241 +#define wxStyledTextCtrl_DocumentStartExtend 3242 +#define wxStyledTextCtrl_DocumentEnd 3243 +#define wxStyledTextCtrl_DocumentEndExtend 3244 +#define wxStyledTextCtrl_PageUp 3245 +#define wxStyledTextCtrl_PageUpExtend 3246 +#define wxStyledTextCtrl_PageDown 3247 +#define wxStyledTextCtrl_PageDownExtend 3248 +#define wxStyledTextCtrl_EditToggleOvertype 3249 +#define wxStyledTextCtrl_Cancel 3250 +#define wxStyledTextCtrl_DeleteBack 3251 +#define wxStyledTextCtrl_Tab 3252 +#define wxStyledTextCtrl_BackTab 3253 +#define wxStyledTextCtrl_NewLine 3254 +#define wxStyledTextCtrl_FormFeed 3255 +#define wxStyledTextCtrl_VCHome 3256 +#define wxStyledTextCtrl_VCHomeExtend 3257 +#define wxStyledTextCtrl_ZoomIn 3258 +#define wxStyledTextCtrl_ZoomOut 3259 +#define wxStyledTextCtrl_DelWordLeft 3260 +#define wxStyledTextCtrl_DelWordRight 3261 +#define wxStyledTextCtrl_LineCut 3262 +#define wxStyledTextCtrl_LineDelete 3263 +#define wxStyledTextCtrl_LineTranspose 3264 +#define wxStyledTextCtrl_LineDuplicate 3265 +#define wxStyledTextCtrl_LowerCase 3266 +#define wxStyledTextCtrl_UpperCase 3267 +#define wxStyledTextCtrl_LineScrollDown 3268 +#define wxStyledTextCtrl_LineScrollUp 3269 +#define wxStyledTextCtrl_DeleteBackNotLine 3270 +#define wxStyledTextCtrl_HomeDisplay 3271 +#define wxStyledTextCtrl_HomeDisplayExtend 3272 +#define wxStyledTextCtrl_LineEndDisplay 3273 +#define wxStyledTextCtrl_LineEndDisplayExtend 3274 +#define wxStyledTextCtrl_HomeWrapExtend 3275 +#define wxStyledTextCtrl_LineEndWrap 3276 +#define wxStyledTextCtrl_LineEndWrapExtend 3277 +#define wxStyledTextCtrl_VCHomeWrap 3278 +#define wxStyledTextCtrl_VCHomeWrapExtend 3279 +#define wxStyledTextCtrl_LineCopy 3280 +#define wxStyledTextCtrl_MoveCaretInsideView 3281 +#define wxStyledTextCtrl_LineLength 3282 +#define wxStyledTextCtrl_BraceHighlight 3283 +#define wxStyledTextCtrl_BraceBadLight 3284 +#define wxStyledTextCtrl_BraceMatch 3285 +#define wxStyledTextCtrl_GetViewEOL 3286 +#define wxStyledTextCtrl_SetViewEOL 3287 +#define wxStyledTextCtrl_SetModEventMask 3288 +#define wxStyledTextCtrl_GetEdgeColumn 3289 +#define wxStyledTextCtrl_SetEdgeColumn 3290 +#define wxStyledTextCtrl_SetEdgeMode 3291 +#define wxStyledTextCtrl_GetEdgeMode 3292 +#define wxStyledTextCtrl_GetEdgeColour 3293 +#define wxStyledTextCtrl_SetEdgeColour 3294 +#define wxStyledTextCtrl_SearchAnchor 3295 +#define wxStyledTextCtrl_SearchNext 3296 +#define wxStyledTextCtrl_SearchPrev 3297 +#define wxStyledTextCtrl_LinesOnScreen 3298 +#define wxStyledTextCtrl_UsePopUp 3299 +#define wxStyledTextCtrl_SelectionIsRectangle 3300 +#define wxStyledTextCtrl_SetZoom 3301 +#define wxStyledTextCtrl_GetZoom 3302 +#define wxStyledTextCtrl_GetModEventMask 3303 +#define wxStyledTextCtrl_SetSTCFocus 3304 +#define wxStyledTextCtrl_GetSTCFocus 3305 +#define wxStyledTextCtrl_SetStatus 3306 +#define wxStyledTextCtrl_GetStatus 3307 +#define wxStyledTextCtrl_SetMouseDownCaptures 3308 +#define wxStyledTextCtrl_GetMouseDownCaptures 3309 +#define wxStyledTextCtrl_SetSTCCursor 3310 +#define wxStyledTextCtrl_GetSTCCursor 3311 +#define wxStyledTextCtrl_SetControlCharSymbol 3312 +#define wxStyledTextCtrl_GetControlCharSymbol 3313 +#define wxStyledTextCtrl_WordPartLeft 3314 +#define wxStyledTextCtrl_WordPartLeftExtend 3315 +#define wxStyledTextCtrl_WordPartRight 3316 +#define wxStyledTextCtrl_WordPartRightExtend 3317 +#define wxStyledTextCtrl_SetVisiblePolicy 3318 +#define wxStyledTextCtrl_DelLineLeft 3319 +#define wxStyledTextCtrl_DelLineRight 3320 +#define wxStyledTextCtrl_GetXOffset 3321 +#define wxStyledTextCtrl_ChooseCaretX 3322 +#define wxStyledTextCtrl_SetXCaretPolicy 3323 +#define wxStyledTextCtrl_SetYCaretPolicy 3324 +#define wxStyledTextCtrl_GetPrintWrapMode 3325 +#define wxStyledTextCtrl_SetHotspotActiveForeground 3326 +#define wxStyledTextCtrl_SetHotspotActiveBackground 3327 +#define wxStyledTextCtrl_SetHotspotActiveUnderline 3328 +#define wxStyledTextCtrl_SetHotspotSingleLine 3329 +#define wxStyledTextCtrl_ParaDownExtend 3330 +#define wxStyledTextCtrl_ParaUp 3331 +#define wxStyledTextCtrl_ParaUpExtend 3332 +#define wxStyledTextCtrl_PositionBefore 3333 +#define wxStyledTextCtrl_PositionAfter 3334 +#define wxStyledTextCtrl_CopyRange 3335 +#define wxStyledTextCtrl_CopyText 3336 +#define wxStyledTextCtrl_SetSelectionMode 3337 +#define wxStyledTextCtrl_GetSelectionMode 3338 +#define wxStyledTextCtrl_LineDownRectExtend 3339 +#define wxStyledTextCtrl_LineUpRectExtend 3340 +#define wxStyledTextCtrl_CharLeftRectExtend 3341 +#define wxStyledTextCtrl_CharRightRectExtend 3342 +#define wxStyledTextCtrl_HomeRectExtend 3343 +#define wxStyledTextCtrl_VCHomeRectExtend 3344 +#define wxStyledTextCtrl_LineEndRectExtend 3345 +#define wxStyledTextCtrl_PageUpRectExtend 3346 +#define wxStyledTextCtrl_PageDownRectExtend 3347 +#define wxStyledTextCtrl_StutteredPageUp 3348 +#define wxStyledTextCtrl_StutteredPageUpExtend 3349 +#define wxStyledTextCtrl_StutteredPageDown 3350 +#define wxStyledTextCtrl_StutteredPageDownExtend 3351 +#define wxStyledTextCtrl_WordLeftEnd 3352 +#define wxStyledTextCtrl_WordLeftEndExtend 3353 +#define wxStyledTextCtrl_WordRightEnd 3354 +#define wxStyledTextCtrl_WordRightEndExtend 3355 +#define wxStyledTextCtrl_SetWhitespaceChars 3356 +#define wxStyledTextCtrl_SetCharsDefault 3357 +#define wxStyledTextCtrl_AutoCompGetCurrent 3358 +#define wxStyledTextCtrl_Allocate 3359 +#define wxStyledTextCtrl_FindColumn 3360 +#define wxStyledTextCtrl_GetCaretSticky 3361 +#define wxStyledTextCtrl_SetCaretSticky 3362 +#define wxStyledTextCtrl_ToggleCaretSticky 3363 +#define wxStyledTextCtrl_SetPasteConvertEndings 3364 +#define wxStyledTextCtrl_GetPasteConvertEndings 3365 +#define wxStyledTextCtrl_SelectionDuplicate 3366 +#define wxStyledTextCtrl_SetCaretLineBackAlpha 3367 +#define wxStyledTextCtrl_GetCaretLineBackAlpha 3368 +#define wxStyledTextCtrl_StartRecord 3369 +#define wxStyledTextCtrl_StopRecord 3370 +#define wxStyledTextCtrl_SetLexer 3371 +#define wxStyledTextCtrl_GetLexer 3372 +#define wxStyledTextCtrl_Colourise 3373 +#define wxStyledTextCtrl_SetProperty 3374 +#define wxStyledTextCtrl_SetKeyWords 3375 +#define wxStyledTextCtrl_SetLexerLanguage 3376 +#define wxStyledTextCtrl_GetProperty 3377 +#define wxStyledTextCtrl_GetStyleBitsNeeded 3378 +#define wxStyledTextCtrl_GetCurrentLine 3379 +#define wxStyledTextCtrl_StyleSetSpec 3380 +#define wxStyledTextCtrl_StyleSetFont 3381 +#define wxStyledTextCtrl_StyleSetFontAttr 3382 +#define wxStyledTextCtrl_StyleSetCharacterSet 3383 +#define wxStyledTextCtrl_StyleSetFontEncoding 3384 +#define wxStyledTextCtrl_CmdKeyExecute 3385 +#define wxStyledTextCtrl_SetMargins 3386 +#define wxStyledTextCtrl_GetSelection 3387 +#define wxStyledTextCtrl_PointFromPosition 3388 +#define wxStyledTextCtrl_ScrollToLine 3389 +#define wxStyledTextCtrl_ScrollToColumn 3390 +#define wxStyledTextCtrl_SetVScrollBar 3391 +#define wxStyledTextCtrl_SetHScrollBar 3392 +#define wxStyledTextCtrl_GetLastKeydownProcessed 3393 +#define wxStyledTextCtrl_SetLastKeydownProcessed 3394 +#define wxStyledTextCtrl_SaveFile 3395 +#define wxStyledTextCtrl_LoadFile 3396 +#define wxStyledTextCtrl_DoDragOver 3397 +#define wxStyledTextCtrl_DoDropText 3398 +#define wxStyledTextCtrl_GetUseAntiAliasing 3399 +#define wxStyledTextCtrl_AddTextRaw 3400 +#define wxStyledTextCtrl_InsertTextRaw 3401 +#define wxStyledTextCtrl_GetCurLineRaw 3402 +#define wxStyledTextCtrl_GetLineRaw 3403 +#define wxStyledTextCtrl_GetSelectedTextRaw 3404 +#define wxStyledTextCtrl_GetTextRangeRaw 3405 +#define wxStyledTextCtrl_SetTextRaw 3406 +#define wxStyledTextCtrl_GetTextRaw 3407 +#define wxStyledTextCtrl_AppendTextRaw 3408 +#define wxArtProvider_GetBitmap 3409 +#define wxArtProvider_GetIcon 3410 +#define wxTreeEvent_GetKeyCode 3411 +#define wxTreeEvent_GetItem 3412 +#define wxTreeEvent_GetKeyEvent 3413 +#define wxTreeEvent_GetLabel 3414 +#define wxTreeEvent_GetOldItem 3415 +#define wxTreeEvent_GetPoint 3416 +#define wxTreeEvent_IsEditCancelled 3417 +#define wxTreeEvent_SetToolTip 3418 +#define wxNotebookEvent_GetOldSelection 3419 +#define wxNotebookEvent_GetSelection 3420 +#define wxNotebookEvent_SetOldSelection 3421 +#define wxNotebookEvent_SetSelection 3422 +#define wxFileDataObject_new 3423 +#define wxFileDataObject_AddFile 3424 +#define wxFileDataObject_GetFilenames 3425 +#define wxFileDataObject_destroy 3426 +#define wxTextDataObject_new 3427 +#define wxTextDataObject_GetTextLength 3428 +#define wxTextDataObject_GetText 3429 +#define wxTextDataObject_SetText 3430 +#define wxTextDataObject_destroy 3431 +#define wxBitmapDataObject_new_1_1 3432 +#define wxBitmapDataObject_new_1_0 3433 +#define wxBitmapDataObject_GetBitmap 3434 +#define wxBitmapDataObject_SetBitmap 3435 +#define wxBitmapDataObject_destroy 3436 +#define wxClipboard_new 3438 +#define wxClipboard_destruct 3439 +#define wxClipboard_AddData 3440 +#define wxClipboard_Clear 3441 +#define wxClipboard_Close 3442 +#define wxClipboard_Flush 3443 +#define wxClipboard_GetData 3444 +#define wxClipboard_IsOpened 3445 +#define wxClipboard_Open 3446 +#define wxClipboard_SetData 3447 +#define wxClipboard_UsePrimarySelection 3449 +#define wxClipboard_IsSupported 3450 +#define wxClipboard_Get 3451 +#define wxSpinEvent_GetPosition 3452 +#define wxSpinEvent_SetPosition 3453 +#define wxSplitterWindow_new_0 3454 +#define wxSplitterWindow_new_2 3455 +#define wxSplitterWindow_destruct 3456 +#define wxSplitterWindow_Create 3457 +#define wxSplitterWindow_GetMinimumPaneSize 3458 +#define wxSplitterWindow_GetSashGravity 3459 +#define wxSplitterWindow_GetSashPosition 3460 +#define wxSplitterWindow_GetSplitMode 3461 +#define wxSplitterWindow_GetWindow1 3462 +#define wxSplitterWindow_GetWindow2 3463 +#define wxSplitterWindow_Initialize 3464 +#define wxSplitterWindow_IsSplit 3465 +#define wxSplitterWindow_ReplaceWindow 3466 +#define wxSplitterWindow_SetSashGravity 3467 +#define wxSplitterWindow_SetSashPosition 3468 +#define wxSplitterWindow_SetSashSize 3469 +#define wxSplitterWindow_SetMinimumPaneSize 3470 +#define wxSplitterWindow_SetSplitMode 3471 +#define wxSplitterWindow_SplitHorizontally 3472 +#define wxSplitterWindow_SplitVertically 3473 +#define wxSplitterWindow_Unsplit 3474 +#define wxSplitterWindow_UpdateSize 3475 +#define wxSplitterEvent_GetSashPosition 3476 +#define wxSplitterEvent_GetX 3477 +#define wxSplitterEvent_GetY 3478 +#define wxSplitterEvent_GetWindowBeingRemoved 3479 +#define wxSplitterEvent_SetSashPosition 3480 +#define wxHtmlWindow_new_0 3481 +#define wxHtmlWindow_new_2 3482 +#define wxHtmlWindow_AppendToPage 3483 +#define wxHtmlWindow_GetOpenedAnchor 3484 +#define wxHtmlWindow_GetOpenedPage 3485 +#define wxHtmlWindow_GetOpenedPageTitle 3486 +#define wxHtmlWindow_GetRelatedFrame 3487 +#define wxHtmlWindow_HistoryBack 3488 +#define wxHtmlWindow_HistoryCanBack 3489 +#define wxHtmlWindow_HistoryCanForward 3490 +#define wxHtmlWindow_HistoryClear 3491 +#define wxHtmlWindow_HistoryForward 3492 +#define wxHtmlWindow_LoadFile 3493 +#define wxHtmlWindow_LoadPage 3494 +#define wxHtmlWindow_SelectAll 3495 +#define wxHtmlWindow_SelectionToText 3496 +#define wxHtmlWindow_SelectLine 3497 +#define wxHtmlWindow_SelectWord 3498 +#define wxHtmlWindow_SetBorders 3499 +#define wxHtmlWindow_SetFonts 3500 +#define wxHtmlWindow_SetPage 3501 +#define wxHtmlWindow_SetRelatedFrame 3502 +#define wxHtmlWindow_SetRelatedStatusBar 3503 +#define wxHtmlWindow_ToText 3504 +#define wxHtmlWindow_destroy 3505 +#define wxHtmlLinkEvent_GetLinkInfo 3506 +#define wxSystemSettings_GetColour 3507 +#define wxSystemSettings_GetFont 3508 +#define wxSystemSettings_GetMetric 3509 +#define wxSystemSettings_GetScreenType 3510 +#define wxSystemOptions_GetOption 3511 +#define wxSystemOptions_GetOptionInt 3512 +#define wxSystemOptions_HasOption 3513 +#define wxSystemOptions_IsFalse 3514 +#define wxSystemOptions_SetOption_2_1 3515 +#define wxSystemOptions_SetOption_2_0 3516 +#define wxAuiNotebookEvent_SetSelection 3517 +#define wxAuiNotebookEvent_GetSelection 3518 +#define wxAuiNotebookEvent_SetOldSelection 3519 +#define wxAuiNotebookEvent_GetOldSelection 3520 +#define wxAuiNotebookEvent_SetDragSource 3521 +#define wxAuiNotebookEvent_GetDragSource 3522 +#define wxAuiManagerEvent_SetManager 3523 +#define wxAuiManagerEvent_GetManager 3524 +#define wxAuiManagerEvent_SetPane 3525 +#define wxAuiManagerEvent_GetPane 3526 +#define wxAuiManagerEvent_SetButton 3527 +#define wxAuiManagerEvent_GetButton 3528 +#define wxAuiManagerEvent_SetDC 3529 +#define wxAuiManagerEvent_GetDC 3530 +#define wxAuiManagerEvent_Veto 3531 +#define wxAuiManagerEvent_GetVeto 3532 +#define wxAuiManagerEvent_SetCanVeto 3533 +#define wxAuiManagerEvent_CanVeto 3534 +#define wxLogNull_new 3535 +#define wxLogNull_destroy 3536 +#define wxTaskBarIcon_new 3537 +#define wxTaskBarIcon_destruct 3538 +#define wxTaskBarIcon_PopupMenu 3539 +#define wxTaskBarIcon_RemoveIcon 3540 +#define wxTaskBarIcon_SetIcon 3541 +#define wxLocale_new_0 3542 +#define wxLocale_new_2 3544 +#define wxLocale_destruct 3545 +#define wxLocale_Init 3547 +#define wxLocale_AddCatalog_1 3548 +#define wxLocale_AddCatalog_3 3549 +#define wxLocale_AddCatalogLookupPathPrefix 3550 +#define wxLocale_GetCanonicalName 3551 +#define wxLocale_GetLanguage 3552 +#define wxLocale_GetLanguageName 3553 +#define wxLocale_GetLocale 3554 +#define wxLocale_GetName 3555 +#define wxLocale_GetString_2 3556 +#define wxLocale_GetString_4 3557 +#define wxLocale_GetHeaderValue 3558 +#define wxLocale_GetSysName 3559 +#define wxLocale_GetSystemEncoding 3560 +#define wxLocale_GetSystemEncodingName 3561 +#define wxLocale_GetSystemLanguage 3562 +#define wxLocale_IsLoaded 3563 +#define wxLocale_IsOk 3564 +#define wxActivateEvent_GetActive 3565 +#define wxPopupWindow_new_2 3567 +#define wxPopupWindow_new_0 3568 +#define wxPopupWindow_destruct 3570 +#define wxPopupWindow_Create 3571 +#define wxPopupWindow_Position 3572 +#define wxPopupTransientWindow_new_0 3573 +#define wxPopupTransientWindow_new_2 3574 +#define wxPopupTransientWindow_destruct 3575 +#define wxPopupTransientWindow_Popup 3576 +#define wxPopupTransientWindow_Dismiss 3577 diff --git a/lib/wx/examples/demo/ex_aui.erl b/lib/wx/examples/demo/ex_aui.erl index e0841da670..7fbf841d16 100644 --- a/lib/wx/examples/demo/ex_aui.erl +++ b/lib/wx/examples/demo/ex_aui.erl @@ -47,40 +47,54 @@ init(Config) -> -define(pi, wxAuiPaneInfo). do_init(Config) -> - Parent = proplists:get_value(parent, Config), + Parent = proplists:get_value(parent, Config), Panel = wxPanel:new(Parent, []), %% Setup sizers MainSizer = wxBoxSizer:new(?wxVERTICAL), Manager = wxAuiManager:new([{managed_wnd, Panel}]), - - Pane = ?pi:new(), - ?pi:closeButton(Pane), - ?pi:right(Pane), - ?pi:dockable(Pane, [{b, true}]), - ?pi:floatingSize(Pane, 300,200), - ?pi:minSize(Pane, {50,50}), - ?pi:paneBorder(Pane), - ?pi:floatable(Pane, [{b, true}]), - - create_pane(Panel, Manager, Pane), - create_pane(Panel, Manager, - ?pi:caption(?pi:top(?pi:new(Pane)), "One")), - create_pane(Panel, Manager, - ?pi:caption(?pi:left(?pi:new(Pane)), "two")), - create_pane(Panel, Manager, - ?pi:caption(?pi:bottom(?pi:new(Pane)), "Three")), - Pane2 = wxAuiPaneInfo:new(Pane), - ?pi:centrePane(Pane2), - create_notebook(Panel, Manager, ?pi:new(Pane2)), - - wxPanel:setSizer(Panel, MainSizer), - - wxAuiManager:connect(Manager, aui_pane_button, [{skip,true}]), - wxAuiManager:connect(Manager, aui_pane_maximize, [{skip,true}]), - wxAuiManager:update(Manager), - process_flag(trap_exit, true), - {Panel, #state{parent=Panel, config=Config, aui=Manager}}. + try + Art = wxAuiManager:getArtProvider(Manager), + wxAuiDockArt:setColour(Art, ?wxAUI_DOCKART_BACKGROUND_COLOUR, {200, 100, 100}), + wxAuiDockArt:setColour(Art, ?wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR, {200, 100, 100}), + wxAuiDockArt:setColour(Art, ?wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, {100, 200, 100}), + + + Pane = ?pi:new(), + ?pi:closeButton(Pane), + ?pi:right(Pane), + ?pi:dockable(Pane, [{b, true}]), + ?pi:floatingSize(Pane, 300,200), + ?pi:minSize(Pane, {50,50}), + ?pi:paneBorder(Pane), + ?pi:floatable(Pane, [{b, true}]), + + create_pane(Panel, Manager, Pane), + create_pane(Panel, Manager, + ?pi:caption(?pi:top(?pi:new(Pane)), "One")), + create_pane(Panel, Manager, + ?pi:caption(?pi:left(?pi:new(Pane)), "two")), + create_pane(Panel, Manager, + ?pi:caption(?pi:bottom(?pi:new(Pane)), "Three")), + Pane2 = wxAuiPaneInfo:new(Pane), + ?pi:centrePane(Pane2), + create_notebook(Panel, Manager, ?pi:new(Pane2)), + + wxPanel:setSizer(Panel, MainSizer), + + wxAuiManager:connect(Manager, aui_pane_button, [{skip,true}]), + wxAuiManager:connect(Manager, aui_pane_maximize, [{skip,true}]), + wxAuiManager:update(Manager), + process_flag(trap_exit, true), + {Panel, #state{parent=Panel, config=Config, aui=Manager}} + catch Class:Reason -> + ST = erlang:get_stacktrace(), + io:format("AUI Crashed ~p ~p~n",[Reason, ST]), + wxAuiManager:unInit(Manager), + wxAuiManager:destroy(Manager), + wxPanel:destroy(Panel), + erlang:raise(Class, Reason, ST) + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Callbacks handled as normal gen_server callbacks @@ -163,6 +177,15 @@ create_notebook(Parent, Manager, Pane) -> Notebook = wxAuiNotebook:new(Parent, [{style, Style}]), + Art = wxAuiSimpleTabArt:new(), + case ?wxMAJOR_VERSION > 2 of + true -> + wxAuiSimpleTabArt:setColour(Art, {200, 0, 0}), + wxAuiSimpleTabArt:setActiveColour(Art, {0, 0, 200}); + false -> ignore + end, + ok = wxAuiNotebook:setArtProvider(Notebook, Art), + Tab1 = wxPanel:new(Notebook, []), wxPanel:setBackgroundColour(Tab1, ?wxBLACK), wxButton:new(Tab1, ?wxID_ANY, [{label,"New tab"}]), diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl index 69ca13aca1..1bc00ca235 100644 --- a/lib/wx/include/wx.hrl +++ b/lib/wx/include/wx.hrl @@ -295,7 +295,7 @@ veto_flag :: boolean(), canveto_flag :: boolean(), dc :: wxDC:wxDC()}). --type wxAuiManagerEventType() :: aui_pane_button | aui_pane_close | aui_pane_maximize | aui_pane_restore | aui_render | aui_find_manager. +-type wxAuiManagerEventType() :: aui_pane_button | aui_pane_close | aui_pane_maximize | aui_pane_restore | aui_pane_activated | aui_render | aui_find_manager. -type wxAuiManager() :: #wxAuiManager{}. %% Callback event: {@link wxAuiManagerEvent} -record(wxInitDialog, {type :: wxInitDialogEventType()}). %% Callback event: {@link wxInitDialogEvent} diff --git a/lib/wx/src/gen/wxAuiDockArt.erl b/lib/wx/src/gen/wxAuiDockArt.erl index 499fbd9a23..4149b1d424 100644 --- a/lib/wx/src/gen/wxAuiDockArt.erl +++ b/lib/wx/src/gen/wxAuiDockArt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ -module(wxAuiDockArt). -include("wxe.hrl"). --export([]). +-export([getColour/2,getFont/2,getMetric/2,setColour/3,setFont/3,setMetric/3]). %% inherited exports -export([parent_class/1]). @@ -35,3 +35,58 @@ parent_class(_Class) -> erlang:error({badtype, ?MODULE}). -type wxAuiDockArt() :: wx:wx_object(). +%% @doc See external documentation. +-spec getColour(This, Id) -> wx:wx_colour4() when + This::wxAuiDockArt(), Id::integer(). +getColour(#wx_ref{type=ThisT,ref=ThisRef},Id) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:call(?wxAuiDockArt_GetColour, + <>). + +%% @doc See external documentation. +-spec getFont(This, Id) -> wxFont:wxFont() when + This::wxAuiDockArt(), Id::integer(). +getFont(#wx_ref{type=ThisT,ref=ThisRef},Id) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:call(?wxAuiDockArt_GetFont, + <>). + +%% @doc See external documentation. +-spec getMetric(This, Id) -> integer() when + This::wxAuiDockArt(), Id::integer(). +getMetric(#wx_ref{type=ThisT,ref=ThisRef},Id) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:call(?wxAuiDockArt_GetMetric, + <>). + +%% @doc See external documentation. +-spec setColour(This, Id, Colour) -> ok when + This::wxAuiDockArt(), Id::integer(), Colour::wx:wx_colour(). +setColour(#wx_ref{type=ThisT,ref=ThisRef},Id,Colour) + when is_integer(Id),tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:cast(?wxAuiDockArt_SetColour, + <>). + +%% @doc See external documentation. +-spec setFont(This, Id, Font) -> ok when + This::wxAuiDockArt(), Id::integer(), Font::wxFont:wxFont(). +setFont(#wx_ref{type=ThisT,ref=ThisRef},Id,#wx_ref{type=FontT,ref=FontRef}) + when is_integer(Id) -> + ?CLASS(ThisT,wxAuiDockArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiDockArt_SetFont, + <>). + +%% @doc See external documentation. +-spec setMetric(This, Id, New_val) -> ok when + This::wxAuiDockArt(), Id::integer(), New_val::integer(). +setMetric(#wx_ref{type=ThisT,ref=ThisRef},Id,New_val) + when is_integer(Id),is_integer(New_val) -> + ?CLASS(ThisT,wxAuiDockArt), + wxe_util:cast(?wxAuiDockArt_SetMetric, + <>). + diff --git a/lib/wx/src/gen/wxAuiManagerEvent.erl b/lib/wx/src/gen/wxAuiManagerEvent.erl index 51ad211e10..88e4433f24 100644 --- a/lib/wx/src/gen/wxAuiManagerEvent.erl +++ b/lib/wx/src/gen/wxAuiManagerEvent.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2013. All Rights Reserved. +%% Copyright Ericsson AB 2009-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ %% @doc See external documentation: wxAuiManagerEvent. %%
Use {@link wxEvtHandler:connect/3.} with EventType:
-%%
aui_pane_button, aui_pane_close, aui_pane_maximize, aui_pane_restore, aui_render, aui_find_manager
+%%
aui_pane_button, aui_pane_close, aui_pane_maximize, aui_pane_restore, aui_pane_activated, aui_render, aui_find_manager
%% See also the message variant {@link wxEvtHandler:wxAuiManager(). #wxAuiManager{}} event record type. %% %%

This class is derived (and can use functions) from: diff --git a/lib/wx/src/gen/wxAuiSimpleTabArt.erl b/lib/wx/src/gen/wxAuiSimpleTabArt.erl new file mode 100644 index 0000000000..57d12e2eb4 --- /dev/null +++ b/lib/wx/src/gen/wxAuiSimpleTabArt.erl @@ -0,0 +1,67 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: wxAuiSimpleTabArt. +%%

This class is derived (and can use functions) from: +%%
{@link wxAuiTabArt} +%%

+%% @type wxAuiSimpleTabArt(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxAuiSimpleTabArt). +-include("wxe.hrl"). +-export([destroy/1,new/0]). + +%% inherited exports +-export([parent_class/1,setActiveColour/2,setColour/2,setFlags/2,setMeasuringFont/2, + setNormalFont/2,setSelectedFont/2]). + +-export_type([wxAuiSimpleTabArt/0]). +%% @hidden +parent_class(wxAuiTabArt) -> true; +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxAuiSimpleTabArt() :: wx:wx_object(). +%% @doc See external documentation. +-spec new() -> wxAuiSimpleTabArt(). +new() -> + wxe_util:construct(?wxAuiSimpleTabArt_new, + <<>>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxAuiSimpleTabArt()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxAuiSimpleTabArt), + wxe_util:destroy(?wxAuiSimpleTabArt_destroy,Obj), + ok. + %% From wxAuiTabArt +%% @hidden +setActiveColour(This,Colour) -> wxAuiTabArt:setActiveColour(This,Colour). +%% @hidden +setColour(This,Colour) -> wxAuiTabArt:setColour(This,Colour). +%% @hidden +setSelectedFont(This,Font) -> wxAuiTabArt:setSelectedFont(This,Font). +%% @hidden +setNormalFont(This,Font) -> wxAuiTabArt:setNormalFont(This,Font). +%% @hidden +setMeasuringFont(This,Font) -> wxAuiTabArt:setMeasuringFont(This,Font). +%% @hidden +setFlags(This,Flags) -> wxAuiTabArt:setFlags(This,Flags). diff --git a/lib/wx/src/gen/wxAuiTabArt.erl b/lib/wx/src/gen/wxAuiTabArt.erl index 0386ef9dce..80924c0269 100644 --- a/lib/wx/src/gen/wxAuiTabArt.erl +++ b/lib/wx/src/gen/wxAuiTabArt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,8 @@ -module(wxAuiTabArt). -include("wxe.hrl"). --export([]). +-export([setActiveColour/2,setColour/2,setFlags/2,setMeasuringFont/2,setNormalFont/2, + setSelectedFont/2]). %% inherited exports -export([parent_class/1]). @@ -35,3 +36,57 @@ parent_class(_Class) -> erlang:error({badtype, ?MODULE}). -type wxAuiTabArt() :: wx:wx_object(). +%% @doc See external documentation. +-spec setFlags(This, Flags) -> ok when + This::wxAuiTabArt(), Flags::integer(). +setFlags(#wx_ref{type=ThisT,ref=ThisRef},Flags) + when is_integer(Flags) -> + ?CLASS(ThisT,wxAuiTabArt), + wxe_util:cast(?wxAuiTabArt_SetFlags, + <>). + +%% @doc See external documentation. +-spec setMeasuringFont(This, Font) -> ok when + This::wxAuiTabArt(), Font::wxFont:wxFont(). +setMeasuringFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) -> + ?CLASS(ThisT,wxAuiTabArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiTabArt_SetMeasuringFont, + <>). + +%% @doc See external documentation. +-spec setNormalFont(This, Font) -> ok when + This::wxAuiTabArt(), Font::wxFont:wxFont(). +setNormalFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) -> + ?CLASS(ThisT,wxAuiTabArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiTabArt_SetNormalFont, + <>). + +%% @doc See external documentation. +-spec setSelectedFont(This, Font) -> ok when + This::wxAuiTabArt(), Font::wxFont:wxFont(). +setSelectedFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) -> + ?CLASS(ThisT,wxAuiTabArt), + ?CLASS(FontT,wxFont), + wxe_util:cast(?wxAuiTabArt_SetSelectedFont, + <>). + +%% @doc See external documentation. +-spec setColour(This, Colour) -> ok when + This::wxAuiTabArt(), Colour::wx:wx_colour(). +setColour(#wx_ref{type=ThisT,ref=ThisRef},Colour) + when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 -> + ?CLASS(ThisT,wxAuiTabArt), + wxe_util:cast(?wxAuiTabArt_SetColour, + <>). + +%% @doc See external documentation. +-spec setActiveColour(This, Colour) -> ok when + This::wxAuiTabArt(), Colour::wx:wx_colour(). +setActiveColour(#wx_ref{type=ThisT,ref=ThisRef},Colour) + when tuple_size(Colour) =:= 3; tuple_size(Colour) =:= 4 -> + ?CLASS(ThisT,wxAuiTabArt), + wxe_util:cast(?wxAuiTabArt_SetActiveColour, + <>). + diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl index 58fbe8d061..22df128514 100644 --- a/lib/wx/src/gen/wxe_debug.hrl +++ b/lib/wx/src/gen/wxe_debug.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2014. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -2462,885 +2462,899 @@ wxdebug_table() -> {2672, {wxAuiNotebook, setTabCtrlHeight, 1}}, {2673, {wxAuiNotebook, setUniformBitmapSize, 1}}, {2674, {wxAuiNotebook, 'Destroy', undefined}}, - {2675, {wxMDIParentFrame, new_0, 0}}, - {2676, {wxMDIParentFrame, new_4, 4}}, - {2677, {wxMDIParentFrame, destruct, 0}}, - {2678, {wxMDIParentFrame, activateNext, 0}}, - {2679, {wxMDIParentFrame, activatePrevious, 0}}, - {2680, {wxMDIParentFrame, arrangeIcons, 0}}, - {2681, {wxMDIParentFrame, cascade, 0}}, - {2682, {wxMDIParentFrame, create, 4}}, - {2683, {wxMDIParentFrame, getActiveChild, 0}}, - {2684, {wxMDIParentFrame, getClientWindow, 0}}, - {2685, {wxMDIParentFrame, tile, 1}}, - {2686, {wxMDIChildFrame, new_0, 0}}, - {2687, {wxMDIChildFrame, new_4, 4}}, - {2688, {wxMDIChildFrame, destruct, 0}}, - {2689, {wxMDIChildFrame, activate, 0}}, - {2690, {wxMDIChildFrame, create, 4}}, - {2691, {wxMDIChildFrame, maximize, 1}}, - {2692, {wxMDIChildFrame, restore, 0}}, - {2693, {wxMDIClientWindow, new_0, 0}}, - {2694, {wxMDIClientWindow, new_2, 2}}, - {2695, {wxMDIClientWindow, destruct, 0}}, - {2696, {wxMDIClientWindow, createClient, 2}}, - {2697, {wxLayoutAlgorithm, new, 0}}, - {2698, {wxLayoutAlgorithm, layoutFrame, 2}}, - {2699, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, - {2700, {wxLayoutAlgorithm, layoutWindow, 2}}, - {2701, {wxLayoutAlgorithm, 'Destroy', undefined}}, - {2702, {wxEvent, getId, 0}}, - {2703, {wxEvent, getSkipped, 0}}, - {2704, {wxEvent, getTimestamp, 0}}, - {2705, {wxEvent, isCommandEvent, 0}}, - {2706, {wxEvent, resumePropagation, 1}}, - {2707, {wxEvent, shouldPropagate, 0}}, - {2708, {wxEvent, skip, 1}}, - {2709, {wxEvent, stopPropagation, 0}}, - {2710, {wxCommandEvent, getClientData, 0}}, - {2711, {wxCommandEvent, getExtraLong, 0}}, - {2712, {wxCommandEvent, getInt, 0}}, - {2713, {wxCommandEvent, getSelection, 0}}, - {2714, {wxCommandEvent, getString, 0}}, - {2715, {wxCommandEvent, isChecked, 0}}, - {2716, {wxCommandEvent, isSelection, 0}}, - {2717, {wxCommandEvent, setInt, 1}}, - {2718, {wxCommandEvent, setString, 1}}, - {2719, {wxScrollEvent, getOrientation, 0}}, - {2720, {wxScrollEvent, getPosition, 0}}, - {2721, {wxScrollWinEvent, getOrientation, 0}}, - {2722, {wxScrollWinEvent, getPosition, 0}}, - {2723, {wxMouseEvent, altDown, 0}}, - {2724, {wxMouseEvent, button, 1}}, - {2725, {wxMouseEvent, buttonDClick, 1}}, - {2726, {wxMouseEvent, buttonDown, 1}}, - {2727, {wxMouseEvent, buttonUp, 1}}, - {2728, {wxMouseEvent, cmdDown, 0}}, - {2729, {wxMouseEvent, controlDown, 0}}, - {2730, {wxMouseEvent, dragging, 0}}, - {2731, {wxMouseEvent, entering, 0}}, - {2732, {wxMouseEvent, getButton, 0}}, - {2735, {wxMouseEvent, getPosition, 0}}, - {2736, {wxMouseEvent, getLogicalPosition, 1}}, - {2737, {wxMouseEvent, getLinesPerAction, 0}}, - {2738, {wxMouseEvent, getWheelRotation, 0}}, - {2739, {wxMouseEvent, getWheelDelta, 0}}, - {2740, {wxMouseEvent, getX, 0}}, - {2741, {wxMouseEvent, getY, 0}}, - {2742, {wxMouseEvent, isButton, 0}}, - {2743, {wxMouseEvent, isPageScroll, 0}}, - {2744, {wxMouseEvent, leaving, 0}}, - {2745, {wxMouseEvent, leftDClick, 0}}, - {2746, {wxMouseEvent, leftDown, 0}}, - {2747, {wxMouseEvent, leftIsDown, 0}}, - {2748, {wxMouseEvent, leftUp, 0}}, - {2749, {wxMouseEvent, metaDown, 0}}, - {2750, {wxMouseEvent, middleDClick, 0}}, - {2751, {wxMouseEvent, middleDown, 0}}, - {2752, {wxMouseEvent, middleIsDown, 0}}, - {2753, {wxMouseEvent, middleUp, 0}}, - {2754, {wxMouseEvent, moving, 0}}, - {2755, {wxMouseEvent, rightDClick, 0}}, - {2756, {wxMouseEvent, rightDown, 0}}, - {2757, {wxMouseEvent, rightIsDown, 0}}, - {2758, {wxMouseEvent, rightUp, 0}}, - {2759, {wxMouseEvent, shiftDown, 0}}, - {2760, {wxSetCursorEvent, getCursor, 0}}, - {2761, {wxSetCursorEvent, getX, 0}}, - {2762, {wxSetCursorEvent, getY, 0}}, - {2763, {wxSetCursorEvent, hasCursor, 0}}, - {2764, {wxSetCursorEvent, setCursor, 1}}, - {2765, {wxKeyEvent, altDown, 0}}, - {2766, {wxKeyEvent, cmdDown, 0}}, - {2767, {wxKeyEvent, controlDown, 0}}, - {2768, {wxKeyEvent, getKeyCode, 0}}, - {2769, {wxKeyEvent, getModifiers, 0}}, - {2772, {wxKeyEvent, getPosition, 0}}, - {2773, {wxKeyEvent, getRawKeyCode, 0}}, - {2774, {wxKeyEvent, getRawKeyFlags, 0}}, - {2775, {wxKeyEvent, getUnicodeKey, 0}}, - {2776, {wxKeyEvent, getX, 0}}, - {2777, {wxKeyEvent, getY, 0}}, - {2778, {wxKeyEvent, hasModifiers, 0}}, - {2779, {wxKeyEvent, metaDown, 0}}, - {2780, {wxKeyEvent, shiftDown, 0}}, - {2781, {wxSizeEvent, getSize, 0}}, - {2782, {wxMoveEvent, getPosition, 0}}, - {2783, {wxEraseEvent, getDC, 0}}, - {2784, {wxFocusEvent, getWindow, 0}}, - {2785, {wxChildFocusEvent, getWindow, 0}}, - {2786, {wxMenuEvent, getMenu, 0}}, - {2787, {wxMenuEvent, getMenuId, 0}}, - {2788, {wxMenuEvent, isPopup, 0}}, - {2789, {wxCloseEvent, canVeto, 0}}, - {2790, {wxCloseEvent, getLoggingOff, 0}}, - {2791, {wxCloseEvent, setCanVeto, 1}}, - {2792, {wxCloseEvent, setLoggingOff, 1}}, - {2793, {wxCloseEvent, veto, 1}}, - {2794, {wxShowEvent, setShow, 1}}, - {2795, {wxShowEvent, getShow, 0}}, - {2796, {wxIconizeEvent, iconized, 0}}, - {2797, {wxJoystickEvent, buttonDown, 1}}, - {2798, {wxJoystickEvent, buttonIsDown, 1}}, - {2799, {wxJoystickEvent, buttonUp, 1}}, - {2800, {wxJoystickEvent, getButtonChange, 0}}, - {2801, {wxJoystickEvent, getButtonState, 0}}, - {2802, {wxJoystickEvent, getJoystick, 0}}, - {2803, {wxJoystickEvent, getPosition, 0}}, - {2804, {wxJoystickEvent, getZPosition, 0}}, - {2805, {wxJoystickEvent, isButton, 0}}, - {2806, {wxJoystickEvent, isMove, 0}}, - {2807, {wxJoystickEvent, isZMove, 0}}, - {2808, {wxUpdateUIEvent, canUpdate, 1}}, - {2809, {wxUpdateUIEvent, check, 1}}, - {2810, {wxUpdateUIEvent, enable, 1}}, - {2811, {wxUpdateUIEvent, show, 1}}, - {2812, {wxUpdateUIEvent, getChecked, 0}}, - {2813, {wxUpdateUIEvent, getEnabled, 0}}, - {2814, {wxUpdateUIEvent, getShown, 0}}, - {2815, {wxUpdateUIEvent, getSetChecked, 0}}, - {2816, {wxUpdateUIEvent, getSetEnabled, 0}}, - {2817, {wxUpdateUIEvent, getSetShown, 0}}, - {2818, {wxUpdateUIEvent, getSetText, 0}}, - {2819, {wxUpdateUIEvent, getText, 0}}, - {2820, {wxUpdateUIEvent, getMode, 0}}, - {2821, {wxUpdateUIEvent, getUpdateInterval, 0}}, - {2822, {wxUpdateUIEvent, resetUpdateTime, 0}}, - {2823, {wxUpdateUIEvent, setMode, 1}}, - {2824, {wxUpdateUIEvent, setText, 1}}, - {2825, {wxUpdateUIEvent, setUpdateInterval, 1}}, - {2826, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, - {2827, {wxPaletteChangedEvent, setChangedWindow, 1}}, - {2828, {wxPaletteChangedEvent, getChangedWindow, 0}}, - {2829, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, - {2830, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, - {2831, {wxNavigationKeyEvent, getDirection, 0}}, - {2832, {wxNavigationKeyEvent, setDirection, 1}}, - {2833, {wxNavigationKeyEvent, isWindowChange, 0}}, - {2834, {wxNavigationKeyEvent, setWindowChange, 1}}, - {2835, {wxNavigationKeyEvent, isFromTab, 0}}, - {2836, {wxNavigationKeyEvent, setFromTab, 1}}, - {2837, {wxNavigationKeyEvent, getCurrentFocus, 0}}, - {2838, {wxNavigationKeyEvent, setCurrentFocus, 1}}, - {2839, {wxHelpEvent, getOrigin, 0}}, - {2840, {wxHelpEvent, getPosition, 0}}, - {2841, {wxHelpEvent, setOrigin, 1}}, - {2842, {wxHelpEvent, setPosition, 1}}, - {2843, {wxContextMenuEvent, getPosition, 0}}, - {2844, {wxContextMenuEvent, setPosition, 1}}, - {2845, {wxIdleEvent, canSend, 1}}, - {2846, {wxIdleEvent, getMode, 0}}, - {2847, {wxIdleEvent, requestMore, 1}}, - {2848, {wxIdleEvent, moreRequested, 0}}, - {2849, {wxIdleEvent, setMode, 1}}, - {2850, {wxGridEvent, altDown, 0}}, - {2851, {wxGridEvent, controlDown, 0}}, - {2852, {wxGridEvent, getCol, 0}}, - {2853, {wxGridEvent, getPosition, 0}}, - {2854, {wxGridEvent, getRow, 0}}, - {2855, {wxGridEvent, metaDown, 0}}, - {2856, {wxGridEvent, selecting, 0}}, - {2857, {wxGridEvent, shiftDown, 0}}, - {2858, {wxNotifyEvent, allow, 0}}, - {2859, {wxNotifyEvent, isAllowed, 0}}, - {2860, {wxNotifyEvent, veto, 0}}, - {2861, {wxSashEvent, getEdge, 0}}, - {2862, {wxSashEvent, getDragRect, 0}}, - {2863, {wxSashEvent, getDragStatus, 0}}, - {2864, {wxListEvent, getCacheFrom, 0}}, - {2865, {wxListEvent, getCacheTo, 0}}, - {2866, {wxListEvent, getKeyCode, 0}}, - {2867, {wxListEvent, getIndex, 0}}, - {2868, {wxListEvent, getColumn, 0}}, - {2869, {wxListEvent, getPoint, 0}}, - {2870, {wxListEvent, getLabel, 0}}, - {2871, {wxListEvent, getText, 0}}, - {2872, {wxListEvent, getImage, 0}}, - {2873, {wxListEvent, getData, 0}}, - {2874, {wxListEvent, getMask, 0}}, - {2875, {wxListEvent, getItem, 0}}, - {2876, {wxListEvent, isEditCancelled, 0}}, - {2877, {wxDateEvent, getDate, 0}}, - {2878, {wxCalendarEvent, getWeekDay, 0}}, - {2879, {wxFileDirPickerEvent, getPath, 0}}, - {2880, {wxColourPickerEvent, getColour, 0}}, - {2881, {wxFontPickerEvent, getFont, 0}}, - {2882, {wxStyledTextEvent, getPosition, 0}}, - {2883, {wxStyledTextEvent, getKey, 0}}, - {2884, {wxStyledTextEvent, getModifiers, 0}}, - {2885, {wxStyledTextEvent, getModificationType, 0}}, - {2886, {wxStyledTextEvent, getText, 0}}, - {2887, {wxStyledTextEvent, getLength, 0}}, - {2888, {wxStyledTextEvent, getLinesAdded, 0}}, - {2889, {wxStyledTextEvent, getLine, 0}}, - {2890, {wxStyledTextEvent, getFoldLevelNow, 0}}, - {2891, {wxStyledTextEvent, getFoldLevelPrev, 0}}, - {2892, {wxStyledTextEvent, getMargin, 0}}, - {2893, {wxStyledTextEvent, getMessage, 0}}, - {2894, {wxStyledTextEvent, getWParam, 0}}, - {2895, {wxStyledTextEvent, getLParam, 0}}, - {2896, {wxStyledTextEvent, getListType, 0}}, - {2897, {wxStyledTextEvent, getX, 0}}, - {2898, {wxStyledTextEvent, getY, 0}}, - {2899, {wxStyledTextEvent, getDragText, 0}}, - {2900, {wxStyledTextEvent, getDragAllowMove, 0}}, - {2901, {wxStyledTextEvent, getDragResult, 0}}, - {2902, {wxStyledTextEvent, getShift, 0}}, - {2903, {wxStyledTextEvent, getControl, 0}}, - {2904, {wxStyledTextEvent, getAlt, 0}}, - {2905, {utils, getKeyState, 1}}, - {2906, {utils, getMousePosition, 2}}, - {2907, {utils, getMouseState, 0}}, - {2908, {utils, setDetectableAutoRepeat, 1}}, - {2909, {utils, bell, 0}}, - {2910, {utils, findMenuItemId, 3}}, - {2911, {utils, genericFindWindowAtPoint, 1}}, - {2912, {utils, findWindowAtPoint, 1}}, - {2913, {utils, beginBusyCursor, 1}}, - {2914, {utils, endBusyCursor, 0}}, - {2915, {utils, isBusy, 0}}, - {2916, {utils, shutdown, 1}}, - {2917, {utils, shell, 1}}, - {2918, {utils, launchDefaultBrowser, 2}}, - {2919, {utils, getEmailAddress, 0}}, - {2920, {utils, getUserId, 0}}, - {2921, {utils, getHomeDir, 0}}, - {2922, {utils, newId, 0}}, - {2923, {utils, registerId, 1}}, - {2924, {utils, getCurrentId, 0}}, - {2925, {utils, getOsDescription, 0}}, - {2926, {utils, isPlatformLittleEndian, 0}}, - {2927, {utils, isPlatform64Bit, 0}}, - {2928, {gdicmn, displaySize, 2}}, - {2929, {gdicmn, setCursor, 1}}, - {2930, {wxPrintout, new, 1}}, - {2931, {wxPrintout, destruct, 0}}, - {2932, {wxPrintout, getDC, 0}}, - {2933, {wxPrintout, getPageSizeMM, 2}}, - {2934, {wxPrintout, getPageSizePixels, 2}}, - {2935, {wxPrintout, getPaperRectPixels, 0}}, - {2936, {wxPrintout, getPPIPrinter, 2}}, - {2937, {wxPrintout, getPPIScreen, 2}}, - {2938, {wxPrintout, getTitle, 0}}, - {2939, {wxPrintout, isPreview, 0}}, - {2940, {wxPrintout, fitThisSizeToPaper, 1}}, - {2941, {wxPrintout, fitThisSizeToPage, 1}}, - {2942, {wxPrintout, fitThisSizeToPageMargins, 2}}, - {2943, {wxPrintout, mapScreenSizeToPaper, 0}}, - {2944, {wxPrintout, mapScreenSizeToPage, 0}}, - {2945, {wxPrintout, mapScreenSizeToPageMargins, 1}}, - {2946, {wxPrintout, mapScreenSizeToDevice, 0}}, - {2947, {wxPrintout, getLogicalPaperRect, 0}}, - {2948, {wxPrintout, getLogicalPageRect, 0}}, - {2949, {wxPrintout, getLogicalPageMarginsRect, 1}}, - {2950, {wxPrintout, setLogicalOrigin, 2}}, - {2951, {wxPrintout, offsetLogicalOrigin, 2}}, - {2952, {wxStyledTextCtrl, new_2, 2}}, - {2953, {wxStyledTextCtrl, new_0, 0}}, - {2954, {wxStyledTextCtrl, destruct, 0}}, - {2955, {wxStyledTextCtrl, create, 2}}, - {2956, {wxStyledTextCtrl, addText, 1}}, - {2957, {wxStyledTextCtrl, addStyledText, 1}}, - {2958, {wxStyledTextCtrl, insertText, 2}}, - {2959, {wxStyledTextCtrl, clearAll, 0}}, - {2960, {wxStyledTextCtrl, clearDocumentStyle, 0}}, - {2961, {wxStyledTextCtrl, getLength, 0}}, - {2962, {wxStyledTextCtrl, getCharAt, 1}}, - {2963, {wxStyledTextCtrl, getCurrentPos, 0}}, - {2964, {wxStyledTextCtrl, getAnchor, 0}}, - {2965, {wxStyledTextCtrl, getStyleAt, 1}}, - {2966, {wxStyledTextCtrl, redo, 0}}, - {2967, {wxStyledTextCtrl, setUndoCollection, 1}}, - {2968, {wxStyledTextCtrl, selectAll, 0}}, - {2969, {wxStyledTextCtrl, setSavePoint, 0}}, - {2970, {wxStyledTextCtrl, getStyledText, 2}}, - {2971, {wxStyledTextCtrl, canRedo, 0}}, - {2972, {wxStyledTextCtrl, markerLineFromHandle, 1}}, - {2973, {wxStyledTextCtrl, markerDeleteHandle, 1}}, - {2974, {wxStyledTextCtrl, getUndoCollection, 0}}, - {2975, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, - {2976, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, - {2977, {wxStyledTextCtrl, positionFromPoint, 1}}, - {2978, {wxStyledTextCtrl, positionFromPointClose, 2}}, - {2979, {wxStyledTextCtrl, gotoLine, 1}}, - {2980, {wxStyledTextCtrl, gotoPos, 1}}, - {2981, {wxStyledTextCtrl, setAnchor, 1}}, - {2982, {wxStyledTextCtrl, getCurLine, 1}}, - {2983, {wxStyledTextCtrl, getEndStyled, 0}}, - {2984, {wxStyledTextCtrl, convertEOLs, 1}}, - {2985, {wxStyledTextCtrl, getEOLMode, 0}}, - {2986, {wxStyledTextCtrl, setEOLMode, 1}}, - {2987, {wxStyledTextCtrl, startStyling, 2}}, - {2988, {wxStyledTextCtrl, setStyling, 2}}, - {2989, {wxStyledTextCtrl, getBufferedDraw, 0}}, - {2990, {wxStyledTextCtrl, setBufferedDraw, 1}}, - {2991, {wxStyledTextCtrl, setTabWidth, 1}}, - {2992, {wxStyledTextCtrl, getTabWidth, 0}}, - {2993, {wxStyledTextCtrl, setCodePage, 1}}, - {2994, {wxStyledTextCtrl, markerDefine, 3}}, - {2995, {wxStyledTextCtrl, markerSetForeground, 2}}, - {2996, {wxStyledTextCtrl, markerSetBackground, 2}}, - {2997, {wxStyledTextCtrl, markerAdd, 2}}, - {2998, {wxStyledTextCtrl, markerDelete, 2}}, - {2999, {wxStyledTextCtrl, markerDeleteAll, 1}}, - {3000, {wxStyledTextCtrl, markerGet, 1}}, - {3001, {wxStyledTextCtrl, markerNext, 2}}, - {3002, {wxStyledTextCtrl, markerPrevious, 2}}, - {3003, {wxStyledTextCtrl, markerDefineBitmap, 2}}, - {3004, {wxStyledTextCtrl, markerAddSet, 2}}, - {3005, {wxStyledTextCtrl, markerSetAlpha, 2}}, - {3006, {wxStyledTextCtrl, setMarginType, 2}}, - {3007, {wxStyledTextCtrl, getMarginType, 1}}, - {3008, {wxStyledTextCtrl, setMarginWidth, 2}}, - {3009, {wxStyledTextCtrl, getMarginWidth, 1}}, - {3010, {wxStyledTextCtrl, setMarginMask, 2}}, - {3011, {wxStyledTextCtrl, getMarginMask, 1}}, - {3012, {wxStyledTextCtrl, setMarginSensitive, 2}}, - {3013, {wxStyledTextCtrl, getMarginSensitive, 1}}, - {3014, {wxStyledTextCtrl, styleClearAll, 0}}, - {3015, {wxStyledTextCtrl, styleSetForeground, 2}}, - {3016, {wxStyledTextCtrl, styleSetBackground, 2}}, - {3017, {wxStyledTextCtrl, styleSetBold, 2}}, - {3018, {wxStyledTextCtrl, styleSetItalic, 2}}, - {3019, {wxStyledTextCtrl, styleSetSize, 2}}, - {3020, {wxStyledTextCtrl, styleSetFaceName, 2}}, - {3021, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, - {3022, {wxStyledTextCtrl, styleResetDefault, 0}}, - {3023, {wxStyledTextCtrl, styleSetUnderline, 2}}, - {3024, {wxStyledTextCtrl, styleSetCase, 2}}, - {3025, {wxStyledTextCtrl, styleSetHotSpot, 2}}, - {3026, {wxStyledTextCtrl, setSelForeground, 2}}, - {3027, {wxStyledTextCtrl, setSelBackground, 2}}, - {3028, {wxStyledTextCtrl, getSelAlpha, 0}}, - {3029, {wxStyledTextCtrl, setSelAlpha, 1}}, - {3030, {wxStyledTextCtrl, setCaretForeground, 1}}, - {3031, {wxStyledTextCtrl, cmdKeyAssign, 3}}, - {3032, {wxStyledTextCtrl, cmdKeyClear, 2}}, - {3033, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, - {3034, {wxStyledTextCtrl, setStyleBytes, 2}}, - {3035, {wxStyledTextCtrl, styleSetVisible, 2}}, - {3036, {wxStyledTextCtrl, getCaretPeriod, 0}}, - {3037, {wxStyledTextCtrl, setCaretPeriod, 1}}, - {3038, {wxStyledTextCtrl, setWordChars, 1}}, - {3039, {wxStyledTextCtrl, beginUndoAction, 0}}, - {3040, {wxStyledTextCtrl, endUndoAction, 0}}, - {3041, {wxStyledTextCtrl, indicatorSetStyle, 2}}, - {3042, {wxStyledTextCtrl, indicatorGetStyle, 1}}, - {3043, {wxStyledTextCtrl, indicatorSetForeground, 2}}, - {3044, {wxStyledTextCtrl, indicatorGetForeground, 1}}, - {3045, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, - {3046, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, - {3047, {wxStyledTextCtrl, getStyleBits, 0}}, - {3048, {wxStyledTextCtrl, setLineState, 2}}, - {3049, {wxStyledTextCtrl, getLineState, 1}}, - {3050, {wxStyledTextCtrl, getMaxLineState, 0}}, - {3051, {wxStyledTextCtrl, getCaretLineVisible, 0}}, - {3052, {wxStyledTextCtrl, setCaretLineVisible, 1}}, - {3053, {wxStyledTextCtrl, getCaretLineBackground, 0}}, - {3054, {wxStyledTextCtrl, setCaretLineBackground, 1}}, - {3055, {wxStyledTextCtrl, autoCompShow, 2}}, - {3056, {wxStyledTextCtrl, autoCompCancel, 0}}, - {3057, {wxStyledTextCtrl, autoCompActive, 0}}, - {3058, {wxStyledTextCtrl, autoCompPosStart, 0}}, - {3059, {wxStyledTextCtrl, autoCompComplete, 0}}, - {3060, {wxStyledTextCtrl, autoCompStops, 1}}, - {3061, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, - {3062, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, - {3063, {wxStyledTextCtrl, autoCompSelect, 1}}, - {3064, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, - {3065, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, - {3066, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, - {3067, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, - {3068, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, - {3069, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, - {3070, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, - {3071, {wxStyledTextCtrl, userListShow, 2}}, - {3072, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, - {3073, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, - {3074, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, - {3075, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, - {3076, {wxStyledTextCtrl, registerImage, 2}}, - {3077, {wxStyledTextCtrl, clearRegisteredImages, 0}}, - {3078, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, - {3079, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, - {3080, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, - {3081, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, - {3082, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, - {3083, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, - {3084, {wxStyledTextCtrl, setIndent, 1}}, - {3085, {wxStyledTextCtrl, getIndent, 0}}, - {3086, {wxStyledTextCtrl, setUseTabs, 1}}, - {3087, {wxStyledTextCtrl, getUseTabs, 0}}, - {3088, {wxStyledTextCtrl, setLineIndentation, 2}}, - {3089, {wxStyledTextCtrl, getLineIndentation, 1}}, - {3090, {wxStyledTextCtrl, getLineIndentPosition, 1}}, - {3091, {wxStyledTextCtrl, getColumn, 1}}, - {3092, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, - {3093, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, - {3094, {wxStyledTextCtrl, setIndentationGuides, 1}}, - {3095, {wxStyledTextCtrl, getIndentationGuides, 0}}, - {3096, {wxStyledTextCtrl, setHighlightGuide, 1}}, - {3097, {wxStyledTextCtrl, getHighlightGuide, 0}}, - {3098, {wxStyledTextCtrl, getLineEndPosition, 1}}, - {3099, {wxStyledTextCtrl, getCodePage, 0}}, - {3100, {wxStyledTextCtrl, getCaretForeground, 0}}, - {3101, {wxStyledTextCtrl, getReadOnly, 0}}, - {3102, {wxStyledTextCtrl, setCurrentPos, 1}}, - {3103, {wxStyledTextCtrl, setSelectionStart, 1}}, - {3104, {wxStyledTextCtrl, getSelectionStart, 0}}, - {3105, {wxStyledTextCtrl, setSelectionEnd, 1}}, - {3106, {wxStyledTextCtrl, getSelectionEnd, 0}}, - {3107, {wxStyledTextCtrl, setPrintMagnification, 1}}, - {3108, {wxStyledTextCtrl, getPrintMagnification, 0}}, - {3109, {wxStyledTextCtrl, setPrintColourMode, 1}}, - {3110, {wxStyledTextCtrl, getPrintColourMode, 0}}, - {3111, {wxStyledTextCtrl, findText, 4}}, - {3112, {wxStyledTextCtrl, formatRange, 7}}, - {3113, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, - {3114, {wxStyledTextCtrl, getLine, 1}}, - {3115, {wxStyledTextCtrl, getLineCount, 0}}, - {3116, {wxStyledTextCtrl, setMarginLeft, 1}}, - {3117, {wxStyledTextCtrl, getMarginLeft, 0}}, - {3118, {wxStyledTextCtrl, setMarginRight, 1}}, - {3119, {wxStyledTextCtrl, getMarginRight, 0}}, - {3120, {wxStyledTextCtrl, getModify, 0}}, - {3121, {wxStyledTextCtrl, setSelection, 2}}, - {3122, {wxStyledTextCtrl, getSelectedText, 0}}, - {3123, {wxStyledTextCtrl, getTextRange, 2}}, - {3124, {wxStyledTextCtrl, hideSelection, 1}}, - {3125, {wxStyledTextCtrl, lineFromPosition, 1}}, - {3126, {wxStyledTextCtrl, positionFromLine, 1}}, - {3127, {wxStyledTextCtrl, lineScroll, 2}}, - {3128, {wxStyledTextCtrl, ensureCaretVisible, 0}}, - {3129, {wxStyledTextCtrl, replaceSelection, 1}}, - {3130, {wxStyledTextCtrl, setReadOnly, 1}}, - {3131, {wxStyledTextCtrl, canPaste, 0}}, - {3132, {wxStyledTextCtrl, canUndo, 0}}, - {3133, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, - {3134, {wxStyledTextCtrl, undo, 0}}, - {3135, {wxStyledTextCtrl, cut, 0}}, - {3136, {wxStyledTextCtrl, copy, 0}}, - {3137, {wxStyledTextCtrl, paste, 0}}, - {3138, {wxStyledTextCtrl, clear, 0}}, - {3139, {wxStyledTextCtrl, setText, 1}}, - {3140, {wxStyledTextCtrl, getText, 0}}, - {3141, {wxStyledTextCtrl, getTextLength, 0}}, - {3142, {wxStyledTextCtrl, getOvertype, 0}}, - {3143, {wxStyledTextCtrl, setCaretWidth, 1}}, - {3144, {wxStyledTextCtrl, getCaretWidth, 0}}, - {3145, {wxStyledTextCtrl, setTargetStart, 1}}, - {3146, {wxStyledTextCtrl, getTargetStart, 0}}, - {3147, {wxStyledTextCtrl, setTargetEnd, 1}}, - {3148, {wxStyledTextCtrl, getTargetEnd, 0}}, - {3149, {wxStyledTextCtrl, replaceTarget, 1}}, - {3150, {wxStyledTextCtrl, searchInTarget, 1}}, - {3151, {wxStyledTextCtrl, setSearchFlags, 1}}, - {3152, {wxStyledTextCtrl, getSearchFlags, 0}}, - {3153, {wxStyledTextCtrl, callTipShow, 2}}, - {3154, {wxStyledTextCtrl, callTipCancel, 0}}, - {3155, {wxStyledTextCtrl, callTipActive, 0}}, - {3156, {wxStyledTextCtrl, callTipPosAtStart, 0}}, - {3157, {wxStyledTextCtrl, callTipSetHighlight, 2}}, - {3158, {wxStyledTextCtrl, callTipSetBackground, 1}}, - {3159, {wxStyledTextCtrl, callTipSetForeground, 1}}, - {3160, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, - {3161, {wxStyledTextCtrl, callTipUseStyle, 1}}, - {3162, {wxStyledTextCtrl, visibleFromDocLine, 1}}, - {3163, {wxStyledTextCtrl, docLineFromVisible, 1}}, - {3164, {wxStyledTextCtrl, wrapCount, 1}}, - {3165, {wxStyledTextCtrl, setFoldLevel, 2}}, - {3166, {wxStyledTextCtrl, getFoldLevel, 1}}, - {3167, {wxStyledTextCtrl, getLastChild, 2}}, - {3168, {wxStyledTextCtrl, getFoldParent, 1}}, - {3169, {wxStyledTextCtrl, showLines, 2}}, - {3170, {wxStyledTextCtrl, hideLines, 2}}, - {3171, {wxStyledTextCtrl, getLineVisible, 1}}, - {3172, {wxStyledTextCtrl, setFoldExpanded, 2}}, - {3173, {wxStyledTextCtrl, getFoldExpanded, 1}}, - {3174, {wxStyledTextCtrl, toggleFold, 1}}, - {3175, {wxStyledTextCtrl, ensureVisible, 1}}, - {3176, {wxStyledTextCtrl, setFoldFlags, 1}}, - {3177, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, - {3178, {wxStyledTextCtrl, setTabIndents, 1}}, - {3179, {wxStyledTextCtrl, getTabIndents, 0}}, - {3180, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, - {3181, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, - {3182, {wxStyledTextCtrl, setMouseDwellTime, 1}}, - {3183, {wxStyledTextCtrl, getMouseDwellTime, 0}}, - {3184, {wxStyledTextCtrl, wordStartPosition, 2}}, - {3185, {wxStyledTextCtrl, wordEndPosition, 2}}, - {3186, {wxStyledTextCtrl, setWrapMode, 1}}, - {3187, {wxStyledTextCtrl, getWrapMode, 0}}, - {3188, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, - {3189, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, - {3190, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, - {3191, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, - {3192, {wxStyledTextCtrl, setWrapStartIndent, 1}}, - {3193, {wxStyledTextCtrl, getWrapStartIndent, 0}}, - {3194, {wxStyledTextCtrl, setLayoutCache, 1}}, - {3195, {wxStyledTextCtrl, getLayoutCache, 0}}, - {3196, {wxStyledTextCtrl, setScrollWidth, 1}}, - {3197, {wxStyledTextCtrl, getScrollWidth, 0}}, - {3198, {wxStyledTextCtrl, textWidth, 2}}, - {3199, {wxStyledTextCtrl, getEndAtLastLine, 0}}, - {3200, {wxStyledTextCtrl, textHeight, 1}}, - {3201, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, - {3202, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, - {3203, {wxStyledTextCtrl, appendText, 1}}, - {3204, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, - {3205, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, - {3206, {wxStyledTextCtrl, targetFromSelection, 0}}, - {3207, {wxStyledTextCtrl, linesJoin, 0}}, - {3208, {wxStyledTextCtrl, linesSplit, 1}}, - {3209, {wxStyledTextCtrl, setFoldMarginColour, 2}}, - {3210, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, - {3211, {wxStyledTextCtrl, lineDown, 0}}, - {3212, {wxStyledTextCtrl, lineDownExtend, 0}}, - {3213, {wxStyledTextCtrl, lineUp, 0}}, - {3214, {wxStyledTextCtrl, lineUpExtend, 0}}, - {3215, {wxStyledTextCtrl, charLeft, 0}}, - {3216, {wxStyledTextCtrl, charLeftExtend, 0}}, - {3217, {wxStyledTextCtrl, charRight, 0}}, - {3218, {wxStyledTextCtrl, charRightExtend, 0}}, - {3219, {wxStyledTextCtrl, wordLeft, 0}}, - {3220, {wxStyledTextCtrl, wordLeftExtend, 0}}, - {3221, {wxStyledTextCtrl, wordRight, 0}}, - {3222, {wxStyledTextCtrl, wordRightExtend, 0}}, - {3223, {wxStyledTextCtrl, home, 0}}, - {3224, {wxStyledTextCtrl, homeExtend, 0}}, - {3225, {wxStyledTextCtrl, lineEnd, 0}}, - {3226, {wxStyledTextCtrl, lineEndExtend, 0}}, - {3227, {wxStyledTextCtrl, documentStart, 0}}, - {3228, {wxStyledTextCtrl, documentStartExtend, 0}}, - {3229, {wxStyledTextCtrl, documentEnd, 0}}, - {3230, {wxStyledTextCtrl, documentEndExtend, 0}}, - {3231, {wxStyledTextCtrl, pageUp, 0}}, - {3232, {wxStyledTextCtrl, pageUpExtend, 0}}, - {3233, {wxStyledTextCtrl, pageDown, 0}}, - {3234, {wxStyledTextCtrl, pageDownExtend, 0}}, - {3235, {wxStyledTextCtrl, editToggleOvertype, 0}}, - {3236, {wxStyledTextCtrl, cancel, 0}}, - {3237, {wxStyledTextCtrl, deleteBack, 0}}, - {3238, {wxStyledTextCtrl, tab, 0}}, - {3239, {wxStyledTextCtrl, backTab, 0}}, - {3240, {wxStyledTextCtrl, newLine, 0}}, - {3241, {wxStyledTextCtrl, formFeed, 0}}, - {3242, {wxStyledTextCtrl, vCHome, 0}}, - {3243, {wxStyledTextCtrl, vCHomeExtend, 0}}, - {3244, {wxStyledTextCtrl, zoomIn, 0}}, - {3245, {wxStyledTextCtrl, zoomOut, 0}}, - {3246, {wxStyledTextCtrl, delWordLeft, 0}}, - {3247, {wxStyledTextCtrl, delWordRight, 0}}, - {3248, {wxStyledTextCtrl, lineCut, 0}}, - {3249, {wxStyledTextCtrl, lineDelete, 0}}, - {3250, {wxStyledTextCtrl, lineTranspose, 0}}, - {3251, {wxStyledTextCtrl, lineDuplicate, 0}}, - {3252, {wxStyledTextCtrl, lowerCase, 0}}, - {3253, {wxStyledTextCtrl, upperCase, 0}}, - {3254, {wxStyledTextCtrl, lineScrollDown, 0}}, - {3255, {wxStyledTextCtrl, lineScrollUp, 0}}, - {3256, {wxStyledTextCtrl, deleteBackNotLine, 0}}, - {3257, {wxStyledTextCtrl, homeDisplay, 0}}, - {3258, {wxStyledTextCtrl, homeDisplayExtend, 0}}, - {3259, {wxStyledTextCtrl, lineEndDisplay, 0}}, - {3260, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, - {3261, {wxStyledTextCtrl, homeWrapExtend, 0}}, - {3262, {wxStyledTextCtrl, lineEndWrap, 0}}, - {3263, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, - {3264, {wxStyledTextCtrl, vCHomeWrap, 0}}, - {3265, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, - {3266, {wxStyledTextCtrl, lineCopy, 0}}, - {3267, {wxStyledTextCtrl, moveCaretInsideView, 0}}, - {3268, {wxStyledTextCtrl, lineLength, 1}}, - {3269, {wxStyledTextCtrl, braceHighlight, 2}}, - {3270, {wxStyledTextCtrl, braceBadLight, 1}}, - {3271, {wxStyledTextCtrl, braceMatch, 1}}, - {3272, {wxStyledTextCtrl, getViewEOL, 0}}, - {3273, {wxStyledTextCtrl, setViewEOL, 1}}, - {3274, {wxStyledTextCtrl, setModEventMask, 1}}, - {3275, {wxStyledTextCtrl, getEdgeColumn, 0}}, - {3276, {wxStyledTextCtrl, setEdgeColumn, 1}}, - {3277, {wxStyledTextCtrl, setEdgeMode, 1}}, - {3278, {wxStyledTextCtrl, getEdgeMode, 0}}, - {3279, {wxStyledTextCtrl, getEdgeColour, 0}}, - {3280, {wxStyledTextCtrl, setEdgeColour, 1}}, - {3281, {wxStyledTextCtrl, searchAnchor, 0}}, - {3282, {wxStyledTextCtrl, searchNext, 2}}, - {3283, {wxStyledTextCtrl, searchPrev, 2}}, - {3284, {wxStyledTextCtrl, linesOnScreen, 0}}, - {3285, {wxStyledTextCtrl, usePopUp, 1}}, - {3286, {wxStyledTextCtrl, selectionIsRectangle, 0}}, - {3287, {wxStyledTextCtrl, setZoom, 1}}, - {3288, {wxStyledTextCtrl, getZoom, 0}}, - {3289, {wxStyledTextCtrl, getModEventMask, 0}}, - {3290, {wxStyledTextCtrl, setSTCFocus, 1}}, - {3291, {wxStyledTextCtrl, getSTCFocus, 0}}, - {3292, {wxStyledTextCtrl, setStatus, 1}}, - {3293, {wxStyledTextCtrl, getStatus, 0}}, - {3294, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, - {3295, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, - {3296, {wxStyledTextCtrl, setSTCCursor, 1}}, - {3297, {wxStyledTextCtrl, getSTCCursor, 0}}, - {3298, {wxStyledTextCtrl, setControlCharSymbol, 1}}, - {3299, {wxStyledTextCtrl, getControlCharSymbol, 0}}, - {3300, {wxStyledTextCtrl, wordPartLeft, 0}}, - {3301, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, - {3302, {wxStyledTextCtrl, wordPartRight, 0}}, - {3303, {wxStyledTextCtrl, wordPartRightExtend, 0}}, - {3304, {wxStyledTextCtrl, setVisiblePolicy, 2}}, - {3305, {wxStyledTextCtrl, delLineLeft, 0}}, - {3306, {wxStyledTextCtrl, delLineRight, 0}}, - {3307, {wxStyledTextCtrl, getXOffset, 0}}, - {3308, {wxStyledTextCtrl, chooseCaretX, 0}}, - {3309, {wxStyledTextCtrl, setXCaretPolicy, 2}}, - {3310, {wxStyledTextCtrl, setYCaretPolicy, 2}}, - {3311, {wxStyledTextCtrl, getPrintWrapMode, 0}}, - {3312, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, - {3313, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, - {3314, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, - {3315, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, - {3316, {wxStyledTextCtrl, paraDownExtend, 0}}, - {3317, {wxStyledTextCtrl, paraUp, 0}}, - {3318, {wxStyledTextCtrl, paraUpExtend, 0}}, - {3319, {wxStyledTextCtrl, positionBefore, 1}}, - {3320, {wxStyledTextCtrl, positionAfter, 1}}, - {3321, {wxStyledTextCtrl, copyRange, 2}}, - {3322, {wxStyledTextCtrl, copyText, 2}}, - {3323, {wxStyledTextCtrl, setSelectionMode, 1}}, - {3324, {wxStyledTextCtrl, getSelectionMode, 0}}, - {3325, {wxStyledTextCtrl, lineDownRectExtend, 0}}, - {3326, {wxStyledTextCtrl, lineUpRectExtend, 0}}, - {3327, {wxStyledTextCtrl, charLeftRectExtend, 0}}, - {3328, {wxStyledTextCtrl, charRightRectExtend, 0}}, - {3329, {wxStyledTextCtrl, homeRectExtend, 0}}, - {3330, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, - {3331, {wxStyledTextCtrl, lineEndRectExtend, 0}}, - {3332, {wxStyledTextCtrl, pageUpRectExtend, 0}}, - {3333, {wxStyledTextCtrl, pageDownRectExtend, 0}}, - {3334, {wxStyledTextCtrl, stutteredPageUp, 0}}, - {3335, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, - {3336, {wxStyledTextCtrl, stutteredPageDown, 0}}, - {3337, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, - {3338, {wxStyledTextCtrl, wordLeftEnd, 0}}, - {3339, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, - {3340, {wxStyledTextCtrl, wordRightEnd, 0}}, - {3341, {wxStyledTextCtrl, wordRightEndExtend, 0}}, - {3342, {wxStyledTextCtrl, setWhitespaceChars, 1}}, - {3343, {wxStyledTextCtrl, setCharsDefault, 0}}, - {3344, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, - {3345, {wxStyledTextCtrl, allocate, 1}}, - {3346, {wxStyledTextCtrl, findColumn, 2}}, - {3347, {wxStyledTextCtrl, getCaretSticky, 0}}, - {3348, {wxStyledTextCtrl, setCaretSticky, 1}}, - {3349, {wxStyledTextCtrl, toggleCaretSticky, 0}}, - {3350, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, - {3351, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, - {3352, {wxStyledTextCtrl, selectionDuplicate, 0}}, - {3353, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, - {3354, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, - {3355, {wxStyledTextCtrl, startRecord, 0}}, - {3356, {wxStyledTextCtrl, stopRecord, 0}}, - {3357, {wxStyledTextCtrl, setLexer, 1}}, - {3358, {wxStyledTextCtrl, getLexer, 0}}, - {3359, {wxStyledTextCtrl, colourise, 2}}, - {3360, {wxStyledTextCtrl, setProperty, 2}}, - {3361, {wxStyledTextCtrl, setKeyWords, 2}}, - {3362, {wxStyledTextCtrl, setLexerLanguage, 1}}, - {3363, {wxStyledTextCtrl, getProperty, 1}}, - {3364, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, - {3365, {wxStyledTextCtrl, getCurrentLine, 0}}, - {3366, {wxStyledTextCtrl, styleSetSpec, 2}}, - {3367, {wxStyledTextCtrl, styleSetFont, 2}}, - {3368, {wxStyledTextCtrl, styleSetFontAttr, 7}}, - {3369, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, - {3370, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, - {3371, {wxStyledTextCtrl, cmdKeyExecute, 1}}, - {3372, {wxStyledTextCtrl, setMargins, 2}}, - {3373, {wxStyledTextCtrl, getSelection, 2}}, - {3374, {wxStyledTextCtrl, pointFromPosition, 1}}, - {3375, {wxStyledTextCtrl, scrollToLine, 1}}, - {3376, {wxStyledTextCtrl, scrollToColumn, 1}}, - {3377, {wxStyledTextCtrl, setVScrollBar, 1}}, - {3378, {wxStyledTextCtrl, setHScrollBar, 1}}, - {3379, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, - {3380, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, - {3381, {wxStyledTextCtrl, saveFile, 1}}, - {3382, {wxStyledTextCtrl, loadFile, 1}}, - {3383, {wxStyledTextCtrl, doDragOver, 3}}, - {3384, {wxStyledTextCtrl, doDropText, 3}}, - {3385, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, - {3386, {wxStyledTextCtrl, addTextRaw, 1}}, - {3387, {wxStyledTextCtrl, insertTextRaw, 2}}, - {3388, {wxStyledTextCtrl, getCurLineRaw, 1}}, - {3389, {wxStyledTextCtrl, getLineRaw, 1}}, - {3390, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, - {3391, {wxStyledTextCtrl, getTextRangeRaw, 2}}, - {3392, {wxStyledTextCtrl, setTextRaw, 1}}, - {3393, {wxStyledTextCtrl, getTextRaw, 0}}, - {3394, {wxStyledTextCtrl, appendTextRaw, 1}}, - {3395, {wxArtProvider, getBitmap, 2}}, - {3396, {wxArtProvider, getIcon, 2}}, - {3397, {wxTreeEvent, getKeyCode, 0}}, - {3398, {wxTreeEvent, getItem, 0}}, - {3399, {wxTreeEvent, getKeyEvent, 0}}, - {3400, {wxTreeEvent, getLabel, 0}}, - {3401, {wxTreeEvent, getOldItem, 0}}, - {3402, {wxTreeEvent, getPoint, 0}}, - {3403, {wxTreeEvent, isEditCancelled, 0}}, - {3404, {wxTreeEvent, setToolTip, 1}}, - {3405, {wxNotebookEvent, getOldSelection, 0}}, - {3406, {wxNotebookEvent, getSelection, 0}}, - {3407, {wxNotebookEvent, setOldSelection, 1}}, - {3408, {wxNotebookEvent, setSelection, 1}}, - {3409, {wxFileDataObject, new, 0}}, - {3410, {wxFileDataObject, addFile, 1}}, - {3411, {wxFileDataObject, getFilenames, 0}}, - {3412, {wxFileDataObject, 'Destroy', undefined}}, - {3413, {wxTextDataObject, new, 1}}, - {3414, {wxTextDataObject, getTextLength, 0}}, - {3415, {wxTextDataObject, getText, 0}}, - {3416, {wxTextDataObject, setText, 1}}, - {3417, {wxTextDataObject, 'Destroy', undefined}}, - {3418, {wxBitmapDataObject, new_1_1, 1}}, - {3419, {wxBitmapDataObject, new_1_0, 1}}, - {3420, {wxBitmapDataObject, getBitmap, 0}}, - {3421, {wxBitmapDataObject, setBitmap, 1}}, - {3422, {wxBitmapDataObject, 'Destroy', undefined}}, - {3424, {wxClipboard, new, 0}}, - {3425, {wxClipboard, destruct, 0}}, - {3426, {wxClipboard, addData, 1}}, - {3427, {wxClipboard, clear, 0}}, - {3428, {wxClipboard, close, 0}}, - {3429, {wxClipboard, flush, 0}}, - {3430, {wxClipboard, getData, 1}}, - {3431, {wxClipboard, isOpened, 0}}, - {3432, {wxClipboard, open, 0}}, - {3433, {wxClipboard, setData, 1}}, - {3435, {wxClipboard, usePrimarySelection, 1}}, - {3436, {wxClipboard, isSupported, 1}}, - {3437, {wxClipboard, get, 0}}, - {3438, {wxSpinEvent, getPosition, 0}}, - {3439, {wxSpinEvent, setPosition, 1}}, - {3440, {wxSplitterWindow, new_0, 0}}, - {3441, {wxSplitterWindow, new_2, 2}}, - {3442, {wxSplitterWindow, destruct, 0}}, - {3443, {wxSplitterWindow, create, 2}}, - {3444, {wxSplitterWindow, getMinimumPaneSize, 0}}, - {3445, {wxSplitterWindow, getSashGravity, 0}}, - {3446, {wxSplitterWindow, getSashPosition, 0}}, - {3447, {wxSplitterWindow, getSplitMode, 0}}, - {3448, {wxSplitterWindow, getWindow1, 0}}, - {3449, {wxSplitterWindow, getWindow2, 0}}, - {3450, {wxSplitterWindow, initialize, 1}}, - {3451, {wxSplitterWindow, isSplit, 0}}, - {3452, {wxSplitterWindow, replaceWindow, 2}}, - {3453, {wxSplitterWindow, setSashGravity, 1}}, - {3454, {wxSplitterWindow, setSashPosition, 2}}, - {3455, {wxSplitterWindow, setSashSize, 1}}, - {3456, {wxSplitterWindow, setMinimumPaneSize, 1}}, - {3457, {wxSplitterWindow, setSplitMode, 1}}, - {3458, {wxSplitterWindow, splitHorizontally, 3}}, - {3459, {wxSplitterWindow, splitVertically, 3}}, - {3460, {wxSplitterWindow, unsplit, 1}}, - {3461, {wxSplitterWindow, updateSize, 0}}, - {3462, {wxSplitterEvent, getSashPosition, 0}}, - {3463, {wxSplitterEvent, getX, 0}}, - {3464, {wxSplitterEvent, getY, 0}}, - {3465, {wxSplitterEvent, getWindowBeingRemoved, 0}}, - {3466, {wxSplitterEvent, setSashPosition, 1}}, - {3467, {wxHtmlWindow, new_0, 0}}, - {3468, {wxHtmlWindow, new_2, 2}}, - {3469, {wxHtmlWindow, appendToPage, 1}}, - {3470, {wxHtmlWindow, getOpenedAnchor, 0}}, - {3471, {wxHtmlWindow, getOpenedPage, 0}}, - {3472, {wxHtmlWindow, getOpenedPageTitle, 0}}, - {3473, {wxHtmlWindow, getRelatedFrame, 0}}, - {3474, {wxHtmlWindow, historyBack, 0}}, - {3475, {wxHtmlWindow, historyCanBack, 0}}, - {3476, {wxHtmlWindow, historyCanForward, 0}}, - {3477, {wxHtmlWindow, historyClear, 0}}, - {3478, {wxHtmlWindow, historyForward, 0}}, - {3479, {wxHtmlWindow, loadFile, 1}}, - {3480, {wxHtmlWindow, loadPage, 1}}, - {3481, {wxHtmlWindow, selectAll, 0}}, - {3482, {wxHtmlWindow, selectionToText, 0}}, - {3483, {wxHtmlWindow, selectLine, 1}}, - {3484, {wxHtmlWindow, selectWord, 1}}, - {3485, {wxHtmlWindow, setBorders, 1}}, - {3486, {wxHtmlWindow, setFonts, 3}}, - {3487, {wxHtmlWindow, setPage, 1}}, - {3488, {wxHtmlWindow, setRelatedFrame, 2}}, - {3489, {wxHtmlWindow, setRelatedStatusBar, 1}}, - {3490, {wxHtmlWindow, toText, 0}}, - {3491, {wxHtmlWindow, 'Destroy', undefined}}, - {3492, {wxHtmlLinkEvent, getLinkInfo, 0}}, - {3493, {wxSystemSettings, getColour, 1}}, - {3494, {wxSystemSettings, getFont, 1}}, - {3495, {wxSystemSettings, getMetric, 2}}, - {3496, {wxSystemSettings, getScreenType, 0}}, - {3497, {wxSystemOptions, getOption, 1}}, - {3498, {wxSystemOptions, getOptionInt, 1}}, - {3499, {wxSystemOptions, hasOption, 1}}, - {3500, {wxSystemOptions, isFalse, 1}}, - {3501, {wxSystemOptions, setOption_2_1, 2}}, - {3502, {wxSystemOptions, setOption_2_0, 2}}, - {3503, {wxAuiNotebookEvent, setSelection, 1}}, - {3504, {wxAuiNotebookEvent, getSelection, 0}}, - {3505, {wxAuiNotebookEvent, setOldSelection, 1}}, - {3506, {wxAuiNotebookEvent, getOldSelection, 0}}, - {3507, {wxAuiNotebookEvent, setDragSource, 1}}, - {3508, {wxAuiNotebookEvent, getDragSource, 0}}, - {3509, {wxAuiManagerEvent, setManager, 1}}, - {3510, {wxAuiManagerEvent, getManager, 0}}, - {3511, {wxAuiManagerEvent, setPane, 1}}, - {3512, {wxAuiManagerEvent, getPane, 0}}, - {3513, {wxAuiManagerEvent, setButton, 1}}, - {3514, {wxAuiManagerEvent, getButton, 0}}, - {3515, {wxAuiManagerEvent, setDC, 1}}, - {3516, {wxAuiManagerEvent, getDC, 0}}, - {3517, {wxAuiManagerEvent, veto, 1}}, - {3518, {wxAuiManagerEvent, getVeto, 0}}, - {3519, {wxAuiManagerEvent, setCanVeto, 1}}, - {3520, {wxAuiManagerEvent, canVeto, 0}}, - {3521, {wxLogNull, new, 0}}, - {3522, {wxLogNull, 'Destroy', undefined}}, - {3523, {wxTaskBarIcon, new, 0}}, - {3524, {wxTaskBarIcon, destruct, 0}}, - {3525, {wxTaskBarIcon, popupMenu, 1}}, - {3526, {wxTaskBarIcon, removeIcon, 0}}, - {3527, {wxTaskBarIcon, setIcon, 2}}, - {3528, {wxLocale, new_0, 0}}, - {3530, {wxLocale, new_2, 2}}, - {3531, {wxLocale, destruct, 0}}, - {3533, {wxLocale, init, 1}}, - {3534, {wxLocale, addCatalog_1, 1}}, - {3535, {wxLocale, addCatalog_3, 3}}, - {3536, {wxLocale, addCatalogLookupPathPrefix, 1}}, - {3537, {wxLocale, getCanonicalName, 0}}, - {3538, {wxLocale, getLanguage, 0}}, - {3539, {wxLocale, getLanguageName, 1}}, - {3540, {wxLocale, getLocale, 0}}, - {3541, {wxLocale, getName, 0}}, - {3542, {wxLocale, getString_2, 2}}, - {3543, {wxLocale, getString_4, 4}}, - {3544, {wxLocale, getHeaderValue, 2}}, - {3545, {wxLocale, getSysName, 0}}, - {3546, {wxLocale, getSystemEncoding, 0}}, - {3547, {wxLocale, getSystemEncodingName, 0}}, - {3548, {wxLocale, getSystemLanguage, 0}}, - {3549, {wxLocale, isLoaded, 1}}, - {3550, {wxLocale, isOk, 0}}, - {3551, {wxActivateEvent, getActive, 0}}, - {3553, {wxPopupWindow, new_2, 2}}, - {3554, {wxPopupWindow, new_0, 0}}, - {3556, {wxPopupWindow, destruct, 0}}, - {3557, {wxPopupWindow, create, 2}}, - {3558, {wxPopupWindow, position, 2}}, - {3559, {wxPopupTransientWindow, new_0, 0}}, - {3560, {wxPopupTransientWindow, new_2, 2}}, - {3561, {wxPopupTransientWindow, destruct, 0}}, - {3562, {wxPopupTransientWindow, popup, 1}}, - {3563, {wxPopupTransientWindow, dismiss, 0}}, + {2675, {wxAuiTabArt, setFlags, 1}}, + {2676, {wxAuiTabArt, setMeasuringFont, 1}}, + {2677, {wxAuiTabArt, setNormalFont, 1}}, + {2678, {wxAuiTabArt, setSelectedFont, 1}}, + {2679, {wxAuiTabArt, setColour, 1}}, + {2680, {wxAuiTabArt, setActiveColour, 1}}, + {2681, {wxAuiDockArt, getColour, 1}}, + {2682, {wxAuiDockArt, getFont, 1}}, + {2683, {wxAuiDockArt, getMetric, 1}}, + {2684, {wxAuiDockArt, setColour, 2}}, + {2685, {wxAuiDockArt, setFont, 2}}, + {2686, {wxAuiDockArt, setMetric, 2}}, + {2687, {wxAuiSimpleTabArt, new, 0}}, + {2688, {wxAuiSimpleTabArt, 'Destroy', undefined}}, + {2689, {wxMDIParentFrame, new_0, 0}}, + {2690, {wxMDIParentFrame, new_4, 4}}, + {2691, {wxMDIParentFrame, destruct, 0}}, + {2692, {wxMDIParentFrame, activateNext, 0}}, + {2693, {wxMDIParentFrame, activatePrevious, 0}}, + {2694, {wxMDIParentFrame, arrangeIcons, 0}}, + {2695, {wxMDIParentFrame, cascade, 0}}, + {2696, {wxMDIParentFrame, create, 4}}, + {2697, {wxMDIParentFrame, getActiveChild, 0}}, + {2698, {wxMDIParentFrame, getClientWindow, 0}}, + {2699, {wxMDIParentFrame, tile, 1}}, + {2700, {wxMDIChildFrame, new_0, 0}}, + {2701, {wxMDIChildFrame, new_4, 4}}, + {2702, {wxMDIChildFrame, destruct, 0}}, + {2703, {wxMDIChildFrame, activate, 0}}, + {2704, {wxMDIChildFrame, create, 4}}, + {2705, {wxMDIChildFrame, maximize, 1}}, + {2706, {wxMDIChildFrame, restore, 0}}, + {2707, {wxMDIClientWindow, new_0, 0}}, + {2708, {wxMDIClientWindow, new_2, 2}}, + {2709, {wxMDIClientWindow, destruct, 0}}, + {2710, {wxMDIClientWindow, createClient, 2}}, + {2711, {wxLayoutAlgorithm, new, 0}}, + {2712, {wxLayoutAlgorithm, layoutFrame, 2}}, + {2713, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, + {2714, {wxLayoutAlgorithm, layoutWindow, 2}}, + {2715, {wxLayoutAlgorithm, 'Destroy', undefined}}, + {2716, {wxEvent, getId, 0}}, + {2717, {wxEvent, getSkipped, 0}}, + {2718, {wxEvent, getTimestamp, 0}}, + {2719, {wxEvent, isCommandEvent, 0}}, + {2720, {wxEvent, resumePropagation, 1}}, + {2721, {wxEvent, shouldPropagate, 0}}, + {2722, {wxEvent, skip, 1}}, + {2723, {wxEvent, stopPropagation, 0}}, + {2724, {wxCommandEvent, getClientData, 0}}, + {2725, {wxCommandEvent, getExtraLong, 0}}, + {2726, {wxCommandEvent, getInt, 0}}, + {2727, {wxCommandEvent, getSelection, 0}}, + {2728, {wxCommandEvent, getString, 0}}, + {2729, {wxCommandEvent, isChecked, 0}}, + {2730, {wxCommandEvent, isSelection, 0}}, + {2731, {wxCommandEvent, setInt, 1}}, + {2732, {wxCommandEvent, setString, 1}}, + {2733, {wxScrollEvent, getOrientation, 0}}, + {2734, {wxScrollEvent, getPosition, 0}}, + {2735, {wxScrollWinEvent, getOrientation, 0}}, + {2736, {wxScrollWinEvent, getPosition, 0}}, + {2737, {wxMouseEvent, altDown, 0}}, + {2738, {wxMouseEvent, button, 1}}, + {2739, {wxMouseEvent, buttonDClick, 1}}, + {2740, {wxMouseEvent, buttonDown, 1}}, + {2741, {wxMouseEvent, buttonUp, 1}}, + {2742, {wxMouseEvent, cmdDown, 0}}, + {2743, {wxMouseEvent, controlDown, 0}}, + {2744, {wxMouseEvent, dragging, 0}}, + {2745, {wxMouseEvent, entering, 0}}, + {2746, {wxMouseEvent, getButton, 0}}, + {2749, {wxMouseEvent, getPosition, 0}}, + {2750, {wxMouseEvent, getLogicalPosition, 1}}, + {2751, {wxMouseEvent, getLinesPerAction, 0}}, + {2752, {wxMouseEvent, getWheelRotation, 0}}, + {2753, {wxMouseEvent, getWheelDelta, 0}}, + {2754, {wxMouseEvent, getX, 0}}, + {2755, {wxMouseEvent, getY, 0}}, + {2756, {wxMouseEvent, isButton, 0}}, + {2757, {wxMouseEvent, isPageScroll, 0}}, + {2758, {wxMouseEvent, leaving, 0}}, + {2759, {wxMouseEvent, leftDClick, 0}}, + {2760, {wxMouseEvent, leftDown, 0}}, + {2761, {wxMouseEvent, leftIsDown, 0}}, + {2762, {wxMouseEvent, leftUp, 0}}, + {2763, {wxMouseEvent, metaDown, 0}}, + {2764, {wxMouseEvent, middleDClick, 0}}, + {2765, {wxMouseEvent, middleDown, 0}}, + {2766, {wxMouseEvent, middleIsDown, 0}}, + {2767, {wxMouseEvent, middleUp, 0}}, + {2768, {wxMouseEvent, moving, 0}}, + {2769, {wxMouseEvent, rightDClick, 0}}, + {2770, {wxMouseEvent, rightDown, 0}}, + {2771, {wxMouseEvent, rightIsDown, 0}}, + {2772, {wxMouseEvent, rightUp, 0}}, + {2773, {wxMouseEvent, shiftDown, 0}}, + {2774, {wxSetCursorEvent, getCursor, 0}}, + {2775, {wxSetCursorEvent, getX, 0}}, + {2776, {wxSetCursorEvent, getY, 0}}, + {2777, {wxSetCursorEvent, hasCursor, 0}}, + {2778, {wxSetCursorEvent, setCursor, 1}}, + {2779, {wxKeyEvent, altDown, 0}}, + {2780, {wxKeyEvent, cmdDown, 0}}, + {2781, {wxKeyEvent, controlDown, 0}}, + {2782, {wxKeyEvent, getKeyCode, 0}}, + {2783, {wxKeyEvent, getModifiers, 0}}, + {2786, {wxKeyEvent, getPosition, 0}}, + {2787, {wxKeyEvent, getRawKeyCode, 0}}, + {2788, {wxKeyEvent, getRawKeyFlags, 0}}, + {2789, {wxKeyEvent, getUnicodeKey, 0}}, + {2790, {wxKeyEvent, getX, 0}}, + {2791, {wxKeyEvent, getY, 0}}, + {2792, {wxKeyEvent, hasModifiers, 0}}, + {2793, {wxKeyEvent, metaDown, 0}}, + {2794, {wxKeyEvent, shiftDown, 0}}, + {2795, {wxSizeEvent, getSize, 0}}, + {2796, {wxMoveEvent, getPosition, 0}}, + {2797, {wxEraseEvent, getDC, 0}}, + {2798, {wxFocusEvent, getWindow, 0}}, + {2799, {wxChildFocusEvent, getWindow, 0}}, + {2800, {wxMenuEvent, getMenu, 0}}, + {2801, {wxMenuEvent, getMenuId, 0}}, + {2802, {wxMenuEvent, isPopup, 0}}, + {2803, {wxCloseEvent, canVeto, 0}}, + {2804, {wxCloseEvent, getLoggingOff, 0}}, + {2805, {wxCloseEvent, setCanVeto, 1}}, + {2806, {wxCloseEvent, setLoggingOff, 1}}, + {2807, {wxCloseEvent, veto, 1}}, + {2808, {wxShowEvent, setShow, 1}}, + {2809, {wxShowEvent, getShow, 0}}, + {2810, {wxIconizeEvent, iconized, 0}}, + {2811, {wxJoystickEvent, buttonDown, 1}}, + {2812, {wxJoystickEvent, buttonIsDown, 1}}, + {2813, {wxJoystickEvent, buttonUp, 1}}, + {2814, {wxJoystickEvent, getButtonChange, 0}}, + {2815, {wxJoystickEvent, getButtonState, 0}}, + {2816, {wxJoystickEvent, getJoystick, 0}}, + {2817, {wxJoystickEvent, getPosition, 0}}, + {2818, {wxJoystickEvent, getZPosition, 0}}, + {2819, {wxJoystickEvent, isButton, 0}}, + {2820, {wxJoystickEvent, isMove, 0}}, + {2821, {wxJoystickEvent, isZMove, 0}}, + {2822, {wxUpdateUIEvent, canUpdate, 1}}, + {2823, {wxUpdateUIEvent, check, 1}}, + {2824, {wxUpdateUIEvent, enable, 1}}, + {2825, {wxUpdateUIEvent, show, 1}}, + {2826, {wxUpdateUIEvent, getChecked, 0}}, + {2827, {wxUpdateUIEvent, getEnabled, 0}}, + {2828, {wxUpdateUIEvent, getShown, 0}}, + {2829, {wxUpdateUIEvent, getSetChecked, 0}}, + {2830, {wxUpdateUIEvent, getSetEnabled, 0}}, + {2831, {wxUpdateUIEvent, getSetShown, 0}}, + {2832, {wxUpdateUIEvent, getSetText, 0}}, + {2833, {wxUpdateUIEvent, getText, 0}}, + {2834, {wxUpdateUIEvent, getMode, 0}}, + {2835, {wxUpdateUIEvent, getUpdateInterval, 0}}, + {2836, {wxUpdateUIEvent, resetUpdateTime, 0}}, + {2837, {wxUpdateUIEvent, setMode, 1}}, + {2838, {wxUpdateUIEvent, setText, 1}}, + {2839, {wxUpdateUIEvent, setUpdateInterval, 1}}, + {2840, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, + {2841, {wxPaletteChangedEvent, setChangedWindow, 1}}, + {2842, {wxPaletteChangedEvent, getChangedWindow, 0}}, + {2843, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, + {2844, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, + {2845, {wxNavigationKeyEvent, getDirection, 0}}, + {2846, {wxNavigationKeyEvent, setDirection, 1}}, + {2847, {wxNavigationKeyEvent, isWindowChange, 0}}, + {2848, {wxNavigationKeyEvent, setWindowChange, 1}}, + {2849, {wxNavigationKeyEvent, isFromTab, 0}}, + {2850, {wxNavigationKeyEvent, setFromTab, 1}}, + {2851, {wxNavigationKeyEvent, getCurrentFocus, 0}}, + {2852, {wxNavigationKeyEvent, setCurrentFocus, 1}}, + {2853, {wxHelpEvent, getOrigin, 0}}, + {2854, {wxHelpEvent, getPosition, 0}}, + {2855, {wxHelpEvent, setOrigin, 1}}, + {2856, {wxHelpEvent, setPosition, 1}}, + {2857, {wxContextMenuEvent, getPosition, 0}}, + {2858, {wxContextMenuEvent, setPosition, 1}}, + {2859, {wxIdleEvent, canSend, 1}}, + {2860, {wxIdleEvent, getMode, 0}}, + {2861, {wxIdleEvent, requestMore, 1}}, + {2862, {wxIdleEvent, moreRequested, 0}}, + {2863, {wxIdleEvent, setMode, 1}}, + {2864, {wxGridEvent, altDown, 0}}, + {2865, {wxGridEvent, controlDown, 0}}, + {2866, {wxGridEvent, getCol, 0}}, + {2867, {wxGridEvent, getPosition, 0}}, + {2868, {wxGridEvent, getRow, 0}}, + {2869, {wxGridEvent, metaDown, 0}}, + {2870, {wxGridEvent, selecting, 0}}, + {2871, {wxGridEvent, shiftDown, 0}}, + {2872, {wxNotifyEvent, allow, 0}}, + {2873, {wxNotifyEvent, isAllowed, 0}}, + {2874, {wxNotifyEvent, veto, 0}}, + {2875, {wxSashEvent, getEdge, 0}}, + {2876, {wxSashEvent, getDragRect, 0}}, + {2877, {wxSashEvent, getDragStatus, 0}}, + {2878, {wxListEvent, getCacheFrom, 0}}, + {2879, {wxListEvent, getCacheTo, 0}}, + {2880, {wxListEvent, getKeyCode, 0}}, + {2881, {wxListEvent, getIndex, 0}}, + {2882, {wxListEvent, getColumn, 0}}, + {2883, {wxListEvent, getPoint, 0}}, + {2884, {wxListEvent, getLabel, 0}}, + {2885, {wxListEvent, getText, 0}}, + {2886, {wxListEvent, getImage, 0}}, + {2887, {wxListEvent, getData, 0}}, + {2888, {wxListEvent, getMask, 0}}, + {2889, {wxListEvent, getItem, 0}}, + {2890, {wxListEvent, isEditCancelled, 0}}, + {2891, {wxDateEvent, getDate, 0}}, + {2892, {wxCalendarEvent, getWeekDay, 0}}, + {2893, {wxFileDirPickerEvent, getPath, 0}}, + {2894, {wxColourPickerEvent, getColour, 0}}, + {2895, {wxFontPickerEvent, getFont, 0}}, + {2896, {wxStyledTextEvent, getPosition, 0}}, + {2897, {wxStyledTextEvent, getKey, 0}}, + {2898, {wxStyledTextEvent, getModifiers, 0}}, + {2899, {wxStyledTextEvent, getModificationType, 0}}, + {2900, {wxStyledTextEvent, getText, 0}}, + {2901, {wxStyledTextEvent, getLength, 0}}, + {2902, {wxStyledTextEvent, getLinesAdded, 0}}, + {2903, {wxStyledTextEvent, getLine, 0}}, + {2904, {wxStyledTextEvent, getFoldLevelNow, 0}}, + {2905, {wxStyledTextEvent, getFoldLevelPrev, 0}}, + {2906, {wxStyledTextEvent, getMargin, 0}}, + {2907, {wxStyledTextEvent, getMessage, 0}}, + {2908, {wxStyledTextEvent, getWParam, 0}}, + {2909, {wxStyledTextEvent, getLParam, 0}}, + {2910, {wxStyledTextEvent, getListType, 0}}, + {2911, {wxStyledTextEvent, getX, 0}}, + {2912, {wxStyledTextEvent, getY, 0}}, + {2913, {wxStyledTextEvent, getDragText, 0}}, + {2914, {wxStyledTextEvent, getDragAllowMove, 0}}, + {2915, {wxStyledTextEvent, getDragResult, 0}}, + {2916, {wxStyledTextEvent, getShift, 0}}, + {2917, {wxStyledTextEvent, getControl, 0}}, + {2918, {wxStyledTextEvent, getAlt, 0}}, + {2919, {utils, getKeyState, 1}}, + {2920, {utils, getMousePosition, 2}}, + {2921, {utils, getMouseState, 0}}, + {2922, {utils, setDetectableAutoRepeat, 1}}, + {2923, {utils, bell, 0}}, + {2924, {utils, findMenuItemId, 3}}, + {2925, {utils, genericFindWindowAtPoint, 1}}, + {2926, {utils, findWindowAtPoint, 1}}, + {2927, {utils, beginBusyCursor, 1}}, + {2928, {utils, endBusyCursor, 0}}, + {2929, {utils, isBusy, 0}}, + {2930, {utils, shutdown, 1}}, + {2931, {utils, shell, 1}}, + {2932, {utils, launchDefaultBrowser, 2}}, + {2933, {utils, getEmailAddress, 0}}, + {2934, {utils, getUserId, 0}}, + {2935, {utils, getHomeDir, 0}}, + {2936, {utils, newId, 0}}, + {2937, {utils, registerId, 1}}, + {2938, {utils, getCurrentId, 0}}, + {2939, {utils, getOsDescription, 0}}, + {2940, {utils, isPlatformLittleEndian, 0}}, + {2941, {utils, isPlatform64Bit, 0}}, + {2942, {gdicmn, displaySize, 2}}, + {2943, {gdicmn, setCursor, 1}}, + {2944, {wxPrintout, new, 1}}, + {2945, {wxPrintout, destruct, 0}}, + {2946, {wxPrintout, getDC, 0}}, + {2947, {wxPrintout, getPageSizeMM, 2}}, + {2948, {wxPrintout, getPageSizePixels, 2}}, + {2949, {wxPrintout, getPaperRectPixels, 0}}, + {2950, {wxPrintout, getPPIPrinter, 2}}, + {2951, {wxPrintout, getPPIScreen, 2}}, + {2952, {wxPrintout, getTitle, 0}}, + {2953, {wxPrintout, isPreview, 0}}, + {2954, {wxPrintout, fitThisSizeToPaper, 1}}, + {2955, {wxPrintout, fitThisSizeToPage, 1}}, + {2956, {wxPrintout, fitThisSizeToPageMargins, 2}}, + {2957, {wxPrintout, mapScreenSizeToPaper, 0}}, + {2958, {wxPrintout, mapScreenSizeToPage, 0}}, + {2959, {wxPrintout, mapScreenSizeToPageMargins, 1}}, + {2960, {wxPrintout, mapScreenSizeToDevice, 0}}, + {2961, {wxPrintout, getLogicalPaperRect, 0}}, + {2962, {wxPrintout, getLogicalPageRect, 0}}, + {2963, {wxPrintout, getLogicalPageMarginsRect, 1}}, + {2964, {wxPrintout, setLogicalOrigin, 2}}, + {2965, {wxPrintout, offsetLogicalOrigin, 2}}, + {2966, {wxStyledTextCtrl, new_2, 2}}, + {2967, {wxStyledTextCtrl, new_0, 0}}, + {2968, {wxStyledTextCtrl, destruct, 0}}, + {2969, {wxStyledTextCtrl, create, 2}}, + {2970, {wxStyledTextCtrl, addText, 1}}, + {2971, {wxStyledTextCtrl, addStyledText, 1}}, + {2972, {wxStyledTextCtrl, insertText, 2}}, + {2973, {wxStyledTextCtrl, clearAll, 0}}, + {2974, {wxStyledTextCtrl, clearDocumentStyle, 0}}, + {2975, {wxStyledTextCtrl, getLength, 0}}, + {2976, {wxStyledTextCtrl, getCharAt, 1}}, + {2977, {wxStyledTextCtrl, getCurrentPos, 0}}, + {2978, {wxStyledTextCtrl, getAnchor, 0}}, + {2979, {wxStyledTextCtrl, getStyleAt, 1}}, + {2980, {wxStyledTextCtrl, redo, 0}}, + {2981, {wxStyledTextCtrl, setUndoCollection, 1}}, + {2982, {wxStyledTextCtrl, selectAll, 0}}, + {2983, {wxStyledTextCtrl, setSavePoint, 0}}, + {2984, {wxStyledTextCtrl, getStyledText, 2}}, + {2985, {wxStyledTextCtrl, canRedo, 0}}, + {2986, {wxStyledTextCtrl, markerLineFromHandle, 1}}, + {2987, {wxStyledTextCtrl, markerDeleteHandle, 1}}, + {2988, {wxStyledTextCtrl, getUndoCollection, 0}}, + {2989, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, + {2990, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, + {2991, {wxStyledTextCtrl, positionFromPoint, 1}}, + {2992, {wxStyledTextCtrl, positionFromPointClose, 2}}, + {2993, {wxStyledTextCtrl, gotoLine, 1}}, + {2994, {wxStyledTextCtrl, gotoPos, 1}}, + {2995, {wxStyledTextCtrl, setAnchor, 1}}, + {2996, {wxStyledTextCtrl, getCurLine, 1}}, + {2997, {wxStyledTextCtrl, getEndStyled, 0}}, + {2998, {wxStyledTextCtrl, convertEOLs, 1}}, + {2999, {wxStyledTextCtrl, getEOLMode, 0}}, + {3000, {wxStyledTextCtrl, setEOLMode, 1}}, + {3001, {wxStyledTextCtrl, startStyling, 2}}, + {3002, {wxStyledTextCtrl, setStyling, 2}}, + {3003, {wxStyledTextCtrl, getBufferedDraw, 0}}, + {3004, {wxStyledTextCtrl, setBufferedDraw, 1}}, + {3005, {wxStyledTextCtrl, setTabWidth, 1}}, + {3006, {wxStyledTextCtrl, getTabWidth, 0}}, + {3007, {wxStyledTextCtrl, setCodePage, 1}}, + {3008, {wxStyledTextCtrl, markerDefine, 3}}, + {3009, {wxStyledTextCtrl, markerSetForeground, 2}}, + {3010, {wxStyledTextCtrl, markerSetBackground, 2}}, + {3011, {wxStyledTextCtrl, markerAdd, 2}}, + {3012, {wxStyledTextCtrl, markerDelete, 2}}, + {3013, {wxStyledTextCtrl, markerDeleteAll, 1}}, + {3014, {wxStyledTextCtrl, markerGet, 1}}, + {3015, {wxStyledTextCtrl, markerNext, 2}}, + {3016, {wxStyledTextCtrl, markerPrevious, 2}}, + {3017, {wxStyledTextCtrl, markerDefineBitmap, 2}}, + {3018, {wxStyledTextCtrl, markerAddSet, 2}}, + {3019, {wxStyledTextCtrl, markerSetAlpha, 2}}, + {3020, {wxStyledTextCtrl, setMarginType, 2}}, + {3021, {wxStyledTextCtrl, getMarginType, 1}}, + {3022, {wxStyledTextCtrl, setMarginWidth, 2}}, + {3023, {wxStyledTextCtrl, getMarginWidth, 1}}, + {3024, {wxStyledTextCtrl, setMarginMask, 2}}, + {3025, {wxStyledTextCtrl, getMarginMask, 1}}, + {3026, {wxStyledTextCtrl, setMarginSensitive, 2}}, + {3027, {wxStyledTextCtrl, getMarginSensitive, 1}}, + {3028, {wxStyledTextCtrl, styleClearAll, 0}}, + {3029, {wxStyledTextCtrl, styleSetForeground, 2}}, + {3030, {wxStyledTextCtrl, styleSetBackground, 2}}, + {3031, {wxStyledTextCtrl, styleSetBold, 2}}, + {3032, {wxStyledTextCtrl, styleSetItalic, 2}}, + {3033, {wxStyledTextCtrl, styleSetSize, 2}}, + {3034, {wxStyledTextCtrl, styleSetFaceName, 2}}, + {3035, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, + {3036, {wxStyledTextCtrl, styleResetDefault, 0}}, + {3037, {wxStyledTextCtrl, styleSetUnderline, 2}}, + {3038, {wxStyledTextCtrl, styleSetCase, 2}}, + {3039, {wxStyledTextCtrl, styleSetHotSpot, 2}}, + {3040, {wxStyledTextCtrl, setSelForeground, 2}}, + {3041, {wxStyledTextCtrl, setSelBackground, 2}}, + {3042, {wxStyledTextCtrl, getSelAlpha, 0}}, + {3043, {wxStyledTextCtrl, setSelAlpha, 1}}, + {3044, {wxStyledTextCtrl, setCaretForeground, 1}}, + {3045, {wxStyledTextCtrl, cmdKeyAssign, 3}}, + {3046, {wxStyledTextCtrl, cmdKeyClear, 2}}, + {3047, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, + {3048, {wxStyledTextCtrl, setStyleBytes, 2}}, + {3049, {wxStyledTextCtrl, styleSetVisible, 2}}, + {3050, {wxStyledTextCtrl, getCaretPeriod, 0}}, + {3051, {wxStyledTextCtrl, setCaretPeriod, 1}}, + {3052, {wxStyledTextCtrl, setWordChars, 1}}, + {3053, {wxStyledTextCtrl, beginUndoAction, 0}}, + {3054, {wxStyledTextCtrl, endUndoAction, 0}}, + {3055, {wxStyledTextCtrl, indicatorSetStyle, 2}}, + {3056, {wxStyledTextCtrl, indicatorGetStyle, 1}}, + {3057, {wxStyledTextCtrl, indicatorSetForeground, 2}}, + {3058, {wxStyledTextCtrl, indicatorGetForeground, 1}}, + {3059, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, + {3060, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, + {3061, {wxStyledTextCtrl, getStyleBits, 0}}, + {3062, {wxStyledTextCtrl, setLineState, 2}}, + {3063, {wxStyledTextCtrl, getLineState, 1}}, + {3064, {wxStyledTextCtrl, getMaxLineState, 0}}, + {3065, {wxStyledTextCtrl, getCaretLineVisible, 0}}, + {3066, {wxStyledTextCtrl, setCaretLineVisible, 1}}, + {3067, {wxStyledTextCtrl, getCaretLineBackground, 0}}, + {3068, {wxStyledTextCtrl, setCaretLineBackground, 1}}, + {3069, {wxStyledTextCtrl, autoCompShow, 2}}, + {3070, {wxStyledTextCtrl, autoCompCancel, 0}}, + {3071, {wxStyledTextCtrl, autoCompActive, 0}}, + {3072, {wxStyledTextCtrl, autoCompPosStart, 0}}, + {3073, {wxStyledTextCtrl, autoCompComplete, 0}}, + {3074, {wxStyledTextCtrl, autoCompStops, 1}}, + {3075, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, + {3076, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, + {3077, {wxStyledTextCtrl, autoCompSelect, 1}}, + {3078, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, + {3079, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, + {3080, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, + {3081, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, + {3082, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, + {3083, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, + {3084, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, + {3085, {wxStyledTextCtrl, userListShow, 2}}, + {3086, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, + {3087, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, + {3088, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, + {3089, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, + {3090, {wxStyledTextCtrl, registerImage, 2}}, + {3091, {wxStyledTextCtrl, clearRegisteredImages, 0}}, + {3092, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, + {3093, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, + {3094, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, + {3095, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, + {3096, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, + {3097, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, + {3098, {wxStyledTextCtrl, setIndent, 1}}, + {3099, {wxStyledTextCtrl, getIndent, 0}}, + {3100, {wxStyledTextCtrl, setUseTabs, 1}}, + {3101, {wxStyledTextCtrl, getUseTabs, 0}}, + {3102, {wxStyledTextCtrl, setLineIndentation, 2}}, + {3103, {wxStyledTextCtrl, getLineIndentation, 1}}, + {3104, {wxStyledTextCtrl, getLineIndentPosition, 1}}, + {3105, {wxStyledTextCtrl, getColumn, 1}}, + {3106, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, + {3107, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, + {3108, {wxStyledTextCtrl, setIndentationGuides, 1}}, + {3109, {wxStyledTextCtrl, getIndentationGuides, 0}}, + {3110, {wxStyledTextCtrl, setHighlightGuide, 1}}, + {3111, {wxStyledTextCtrl, getHighlightGuide, 0}}, + {3112, {wxStyledTextCtrl, getLineEndPosition, 1}}, + {3113, {wxStyledTextCtrl, getCodePage, 0}}, + {3114, {wxStyledTextCtrl, getCaretForeground, 0}}, + {3115, {wxStyledTextCtrl, getReadOnly, 0}}, + {3116, {wxStyledTextCtrl, setCurrentPos, 1}}, + {3117, {wxStyledTextCtrl, setSelectionStart, 1}}, + {3118, {wxStyledTextCtrl, getSelectionStart, 0}}, + {3119, {wxStyledTextCtrl, setSelectionEnd, 1}}, + {3120, {wxStyledTextCtrl, getSelectionEnd, 0}}, + {3121, {wxStyledTextCtrl, setPrintMagnification, 1}}, + {3122, {wxStyledTextCtrl, getPrintMagnification, 0}}, + {3123, {wxStyledTextCtrl, setPrintColourMode, 1}}, + {3124, {wxStyledTextCtrl, getPrintColourMode, 0}}, + {3125, {wxStyledTextCtrl, findText, 4}}, + {3126, {wxStyledTextCtrl, formatRange, 7}}, + {3127, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, + {3128, {wxStyledTextCtrl, getLine, 1}}, + {3129, {wxStyledTextCtrl, getLineCount, 0}}, + {3130, {wxStyledTextCtrl, setMarginLeft, 1}}, + {3131, {wxStyledTextCtrl, getMarginLeft, 0}}, + {3132, {wxStyledTextCtrl, setMarginRight, 1}}, + {3133, {wxStyledTextCtrl, getMarginRight, 0}}, + {3134, {wxStyledTextCtrl, getModify, 0}}, + {3135, {wxStyledTextCtrl, setSelection, 2}}, + {3136, {wxStyledTextCtrl, getSelectedText, 0}}, + {3137, {wxStyledTextCtrl, getTextRange, 2}}, + {3138, {wxStyledTextCtrl, hideSelection, 1}}, + {3139, {wxStyledTextCtrl, lineFromPosition, 1}}, + {3140, {wxStyledTextCtrl, positionFromLine, 1}}, + {3141, {wxStyledTextCtrl, lineScroll, 2}}, + {3142, {wxStyledTextCtrl, ensureCaretVisible, 0}}, + {3143, {wxStyledTextCtrl, replaceSelection, 1}}, + {3144, {wxStyledTextCtrl, setReadOnly, 1}}, + {3145, {wxStyledTextCtrl, canPaste, 0}}, + {3146, {wxStyledTextCtrl, canUndo, 0}}, + {3147, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, + {3148, {wxStyledTextCtrl, undo, 0}}, + {3149, {wxStyledTextCtrl, cut, 0}}, + {3150, {wxStyledTextCtrl, copy, 0}}, + {3151, {wxStyledTextCtrl, paste, 0}}, + {3152, {wxStyledTextCtrl, clear, 0}}, + {3153, {wxStyledTextCtrl, setText, 1}}, + {3154, {wxStyledTextCtrl, getText, 0}}, + {3155, {wxStyledTextCtrl, getTextLength, 0}}, + {3156, {wxStyledTextCtrl, getOvertype, 0}}, + {3157, {wxStyledTextCtrl, setCaretWidth, 1}}, + {3158, {wxStyledTextCtrl, getCaretWidth, 0}}, + {3159, {wxStyledTextCtrl, setTargetStart, 1}}, + {3160, {wxStyledTextCtrl, getTargetStart, 0}}, + {3161, {wxStyledTextCtrl, setTargetEnd, 1}}, + {3162, {wxStyledTextCtrl, getTargetEnd, 0}}, + {3163, {wxStyledTextCtrl, replaceTarget, 1}}, + {3164, {wxStyledTextCtrl, searchInTarget, 1}}, + {3165, {wxStyledTextCtrl, setSearchFlags, 1}}, + {3166, {wxStyledTextCtrl, getSearchFlags, 0}}, + {3167, {wxStyledTextCtrl, callTipShow, 2}}, + {3168, {wxStyledTextCtrl, callTipCancel, 0}}, + {3169, {wxStyledTextCtrl, callTipActive, 0}}, + {3170, {wxStyledTextCtrl, callTipPosAtStart, 0}}, + {3171, {wxStyledTextCtrl, callTipSetHighlight, 2}}, + {3172, {wxStyledTextCtrl, callTipSetBackground, 1}}, + {3173, {wxStyledTextCtrl, callTipSetForeground, 1}}, + {3174, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, + {3175, {wxStyledTextCtrl, callTipUseStyle, 1}}, + {3176, {wxStyledTextCtrl, visibleFromDocLine, 1}}, + {3177, {wxStyledTextCtrl, docLineFromVisible, 1}}, + {3178, {wxStyledTextCtrl, wrapCount, 1}}, + {3179, {wxStyledTextCtrl, setFoldLevel, 2}}, + {3180, {wxStyledTextCtrl, getFoldLevel, 1}}, + {3181, {wxStyledTextCtrl, getLastChild, 2}}, + {3182, {wxStyledTextCtrl, getFoldParent, 1}}, + {3183, {wxStyledTextCtrl, showLines, 2}}, + {3184, {wxStyledTextCtrl, hideLines, 2}}, + {3185, {wxStyledTextCtrl, getLineVisible, 1}}, + {3186, {wxStyledTextCtrl, setFoldExpanded, 2}}, + {3187, {wxStyledTextCtrl, getFoldExpanded, 1}}, + {3188, {wxStyledTextCtrl, toggleFold, 1}}, + {3189, {wxStyledTextCtrl, ensureVisible, 1}}, + {3190, {wxStyledTextCtrl, setFoldFlags, 1}}, + {3191, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, + {3192, {wxStyledTextCtrl, setTabIndents, 1}}, + {3193, {wxStyledTextCtrl, getTabIndents, 0}}, + {3194, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, + {3195, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, + {3196, {wxStyledTextCtrl, setMouseDwellTime, 1}}, + {3197, {wxStyledTextCtrl, getMouseDwellTime, 0}}, + {3198, {wxStyledTextCtrl, wordStartPosition, 2}}, + {3199, {wxStyledTextCtrl, wordEndPosition, 2}}, + {3200, {wxStyledTextCtrl, setWrapMode, 1}}, + {3201, {wxStyledTextCtrl, getWrapMode, 0}}, + {3202, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, + {3203, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, + {3204, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, + {3205, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, + {3206, {wxStyledTextCtrl, setWrapStartIndent, 1}}, + {3207, {wxStyledTextCtrl, getWrapStartIndent, 0}}, + {3208, {wxStyledTextCtrl, setLayoutCache, 1}}, + {3209, {wxStyledTextCtrl, getLayoutCache, 0}}, + {3210, {wxStyledTextCtrl, setScrollWidth, 1}}, + {3211, {wxStyledTextCtrl, getScrollWidth, 0}}, + {3212, {wxStyledTextCtrl, textWidth, 2}}, + {3213, {wxStyledTextCtrl, getEndAtLastLine, 0}}, + {3214, {wxStyledTextCtrl, textHeight, 1}}, + {3215, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, + {3216, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, + {3217, {wxStyledTextCtrl, appendText, 1}}, + {3218, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, + {3219, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, + {3220, {wxStyledTextCtrl, targetFromSelection, 0}}, + {3221, {wxStyledTextCtrl, linesJoin, 0}}, + {3222, {wxStyledTextCtrl, linesSplit, 1}}, + {3223, {wxStyledTextCtrl, setFoldMarginColour, 2}}, + {3224, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, + {3225, {wxStyledTextCtrl, lineDown, 0}}, + {3226, {wxStyledTextCtrl, lineDownExtend, 0}}, + {3227, {wxStyledTextCtrl, lineUp, 0}}, + {3228, {wxStyledTextCtrl, lineUpExtend, 0}}, + {3229, {wxStyledTextCtrl, charLeft, 0}}, + {3230, {wxStyledTextCtrl, charLeftExtend, 0}}, + {3231, {wxStyledTextCtrl, charRight, 0}}, + {3232, {wxStyledTextCtrl, charRightExtend, 0}}, + {3233, {wxStyledTextCtrl, wordLeft, 0}}, + {3234, {wxStyledTextCtrl, wordLeftExtend, 0}}, + {3235, {wxStyledTextCtrl, wordRight, 0}}, + {3236, {wxStyledTextCtrl, wordRightExtend, 0}}, + {3237, {wxStyledTextCtrl, home, 0}}, + {3238, {wxStyledTextCtrl, homeExtend, 0}}, + {3239, {wxStyledTextCtrl, lineEnd, 0}}, + {3240, {wxStyledTextCtrl, lineEndExtend, 0}}, + {3241, {wxStyledTextCtrl, documentStart, 0}}, + {3242, {wxStyledTextCtrl, documentStartExtend, 0}}, + {3243, {wxStyledTextCtrl, documentEnd, 0}}, + {3244, {wxStyledTextCtrl, documentEndExtend, 0}}, + {3245, {wxStyledTextCtrl, pageUp, 0}}, + {3246, {wxStyledTextCtrl, pageUpExtend, 0}}, + {3247, {wxStyledTextCtrl, pageDown, 0}}, + {3248, {wxStyledTextCtrl, pageDownExtend, 0}}, + {3249, {wxStyledTextCtrl, editToggleOvertype, 0}}, + {3250, {wxStyledTextCtrl, cancel, 0}}, + {3251, {wxStyledTextCtrl, deleteBack, 0}}, + {3252, {wxStyledTextCtrl, tab, 0}}, + {3253, {wxStyledTextCtrl, backTab, 0}}, + {3254, {wxStyledTextCtrl, newLine, 0}}, + {3255, {wxStyledTextCtrl, formFeed, 0}}, + {3256, {wxStyledTextCtrl, vCHome, 0}}, + {3257, {wxStyledTextCtrl, vCHomeExtend, 0}}, + {3258, {wxStyledTextCtrl, zoomIn, 0}}, + {3259, {wxStyledTextCtrl, zoomOut, 0}}, + {3260, {wxStyledTextCtrl, delWordLeft, 0}}, + {3261, {wxStyledTextCtrl, delWordRight, 0}}, + {3262, {wxStyledTextCtrl, lineCut, 0}}, + {3263, {wxStyledTextCtrl, lineDelete, 0}}, + {3264, {wxStyledTextCtrl, lineTranspose, 0}}, + {3265, {wxStyledTextCtrl, lineDuplicate, 0}}, + {3266, {wxStyledTextCtrl, lowerCase, 0}}, + {3267, {wxStyledTextCtrl, upperCase, 0}}, + {3268, {wxStyledTextCtrl, lineScrollDown, 0}}, + {3269, {wxStyledTextCtrl, lineScrollUp, 0}}, + {3270, {wxStyledTextCtrl, deleteBackNotLine, 0}}, + {3271, {wxStyledTextCtrl, homeDisplay, 0}}, + {3272, {wxStyledTextCtrl, homeDisplayExtend, 0}}, + {3273, {wxStyledTextCtrl, lineEndDisplay, 0}}, + {3274, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, + {3275, {wxStyledTextCtrl, homeWrapExtend, 0}}, + {3276, {wxStyledTextCtrl, lineEndWrap, 0}}, + {3277, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, + {3278, {wxStyledTextCtrl, vCHomeWrap, 0}}, + {3279, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, + {3280, {wxStyledTextCtrl, lineCopy, 0}}, + {3281, {wxStyledTextCtrl, moveCaretInsideView, 0}}, + {3282, {wxStyledTextCtrl, lineLength, 1}}, + {3283, {wxStyledTextCtrl, braceHighlight, 2}}, + {3284, {wxStyledTextCtrl, braceBadLight, 1}}, + {3285, {wxStyledTextCtrl, braceMatch, 1}}, + {3286, {wxStyledTextCtrl, getViewEOL, 0}}, + {3287, {wxStyledTextCtrl, setViewEOL, 1}}, + {3288, {wxStyledTextCtrl, setModEventMask, 1}}, + {3289, {wxStyledTextCtrl, getEdgeColumn, 0}}, + {3290, {wxStyledTextCtrl, setEdgeColumn, 1}}, + {3291, {wxStyledTextCtrl, setEdgeMode, 1}}, + {3292, {wxStyledTextCtrl, getEdgeMode, 0}}, + {3293, {wxStyledTextCtrl, getEdgeColour, 0}}, + {3294, {wxStyledTextCtrl, setEdgeColour, 1}}, + {3295, {wxStyledTextCtrl, searchAnchor, 0}}, + {3296, {wxStyledTextCtrl, searchNext, 2}}, + {3297, {wxStyledTextCtrl, searchPrev, 2}}, + {3298, {wxStyledTextCtrl, linesOnScreen, 0}}, + {3299, {wxStyledTextCtrl, usePopUp, 1}}, + {3300, {wxStyledTextCtrl, selectionIsRectangle, 0}}, + {3301, {wxStyledTextCtrl, setZoom, 1}}, + {3302, {wxStyledTextCtrl, getZoom, 0}}, + {3303, {wxStyledTextCtrl, getModEventMask, 0}}, + {3304, {wxStyledTextCtrl, setSTCFocus, 1}}, + {3305, {wxStyledTextCtrl, getSTCFocus, 0}}, + {3306, {wxStyledTextCtrl, setStatus, 1}}, + {3307, {wxStyledTextCtrl, getStatus, 0}}, + {3308, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, + {3309, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, + {3310, {wxStyledTextCtrl, setSTCCursor, 1}}, + {3311, {wxStyledTextCtrl, getSTCCursor, 0}}, + {3312, {wxStyledTextCtrl, setControlCharSymbol, 1}}, + {3313, {wxStyledTextCtrl, getControlCharSymbol, 0}}, + {3314, {wxStyledTextCtrl, wordPartLeft, 0}}, + {3315, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, + {3316, {wxStyledTextCtrl, wordPartRight, 0}}, + {3317, {wxStyledTextCtrl, wordPartRightExtend, 0}}, + {3318, {wxStyledTextCtrl, setVisiblePolicy, 2}}, + {3319, {wxStyledTextCtrl, delLineLeft, 0}}, + {3320, {wxStyledTextCtrl, delLineRight, 0}}, + {3321, {wxStyledTextCtrl, getXOffset, 0}}, + {3322, {wxStyledTextCtrl, chooseCaretX, 0}}, + {3323, {wxStyledTextCtrl, setXCaretPolicy, 2}}, + {3324, {wxStyledTextCtrl, setYCaretPolicy, 2}}, + {3325, {wxStyledTextCtrl, getPrintWrapMode, 0}}, + {3326, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, + {3327, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, + {3328, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, + {3329, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, + {3330, {wxStyledTextCtrl, paraDownExtend, 0}}, + {3331, {wxStyledTextCtrl, paraUp, 0}}, + {3332, {wxStyledTextCtrl, paraUpExtend, 0}}, + {3333, {wxStyledTextCtrl, positionBefore, 1}}, + {3334, {wxStyledTextCtrl, positionAfter, 1}}, + {3335, {wxStyledTextCtrl, copyRange, 2}}, + {3336, {wxStyledTextCtrl, copyText, 2}}, + {3337, {wxStyledTextCtrl, setSelectionMode, 1}}, + {3338, {wxStyledTextCtrl, getSelectionMode, 0}}, + {3339, {wxStyledTextCtrl, lineDownRectExtend, 0}}, + {3340, {wxStyledTextCtrl, lineUpRectExtend, 0}}, + {3341, {wxStyledTextCtrl, charLeftRectExtend, 0}}, + {3342, {wxStyledTextCtrl, charRightRectExtend, 0}}, + {3343, {wxStyledTextCtrl, homeRectExtend, 0}}, + {3344, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, + {3345, {wxStyledTextCtrl, lineEndRectExtend, 0}}, + {3346, {wxStyledTextCtrl, pageUpRectExtend, 0}}, + {3347, {wxStyledTextCtrl, pageDownRectExtend, 0}}, + {3348, {wxStyledTextCtrl, stutteredPageUp, 0}}, + {3349, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, + {3350, {wxStyledTextCtrl, stutteredPageDown, 0}}, + {3351, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, + {3352, {wxStyledTextCtrl, wordLeftEnd, 0}}, + {3353, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, + {3354, {wxStyledTextCtrl, wordRightEnd, 0}}, + {3355, {wxStyledTextCtrl, wordRightEndExtend, 0}}, + {3356, {wxStyledTextCtrl, setWhitespaceChars, 1}}, + {3357, {wxStyledTextCtrl, setCharsDefault, 0}}, + {3358, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, + {3359, {wxStyledTextCtrl, allocate, 1}}, + {3360, {wxStyledTextCtrl, findColumn, 2}}, + {3361, {wxStyledTextCtrl, getCaretSticky, 0}}, + {3362, {wxStyledTextCtrl, setCaretSticky, 1}}, + {3363, {wxStyledTextCtrl, toggleCaretSticky, 0}}, + {3364, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, + {3365, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, + {3366, {wxStyledTextCtrl, selectionDuplicate, 0}}, + {3367, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, + {3368, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, + {3369, {wxStyledTextCtrl, startRecord, 0}}, + {3370, {wxStyledTextCtrl, stopRecord, 0}}, + {3371, {wxStyledTextCtrl, setLexer, 1}}, + {3372, {wxStyledTextCtrl, getLexer, 0}}, + {3373, {wxStyledTextCtrl, colourise, 2}}, + {3374, {wxStyledTextCtrl, setProperty, 2}}, + {3375, {wxStyledTextCtrl, setKeyWords, 2}}, + {3376, {wxStyledTextCtrl, setLexerLanguage, 1}}, + {3377, {wxStyledTextCtrl, getProperty, 1}}, + {3378, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, + {3379, {wxStyledTextCtrl, getCurrentLine, 0}}, + {3380, {wxStyledTextCtrl, styleSetSpec, 2}}, + {3381, {wxStyledTextCtrl, styleSetFont, 2}}, + {3382, {wxStyledTextCtrl, styleSetFontAttr, 7}}, + {3383, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, + {3384, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, + {3385, {wxStyledTextCtrl, cmdKeyExecute, 1}}, + {3386, {wxStyledTextCtrl, setMargins, 2}}, + {3387, {wxStyledTextCtrl, getSelection, 2}}, + {3388, {wxStyledTextCtrl, pointFromPosition, 1}}, + {3389, {wxStyledTextCtrl, scrollToLine, 1}}, + {3390, {wxStyledTextCtrl, scrollToColumn, 1}}, + {3391, {wxStyledTextCtrl, setVScrollBar, 1}}, + {3392, {wxStyledTextCtrl, setHScrollBar, 1}}, + {3393, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, + {3394, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, + {3395, {wxStyledTextCtrl, saveFile, 1}}, + {3396, {wxStyledTextCtrl, loadFile, 1}}, + {3397, {wxStyledTextCtrl, doDragOver, 3}}, + {3398, {wxStyledTextCtrl, doDropText, 3}}, + {3399, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, + {3400, {wxStyledTextCtrl, addTextRaw, 1}}, + {3401, {wxStyledTextCtrl, insertTextRaw, 2}}, + {3402, {wxStyledTextCtrl, getCurLineRaw, 1}}, + {3403, {wxStyledTextCtrl, getLineRaw, 1}}, + {3404, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, + {3405, {wxStyledTextCtrl, getTextRangeRaw, 2}}, + {3406, {wxStyledTextCtrl, setTextRaw, 1}}, + {3407, {wxStyledTextCtrl, getTextRaw, 0}}, + {3408, {wxStyledTextCtrl, appendTextRaw, 1}}, + {3409, {wxArtProvider, getBitmap, 2}}, + {3410, {wxArtProvider, getIcon, 2}}, + {3411, {wxTreeEvent, getKeyCode, 0}}, + {3412, {wxTreeEvent, getItem, 0}}, + {3413, {wxTreeEvent, getKeyEvent, 0}}, + {3414, {wxTreeEvent, getLabel, 0}}, + {3415, {wxTreeEvent, getOldItem, 0}}, + {3416, {wxTreeEvent, getPoint, 0}}, + {3417, {wxTreeEvent, isEditCancelled, 0}}, + {3418, {wxTreeEvent, setToolTip, 1}}, + {3419, {wxNotebookEvent, getOldSelection, 0}}, + {3420, {wxNotebookEvent, getSelection, 0}}, + {3421, {wxNotebookEvent, setOldSelection, 1}}, + {3422, {wxNotebookEvent, setSelection, 1}}, + {3423, {wxFileDataObject, new, 0}}, + {3424, {wxFileDataObject, addFile, 1}}, + {3425, {wxFileDataObject, getFilenames, 0}}, + {3426, {wxFileDataObject, 'Destroy', undefined}}, + {3427, {wxTextDataObject, new, 1}}, + {3428, {wxTextDataObject, getTextLength, 0}}, + {3429, {wxTextDataObject, getText, 0}}, + {3430, {wxTextDataObject, setText, 1}}, + {3431, {wxTextDataObject, 'Destroy', undefined}}, + {3432, {wxBitmapDataObject, new_1_1, 1}}, + {3433, {wxBitmapDataObject, new_1_0, 1}}, + {3434, {wxBitmapDataObject, getBitmap, 0}}, + {3435, {wxBitmapDataObject, setBitmap, 1}}, + {3436, {wxBitmapDataObject, 'Destroy', undefined}}, + {3438, {wxClipboard, new, 0}}, + {3439, {wxClipboard, destruct, 0}}, + {3440, {wxClipboard, addData, 1}}, + {3441, {wxClipboard, clear, 0}}, + {3442, {wxClipboard, close, 0}}, + {3443, {wxClipboard, flush, 0}}, + {3444, {wxClipboard, getData, 1}}, + {3445, {wxClipboard, isOpened, 0}}, + {3446, {wxClipboard, open, 0}}, + {3447, {wxClipboard, setData, 1}}, + {3449, {wxClipboard, usePrimarySelection, 1}}, + {3450, {wxClipboard, isSupported, 1}}, + {3451, {wxClipboard, get, 0}}, + {3452, {wxSpinEvent, getPosition, 0}}, + {3453, {wxSpinEvent, setPosition, 1}}, + {3454, {wxSplitterWindow, new_0, 0}}, + {3455, {wxSplitterWindow, new_2, 2}}, + {3456, {wxSplitterWindow, destruct, 0}}, + {3457, {wxSplitterWindow, create, 2}}, + {3458, {wxSplitterWindow, getMinimumPaneSize, 0}}, + {3459, {wxSplitterWindow, getSashGravity, 0}}, + {3460, {wxSplitterWindow, getSashPosition, 0}}, + {3461, {wxSplitterWindow, getSplitMode, 0}}, + {3462, {wxSplitterWindow, getWindow1, 0}}, + {3463, {wxSplitterWindow, getWindow2, 0}}, + {3464, {wxSplitterWindow, initialize, 1}}, + {3465, {wxSplitterWindow, isSplit, 0}}, + {3466, {wxSplitterWindow, replaceWindow, 2}}, + {3467, {wxSplitterWindow, setSashGravity, 1}}, + {3468, {wxSplitterWindow, setSashPosition, 2}}, + {3469, {wxSplitterWindow, setSashSize, 1}}, + {3470, {wxSplitterWindow, setMinimumPaneSize, 1}}, + {3471, {wxSplitterWindow, setSplitMode, 1}}, + {3472, {wxSplitterWindow, splitHorizontally, 3}}, + {3473, {wxSplitterWindow, splitVertically, 3}}, + {3474, {wxSplitterWindow, unsplit, 1}}, + {3475, {wxSplitterWindow, updateSize, 0}}, + {3476, {wxSplitterEvent, getSashPosition, 0}}, + {3477, {wxSplitterEvent, getX, 0}}, + {3478, {wxSplitterEvent, getY, 0}}, + {3479, {wxSplitterEvent, getWindowBeingRemoved, 0}}, + {3480, {wxSplitterEvent, setSashPosition, 1}}, + {3481, {wxHtmlWindow, new_0, 0}}, + {3482, {wxHtmlWindow, new_2, 2}}, + {3483, {wxHtmlWindow, appendToPage, 1}}, + {3484, {wxHtmlWindow, getOpenedAnchor, 0}}, + {3485, {wxHtmlWindow, getOpenedPage, 0}}, + {3486, {wxHtmlWindow, getOpenedPageTitle, 0}}, + {3487, {wxHtmlWindow, getRelatedFrame, 0}}, + {3488, {wxHtmlWindow, historyBack, 0}}, + {3489, {wxHtmlWindow, historyCanBack, 0}}, + {3490, {wxHtmlWindow, historyCanForward, 0}}, + {3491, {wxHtmlWindow, historyClear, 0}}, + {3492, {wxHtmlWindow, historyForward, 0}}, + {3493, {wxHtmlWindow, loadFile, 1}}, + {3494, {wxHtmlWindow, loadPage, 1}}, + {3495, {wxHtmlWindow, selectAll, 0}}, + {3496, {wxHtmlWindow, selectionToText, 0}}, + {3497, {wxHtmlWindow, selectLine, 1}}, + {3498, {wxHtmlWindow, selectWord, 1}}, + {3499, {wxHtmlWindow, setBorders, 1}}, + {3500, {wxHtmlWindow, setFonts, 3}}, + {3501, {wxHtmlWindow, setPage, 1}}, + {3502, {wxHtmlWindow, setRelatedFrame, 2}}, + {3503, {wxHtmlWindow, setRelatedStatusBar, 1}}, + {3504, {wxHtmlWindow, toText, 0}}, + {3505, {wxHtmlWindow, 'Destroy', undefined}}, + {3506, {wxHtmlLinkEvent, getLinkInfo, 0}}, + {3507, {wxSystemSettings, getColour, 1}}, + {3508, {wxSystemSettings, getFont, 1}}, + {3509, {wxSystemSettings, getMetric, 2}}, + {3510, {wxSystemSettings, getScreenType, 0}}, + {3511, {wxSystemOptions, getOption, 1}}, + {3512, {wxSystemOptions, getOptionInt, 1}}, + {3513, {wxSystemOptions, hasOption, 1}}, + {3514, {wxSystemOptions, isFalse, 1}}, + {3515, {wxSystemOptions, setOption_2_1, 2}}, + {3516, {wxSystemOptions, setOption_2_0, 2}}, + {3517, {wxAuiNotebookEvent, setSelection, 1}}, + {3518, {wxAuiNotebookEvent, getSelection, 0}}, + {3519, {wxAuiNotebookEvent, setOldSelection, 1}}, + {3520, {wxAuiNotebookEvent, getOldSelection, 0}}, + {3521, {wxAuiNotebookEvent, setDragSource, 1}}, + {3522, {wxAuiNotebookEvent, getDragSource, 0}}, + {3523, {wxAuiManagerEvent, setManager, 1}}, + {3524, {wxAuiManagerEvent, getManager, 0}}, + {3525, {wxAuiManagerEvent, setPane, 1}}, + {3526, {wxAuiManagerEvent, getPane, 0}}, + {3527, {wxAuiManagerEvent, setButton, 1}}, + {3528, {wxAuiManagerEvent, getButton, 0}}, + {3529, {wxAuiManagerEvent, setDC, 1}}, + {3530, {wxAuiManagerEvent, getDC, 0}}, + {3531, {wxAuiManagerEvent, veto, 1}}, + {3532, {wxAuiManagerEvent, getVeto, 0}}, + {3533, {wxAuiManagerEvent, setCanVeto, 1}}, + {3534, {wxAuiManagerEvent, canVeto, 0}}, + {3535, {wxLogNull, new, 0}}, + {3536, {wxLogNull, 'Destroy', undefined}}, + {3537, {wxTaskBarIcon, new, 0}}, + {3538, {wxTaskBarIcon, destruct, 0}}, + {3539, {wxTaskBarIcon, popupMenu, 1}}, + {3540, {wxTaskBarIcon, removeIcon, 0}}, + {3541, {wxTaskBarIcon, setIcon, 2}}, + {3542, {wxLocale, new_0, 0}}, + {3544, {wxLocale, new_2, 2}}, + {3545, {wxLocale, destruct, 0}}, + {3547, {wxLocale, init, 1}}, + {3548, {wxLocale, addCatalog_1, 1}}, + {3549, {wxLocale, addCatalog_3, 3}}, + {3550, {wxLocale, addCatalogLookupPathPrefix, 1}}, + {3551, {wxLocale, getCanonicalName, 0}}, + {3552, {wxLocale, getLanguage, 0}}, + {3553, {wxLocale, getLanguageName, 1}}, + {3554, {wxLocale, getLocale, 0}}, + {3555, {wxLocale, getName, 0}}, + {3556, {wxLocale, getString_2, 2}}, + {3557, {wxLocale, getString_4, 4}}, + {3558, {wxLocale, getHeaderValue, 2}}, + {3559, {wxLocale, getSysName, 0}}, + {3560, {wxLocale, getSystemEncoding, 0}}, + {3561, {wxLocale, getSystemEncodingName, 0}}, + {3562, {wxLocale, getSystemLanguage, 0}}, + {3563, {wxLocale, isLoaded, 1}}, + {3564, {wxLocale, isOk, 0}}, + {3565, {wxActivateEvent, getActive, 0}}, + {3567, {wxPopupWindow, new_2, 2}}, + {3568, {wxPopupWindow, new_0, 0}}, + {3570, {wxPopupWindow, destruct, 0}}, + {3571, {wxPopupWindow, create, 2}}, + {3572, {wxPopupWindow, position, 2}}, + {3573, {wxPopupTransientWindow, new_0, 0}}, + {3574, {wxPopupTransientWindow, new_2, 2}}, + {3575, {wxPopupTransientWindow, destruct, 0}}, + {3576, {wxPopupTransientWindow, popup, 1}}, + {3577, {wxPopupTransientWindow, dismiss, 0}}, {-1, {mod, func, -1}} ]. diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl index faab72184d..d3df1e4e44 100644 --- a/lib/wx/src/gen/wxe_funcs.hrl +++ b/lib/wx/src/gen/wxe_funcs.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2014. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -2459,882 +2459,896 @@ -define(wxAuiNotebook_SetTabCtrlHeight, 2672). -define(wxAuiNotebook_SetUniformBitmapSize, 2673). -define(wxAuiNotebook_destroy, 2674). --define(wxMDIParentFrame_new_0, 2675). --define(wxMDIParentFrame_new_4, 2676). --define(wxMDIParentFrame_destruct, 2677). --define(wxMDIParentFrame_ActivateNext, 2678). --define(wxMDIParentFrame_ActivatePrevious, 2679). --define(wxMDIParentFrame_ArrangeIcons, 2680). --define(wxMDIParentFrame_Cascade, 2681). --define(wxMDIParentFrame_Create, 2682). --define(wxMDIParentFrame_GetActiveChild, 2683). --define(wxMDIParentFrame_GetClientWindow, 2684). --define(wxMDIParentFrame_Tile, 2685). --define(wxMDIChildFrame_new_0, 2686). --define(wxMDIChildFrame_new_4, 2687). --define(wxMDIChildFrame_destruct, 2688). --define(wxMDIChildFrame_Activate, 2689). --define(wxMDIChildFrame_Create, 2690). --define(wxMDIChildFrame_Maximize, 2691). --define(wxMDIChildFrame_Restore, 2692). --define(wxMDIClientWindow_new_0, 2693). --define(wxMDIClientWindow_new_2, 2694). --define(wxMDIClientWindow_destruct, 2695). --define(wxMDIClientWindow_CreateClient, 2696). --define(wxLayoutAlgorithm_new, 2697). --define(wxLayoutAlgorithm_LayoutFrame, 2698). --define(wxLayoutAlgorithm_LayoutMDIFrame, 2699). --define(wxLayoutAlgorithm_LayoutWindow, 2700). --define(wxLayoutAlgorithm_destroy, 2701). --define(wxEvent_GetId, 2702). --define(wxEvent_GetSkipped, 2703). --define(wxEvent_GetTimestamp, 2704). --define(wxEvent_IsCommandEvent, 2705). --define(wxEvent_ResumePropagation, 2706). --define(wxEvent_ShouldPropagate, 2707). --define(wxEvent_Skip, 2708). --define(wxEvent_StopPropagation, 2709). --define(wxCommandEvent_getClientData, 2710). --define(wxCommandEvent_GetExtraLong, 2711). --define(wxCommandEvent_GetInt, 2712). --define(wxCommandEvent_GetSelection, 2713). --define(wxCommandEvent_GetString, 2714). --define(wxCommandEvent_IsChecked, 2715). --define(wxCommandEvent_IsSelection, 2716). --define(wxCommandEvent_SetInt, 2717). --define(wxCommandEvent_SetString, 2718). --define(wxScrollEvent_GetOrientation, 2719). --define(wxScrollEvent_GetPosition, 2720). --define(wxScrollWinEvent_GetOrientation, 2721). --define(wxScrollWinEvent_GetPosition, 2722). --define(wxMouseEvent_AltDown, 2723). --define(wxMouseEvent_Button, 2724). --define(wxMouseEvent_ButtonDClick, 2725). --define(wxMouseEvent_ButtonDown, 2726). --define(wxMouseEvent_ButtonUp, 2727). --define(wxMouseEvent_CmdDown, 2728). --define(wxMouseEvent_ControlDown, 2729). --define(wxMouseEvent_Dragging, 2730). --define(wxMouseEvent_Entering, 2731). --define(wxMouseEvent_GetButton, 2732). --define(wxMouseEvent_GetPosition, 2735). --define(wxMouseEvent_GetLogicalPosition, 2736). --define(wxMouseEvent_GetLinesPerAction, 2737). --define(wxMouseEvent_GetWheelRotation, 2738). --define(wxMouseEvent_GetWheelDelta, 2739). --define(wxMouseEvent_GetX, 2740). --define(wxMouseEvent_GetY, 2741). --define(wxMouseEvent_IsButton, 2742). --define(wxMouseEvent_IsPageScroll, 2743). --define(wxMouseEvent_Leaving, 2744). --define(wxMouseEvent_LeftDClick, 2745). --define(wxMouseEvent_LeftDown, 2746). --define(wxMouseEvent_LeftIsDown, 2747). --define(wxMouseEvent_LeftUp, 2748). --define(wxMouseEvent_MetaDown, 2749). --define(wxMouseEvent_MiddleDClick, 2750). --define(wxMouseEvent_MiddleDown, 2751). --define(wxMouseEvent_MiddleIsDown, 2752). --define(wxMouseEvent_MiddleUp, 2753). --define(wxMouseEvent_Moving, 2754). --define(wxMouseEvent_RightDClick, 2755). --define(wxMouseEvent_RightDown, 2756). --define(wxMouseEvent_RightIsDown, 2757). --define(wxMouseEvent_RightUp, 2758). --define(wxMouseEvent_ShiftDown, 2759). --define(wxSetCursorEvent_GetCursor, 2760). --define(wxSetCursorEvent_GetX, 2761). --define(wxSetCursorEvent_GetY, 2762). --define(wxSetCursorEvent_HasCursor, 2763). --define(wxSetCursorEvent_SetCursor, 2764). --define(wxKeyEvent_AltDown, 2765). --define(wxKeyEvent_CmdDown, 2766). --define(wxKeyEvent_ControlDown, 2767). --define(wxKeyEvent_GetKeyCode, 2768). --define(wxKeyEvent_GetModifiers, 2769). --define(wxKeyEvent_GetPosition, 2772). --define(wxKeyEvent_GetRawKeyCode, 2773). --define(wxKeyEvent_GetRawKeyFlags, 2774). --define(wxKeyEvent_GetUnicodeKey, 2775). --define(wxKeyEvent_GetX, 2776). --define(wxKeyEvent_GetY, 2777). --define(wxKeyEvent_HasModifiers, 2778). --define(wxKeyEvent_MetaDown, 2779). --define(wxKeyEvent_ShiftDown, 2780). --define(wxSizeEvent_GetSize, 2781). --define(wxMoveEvent_GetPosition, 2782). --define(wxEraseEvent_GetDC, 2783). --define(wxFocusEvent_GetWindow, 2784). --define(wxChildFocusEvent_GetWindow, 2785). --define(wxMenuEvent_GetMenu, 2786). --define(wxMenuEvent_GetMenuId, 2787). --define(wxMenuEvent_IsPopup, 2788). --define(wxCloseEvent_CanVeto, 2789). --define(wxCloseEvent_GetLoggingOff, 2790). --define(wxCloseEvent_SetCanVeto, 2791). --define(wxCloseEvent_SetLoggingOff, 2792). --define(wxCloseEvent_Veto, 2793). --define(wxShowEvent_SetShow, 2794). --define(wxShowEvent_GetShow, 2795). --define(wxIconizeEvent_Iconized, 2796). --define(wxJoystickEvent_ButtonDown, 2797). --define(wxJoystickEvent_ButtonIsDown, 2798). --define(wxJoystickEvent_ButtonUp, 2799). --define(wxJoystickEvent_GetButtonChange, 2800). --define(wxJoystickEvent_GetButtonState, 2801). --define(wxJoystickEvent_GetJoystick, 2802). --define(wxJoystickEvent_GetPosition, 2803). --define(wxJoystickEvent_GetZPosition, 2804). --define(wxJoystickEvent_IsButton, 2805). --define(wxJoystickEvent_IsMove, 2806). --define(wxJoystickEvent_IsZMove, 2807). --define(wxUpdateUIEvent_CanUpdate, 2808). --define(wxUpdateUIEvent_Check, 2809). --define(wxUpdateUIEvent_Enable, 2810). --define(wxUpdateUIEvent_Show, 2811). --define(wxUpdateUIEvent_GetChecked, 2812). --define(wxUpdateUIEvent_GetEnabled, 2813). --define(wxUpdateUIEvent_GetShown, 2814). --define(wxUpdateUIEvent_GetSetChecked, 2815). --define(wxUpdateUIEvent_GetSetEnabled, 2816). --define(wxUpdateUIEvent_GetSetShown, 2817). --define(wxUpdateUIEvent_GetSetText, 2818). --define(wxUpdateUIEvent_GetText, 2819). --define(wxUpdateUIEvent_GetMode, 2820). --define(wxUpdateUIEvent_GetUpdateInterval, 2821). --define(wxUpdateUIEvent_ResetUpdateTime, 2822). --define(wxUpdateUIEvent_SetMode, 2823). --define(wxUpdateUIEvent_SetText, 2824). --define(wxUpdateUIEvent_SetUpdateInterval, 2825). --define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2826). --define(wxPaletteChangedEvent_SetChangedWindow, 2827). --define(wxPaletteChangedEvent_GetChangedWindow, 2828). --define(wxQueryNewPaletteEvent_SetPaletteRealized, 2829). --define(wxQueryNewPaletteEvent_GetPaletteRealized, 2830). --define(wxNavigationKeyEvent_GetDirection, 2831). --define(wxNavigationKeyEvent_SetDirection, 2832). --define(wxNavigationKeyEvent_IsWindowChange, 2833). --define(wxNavigationKeyEvent_SetWindowChange, 2834). --define(wxNavigationKeyEvent_IsFromTab, 2835). --define(wxNavigationKeyEvent_SetFromTab, 2836). --define(wxNavigationKeyEvent_GetCurrentFocus, 2837). --define(wxNavigationKeyEvent_SetCurrentFocus, 2838). --define(wxHelpEvent_GetOrigin, 2839). --define(wxHelpEvent_GetPosition, 2840). --define(wxHelpEvent_SetOrigin, 2841). --define(wxHelpEvent_SetPosition, 2842). --define(wxContextMenuEvent_GetPosition, 2843). --define(wxContextMenuEvent_SetPosition, 2844). --define(wxIdleEvent_CanSend, 2845). --define(wxIdleEvent_GetMode, 2846). --define(wxIdleEvent_RequestMore, 2847). --define(wxIdleEvent_MoreRequested, 2848). --define(wxIdleEvent_SetMode, 2849). --define(wxGridEvent_AltDown, 2850). --define(wxGridEvent_ControlDown, 2851). --define(wxGridEvent_GetCol, 2852). --define(wxGridEvent_GetPosition, 2853). --define(wxGridEvent_GetRow, 2854). --define(wxGridEvent_MetaDown, 2855). --define(wxGridEvent_Selecting, 2856). --define(wxGridEvent_ShiftDown, 2857). --define(wxNotifyEvent_Allow, 2858). --define(wxNotifyEvent_IsAllowed, 2859). --define(wxNotifyEvent_Veto, 2860). --define(wxSashEvent_GetEdge, 2861). --define(wxSashEvent_GetDragRect, 2862). --define(wxSashEvent_GetDragStatus, 2863). --define(wxListEvent_GetCacheFrom, 2864). --define(wxListEvent_GetCacheTo, 2865). --define(wxListEvent_GetKeyCode, 2866). --define(wxListEvent_GetIndex, 2867). --define(wxListEvent_GetColumn, 2868). --define(wxListEvent_GetPoint, 2869). --define(wxListEvent_GetLabel, 2870). --define(wxListEvent_GetText, 2871). --define(wxListEvent_GetImage, 2872). --define(wxListEvent_GetData, 2873). --define(wxListEvent_GetMask, 2874). --define(wxListEvent_GetItem, 2875). --define(wxListEvent_IsEditCancelled, 2876). --define(wxDateEvent_GetDate, 2877). --define(wxCalendarEvent_GetWeekDay, 2878). --define(wxFileDirPickerEvent_GetPath, 2879). --define(wxColourPickerEvent_GetColour, 2880). --define(wxFontPickerEvent_GetFont, 2881). --define(wxStyledTextEvent_GetPosition, 2882). --define(wxStyledTextEvent_GetKey, 2883). --define(wxStyledTextEvent_GetModifiers, 2884). --define(wxStyledTextEvent_GetModificationType, 2885). --define(wxStyledTextEvent_GetText, 2886). --define(wxStyledTextEvent_GetLength, 2887). --define(wxStyledTextEvent_GetLinesAdded, 2888). --define(wxStyledTextEvent_GetLine, 2889). --define(wxStyledTextEvent_GetFoldLevelNow, 2890). --define(wxStyledTextEvent_GetFoldLevelPrev, 2891). --define(wxStyledTextEvent_GetMargin, 2892). --define(wxStyledTextEvent_GetMessage, 2893). --define(wxStyledTextEvent_GetWParam, 2894). --define(wxStyledTextEvent_GetLParam, 2895). --define(wxStyledTextEvent_GetListType, 2896). --define(wxStyledTextEvent_GetX, 2897). --define(wxStyledTextEvent_GetY, 2898). --define(wxStyledTextEvent_GetDragText, 2899). --define(wxStyledTextEvent_GetDragAllowMove, 2900). --define(wxStyledTextEvent_GetDragResult, 2901). --define(wxStyledTextEvent_GetShift, 2902). --define(wxStyledTextEvent_GetControl, 2903). --define(wxStyledTextEvent_GetAlt, 2904). --define(utils_wxGetKeyState, 2905). --define(utils_wxGetMousePosition, 2906). --define(utils_wxGetMouseState, 2907). --define(utils_wxSetDetectableAutoRepeat, 2908). --define(utils_wxBell, 2909). --define(utils_wxFindMenuItemId, 2910). --define(utils_wxGenericFindWindowAtPoint, 2911). --define(utils_wxFindWindowAtPoint, 2912). --define(utils_wxBeginBusyCursor, 2913). --define(utils_wxEndBusyCursor, 2914). --define(utils_wxIsBusy, 2915). --define(utils_wxShutdown, 2916). --define(utils_wxShell, 2917). --define(utils_wxLaunchDefaultBrowser, 2918). --define(utils_wxGetEmailAddress, 2919). --define(utils_wxGetUserId, 2920). --define(utils_wxGetHomeDir, 2921). --define(utils_wxNewId, 2922). --define(utils_wxRegisterId, 2923). --define(utils_wxGetCurrentId, 2924). --define(utils_wxGetOsDescription, 2925). --define(utils_wxIsPlatformLittleEndian, 2926). --define(utils_wxIsPlatform64Bit, 2927). --define(gdicmn_wxDisplaySize, 2928). --define(gdicmn_wxSetCursor, 2929). --define(wxPrintout_new, 2930). --define(wxPrintout_destruct, 2931). --define(wxPrintout_GetDC, 2932). --define(wxPrintout_GetPageSizeMM, 2933). --define(wxPrintout_GetPageSizePixels, 2934). --define(wxPrintout_GetPaperRectPixels, 2935). --define(wxPrintout_GetPPIPrinter, 2936). --define(wxPrintout_GetPPIScreen, 2937). --define(wxPrintout_GetTitle, 2938). --define(wxPrintout_IsPreview, 2939). --define(wxPrintout_FitThisSizeToPaper, 2940). --define(wxPrintout_FitThisSizeToPage, 2941). --define(wxPrintout_FitThisSizeToPageMargins, 2942). --define(wxPrintout_MapScreenSizeToPaper, 2943). --define(wxPrintout_MapScreenSizeToPage, 2944). --define(wxPrintout_MapScreenSizeToPageMargins, 2945). --define(wxPrintout_MapScreenSizeToDevice, 2946). --define(wxPrintout_GetLogicalPaperRect, 2947). --define(wxPrintout_GetLogicalPageRect, 2948). --define(wxPrintout_GetLogicalPageMarginsRect, 2949). --define(wxPrintout_SetLogicalOrigin, 2950). --define(wxPrintout_OffsetLogicalOrigin, 2951). --define(wxStyledTextCtrl_new_2, 2952). --define(wxStyledTextCtrl_new_0, 2953). --define(wxStyledTextCtrl_destruct, 2954). --define(wxStyledTextCtrl_Create, 2955). --define(wxStyledTextCtrl_AddText, 2956). --define(wxStyledTextCtrl_AddStyledText, 2957). --define(wxStyledTextCtrl_InsertText, 2958). --define(wxStyledTextCtrl_ClearAll, 2959). --define(wxStyledTextCtrl_ClearDocumentStyle, 2960). --define(wxStyledTextCtrl_GetLength, 2961). --define(wxStyledTextCtrl_GetCharAt, 2962). --define(wxStyledTextCtrl_GetCurrentPos, 2963). --define(wxStyledTextCtrl_GetAnchor, 2964). --define(wxStyledTextCtrl_GetStyleAt, 2965). --define(wxStyledTextCtrl_Redo, 2966). --define(wxStyledTextCtrl_SetUndoCollection, 2967). --define(wxStyledTextCtrl_SelectAll, 2968). --define(wxStyledTextCtrl_SetSavePoint, 2969). --define(wxStyledTextCtrl_GetStyledText, 2970). --define(wxStyledTextCtrl_CanRedo, 2971). --define(wxStyledTextCtrl_MarkerLineFromHandle, 2972). --define(wxStyledTextCtrl_MarkerDeleteHandle, 2973). --define(wxStyledTextCtrl_GetUndoCollection, 2974). --define(wxStyledTextCtrl_GetViewWhiteSpace, 2975). --define(wxStyledTextCtrl_SetViewWhiteSpace, 2976). --define(wxStyledTextCtrl_PositionFromPoint, 2977). --define(wxStyledTextCtrl_PositionFromPointClose, 2978). --define(wxStyledTextCtrl_GotoLine, 2979). --define(wxStyledTextCtrl_GotoPos, 2980). --define(wxStyledTextCtrl_SetAnchor, 2981). --define(wxStyledTextCtrl_GetCurLine, 2982). --define(wxStyledTextCtrl_GetEndStyled, 2983). --define(wxStyledTextCtrl_ConvertEOLs, 2984). --define(wxStyledTextCtrl_GetEOLMode, 2985). --define(wxStyledTextCtrl_SetEOLMode, 2986). --define(wxStyledTextCtrl_StartStyling, 2987). --define(wxStyledTextCtrl_SetStyling, 2988). --define(wxStyledTextCtrl_GetBufferedDraw, 2989). --define(wxStyledTextCtrl_SetBufferedDraw, 2990). --define(wxStyledTextCtrl_SetTabWidth, 2991). --define(wxStyledTextCtrl_GetTabWidth, 2992). --define(wxStyledTextCtrl_SetCodePage, 2993). --define(wxStyledTextCtrl_MarkerDefine, 2994). --define(wxStyledTextCtrl_MarkerSetForeground, 2995). --define(wxStyledTextCtrl_MarkerSetBackground, 2996). --define(wxStyledTextCtrl_MarkerAdd, 2997). --define(wxStyledTextCtrl_MarkerDelete, 2998). --define(wxStyledTextCtrl_MarkerDeleteAll, 2999). --define(wxStyledTextCtrl_MarkerGet, 3000). --define(wxStyledTextCtrl_MarkerNext, 3001). --define(wxStyledTextCtrl_MarkerPrevious, 3002). --define(wxStyledTextCtrl_MarkerDefineBitmap, 3003). --define(wxStyledTextCtrl_MarkerAddSet, 3004). --define(wxStyledTextCtrl_MarkerSetAlpha, 3005). --define(wxStyledTextCtrl_SetMarginType, 3006). --define(wxStyledTextCtrl_GetMarginType, 3007). --define(wxStyledTextCtrl_SetMarginWidth, 3008). --define(wxStyledTextCtrl_GetMarginWidth, 3009). --define(wxStyledTextCtrl_SetMarginMask, 3010). --define(wxStyledTextCtrl_GetMarginMask, 3011). --define(wxStyledTextCtrl_SetMarginSensitive, 3012). --define(wxStyledTextCtrl_GetMarginSensitive, 3013). --define(wxStyledTextCtrl_StyleClearAll, 3014). --define(wxStyledTextCtrl_StyleSetForeground, 3015). --define(wxStyledTextCtrl_StyleSetBackground, 3016). --define(wxStyledTextCtrl_StyleSetBold, 3017). --define(wxStyledTextCtrl_StyleSetItalic, 3018). --define(wxStyledTextCtrl_StyleSetSize, 3019). --define(wxStyledTextCtrl_StyleSetFaceName, 3020). --define(wxStyledTextCtrl_StyleSetEOLFilled, 3021). --define(wxStyledTextCtrl_StyleResetDefault, 3022). --define(wxStyledTextCtrl_StyleSetUnderline, 3023). --define(wxStyledTextCtrl_StyleSetCase, 3024). --define(wxStyledTextCtrl_StyleSetHotSpot, 3025). --define(wxStyledTextCtrl_SetSelForeground, 3026). --define(wxStyledTextCtrl_SetSelBackground, 3027). --define(wxStyledTextCtrl_GetSelAlpha, 3028). --define(wxStyledTextCtrl_SetSelAlpha, 3029). --define(wxStyledTextCtrl_SetCaretForeground, 3030). --define(wxStyledTextCtrl_CmdKeyAssign, 3031). --define(wxStyledTextCtrl_CmdKeyClear, 3032). --define(wxStyledTextCtrl_CmdKeyClearAll, 3033). --define(wxStyledTextCtrl_SetStyleBytes, 3034). --define(wxStyledTextCtrl_StyleSetVisible, 3035). --define(wxStyledTextCtrl_GetCaretPeriod, 3036). --define(wxStyledTextCtrl_SetCaretPeriod, 3037). --define(wxStyledTextCtrl_SetWordChars, 3038). --define(wxStyledTextCtrl_BeginUndoAction, 3039). --define(wxStyledTextCtrl_EndUndoAction, 3040). --define(wxStyledTextCtrl_IndicatorSetStyle, 3041). --define(wxStyledTextCtrl_IndicatorGetStyle, 3042). --define(wxStyledTextCtrl_IndicatorSetForeground, 3043). --define(wxStyledTextCtrl_IndicatorGetForeground, 3044). --define(wxStyledTextCtrl_SetWhitespaceForeground, 3045). --define(wxStyledTextCtrl_SetWhitespaceBackground, 3046). --define(wxStyledTextCtrl_GetStyleBits, 3047). --define(wxStyledTextCtrl_SetLineState, 3048). --define(wxStyledTextCtrl_GetLineState, 3049). --define(wxStyledTextCtrl_GetMaxLineState, 3050). --define(wxStyledTextCtrl_GetCaretLineVisible, 3051). --define(wxStyledTextCtrl_SetCaretLineVisible, 3052). --define(wxStyledTextCtrl_GetCaretLineBackground, 3053). --define(wxStyledTextCtrl_SetCaretLineBackground, 3054). --define(wxStyledTextCtrl_AutoCompShow, 3055). --define(wxStyledTextCtrl_AutoCompCancel, 3056). --define(wxStyledTextCtrl_AutoCompActive, 3057). --define(wxStyledTextCtrl_AutoCompPosStart, 3058). --define(wxStyledTextCtrl_AutoCompComplete, 3059). --define(wxStyledTextCtrl_AutoCompStops, 3060). --define(wxStyledTextCtrl_AutoCompSetSeparator, 3061). --define(wxStyledTextCtrl_AutoCompGetSeparator, 3062). --define(wxStyledTextCtrl_AutoCompSelect, 3063). --define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3064). --define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3065). --define(wxStyledTextCtrl_AutoCompSetFillUps, 3066). --define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3067). --define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3068). --define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3069). --define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3070). --define(wxStyledTextCtrl_UserListShow, 3071). --define(wxStyledTextCtrl_AutoCompSetAutoHide, 3072). --define(wxStyledTextCtrl_AutoCompGetAutoHide, 3073). --define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3074). --define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3075). --define(wxStyledTextCtrl_RegisterImage, 3076). --define(wxStyledTextCtrl_ClearRegisteredImages, 3077). --define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3078). --define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3079). --define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3080). --define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3081). --define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3082). --define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3083). --define(wxStyledTextCtrl_SetIndent, 3084). --define(wxStyledTextCtrl_GetIndent, 3085). --define(wxStyledTextCtrl_SetUseTabs, 3086). --define(wxStyledTextCtrl_GetUseTabs, 3087). --define(wxStyledTextCtrl_SetLineIndentation, 3088). --define(wxStyledTextCtrl_GetLineIndentation, 3089). --define(wxStyledTextCtrl_GetLineIndentPosition, 3090). --define(wxStyledTextCtrl_GetColumn, 3091). --define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3092). --define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3093). --define(wxStyledTextCtrl_SetIndentationGuides, 3094). --define(wxStyledTextCtrl_GetIndentationGuides, 3095). --define(wxStyledTextCtrl_SetHighlightGuide, 3096). --define(wxStyledTextCtrl_GetHighlightGuide, 3097). --define(wxStyledTextCtrl_GetLineEndPosition, 3098). --define(wxStyledTextCtrl_GetCodePage, 3099). --define(wxStyledTextCtrl_GetCaretForeground, 3100). --define(wxStyledTextCtrl_GetReadOnly, 3101). --define(wxStyledTextCtrl_SetCurrentPos, 3102). --define(wxStyledTextCtrl_SetSelectionStart, 3103). --define(wxStyledTextCtrl_GetSelectionStart, 3104). --define(wxStyledTextCtrl_SetSelectionEnd, 3105). --define(wxStyledTextCtrl_GetSelectionEnd, 3106). --define(wxStyledTextCtrl_SetPrintMagnification, 3107). --define(wxStyledTextCtrl_GetPrintMagnification, 3108). --define(wxStyledTextCtrl_SetPrintColourMode, 3109). --define(wxStyledTextCtrl_GetPrintColourMode, 3110). --define(wxStyledTextCtrl_FindText, 3111). --define(wxStyledTextCtrl_FormatRange, 3112). --define(wxStyledTextCtrl_GetFirstVisibleLine, 3113). --define(wxStyledTextCtrl_GetLine, 3114). --define(wxStyledTextCtrl_GetLineCount, 3115). --define(wxStyledTextCtrl_SetMarginLeft, 3116). --define(wxStyledTextCtrl_GetMarginLeft, 3117). --define(wxStyledTextCtrl_SetMarginRight, 3118). --define(wxStyledTextCtrl_GetMarginRight, 3119). --define(wxStyledTextCtrl_GetModify, 3120). --define(wxStyledTextCtrl_SetSelection, 3121). --define(wxStyledTextCtrl_GetSelectedText, 3122). --define(wxStyledTextCtrl_GetTextRange, 3123). --define(wxStyledTextCtrl_HideSelection, 3124). --define(wxStyledTextCtrl_LineFromPosition, 3125). --define(wxStyledTextCtrl_PositionFromLine, 3126). --define(wxStyledTextCtrl_LineScroll, 3127). --define(wxStyledTextCtrl_EnsureCaretVisible, 3128). --define(wxStyledTextCtrl_ReplaceSelection, 3129). --define(wxStyledTextCtrl_SetReadOnly, 3130). --define(wxStyledTextCtrl_CanPaste, 3131). --define(wxStyledTextCtrl_CanUndo, 3132). --define(wxStyledTextCtrl_EmptyUndoBuffer, 3133). --define(wxStyledTextCtrl_Undo, 3134). --define(wxStyledTextCtrl_Cut, 3135). --define(wxStyledTextCtrl_Copy, 3136). --define(wxStyledTextCtrl_Paste, 3137). --define(wxStyledTextCtrl_Clear, 3138). --define(wxStyledTextCtrl_SetText, 3139). --define(wxStyledTextCtrl_GetText, 3140). --define(wxStyledTextCtrl_GetTextLength, 3141). --define(wxStyledTextCtrl_GetOvertype, 3142). --define(wxStyledTextCtrl_SetCaretWidth, 3143). --define(wxStyledTextCtrl_GetCaretWidth, 3144). --define(wxStyledTextCtrl_SetTargetStart, 3145). --define(wxStyledTextCtrl_GetTargetStart, 3146). --define(wxStyledTextCtrl_SetTargetEnd, 3147). --define(wxStyledTextCtrl_GetTargetEnd, 3148). --define(wxStyledTextCtrl_ReplaceTarget, 3149). --define(wxStyledTextCtrl_SearchInTarget, 3150). --define(wxStyledTextCtrl_SetSearchFlags, 3151). --define(wxStyledTextCtrl_GetSearchFlags, 3152). --define(wxStyledTextCtrl_CallTipShow, 3153). --define(wxStyledTextCtrl_CallTipCancel, 3154). --define(wxStyledTextCtrl_CallTipActive, 3155). --define(wxStyledTextCtrl_CallTipPosAtStart, 3156). --define(wxStyledTextCtrl_CallTipSetHighlight, 3157). --define(wxStyledTextCtrl_CallTipSetBackground, 3158). --define(wxStyledTextCtrl_CallTipSetForeground, 3159). --define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3160). --define(wxStyledTextCtrl_CallTipUseStyle, 3161). --define(wxStyledTextCtrl_VisibleFromDocLine, 3162). --define(wxStyledTextCtrl_DocLineFromVisible, 3163). --define(wxStyledTextCtrl_WrapCount, 3164). --define(wxStyledTextCtrl_SetFoldLevel, 3165). --define(wxStyledTextCtrl_GetFoldLevel, 3166). --define(wxStyledTextCtrl_GetLastChild, 3167). --define(wxStyledTextCtrl_GetFoldParent, 3168). --define(wxStyledTextCtrl_ShowLines, 3169). --define(wxStyledTextCtrl_HideLines, 3170). --define(wxStyledTextCtrl_GetLineVisible, 3171). --define(wxStyledTextCtrl_SetFoldExpanded, 3172). --define(wxStyledTextCtrl_GetFoldExpanded, 3173). --define(wxStyledTextCtrl_ToggleFold, 3174). --define(wxStyledTextCtrl_EnsureVisible, 3175). --define(wxStyledTextCtrl_SetFoldFlags, 3176). --define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3177). --define(wxStyledTextCtrl_SetTabIndents, 3178). --define(wxStyledTextCtrl_GetTabIndents, 3179). --define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3180). --define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3181). --define(wxStyledTextCtrl_SetMouseDwellTime, 3182). --define(wxStyledTextCtrl_GetMouseDwellTime, 3183). --define(wxStyledTextCtrl_WordStartPosition, 3184). --define(wxStyledTextCtrl_WordEndPosition, 3185). --define(wxStyledTextCtrl_SetWrapMode, 3186). --define(wxStyledTextCtrl_GetWrapMode, 3187). --define(wxStyledTextCtrl_SetWrapVisualFlags, 3188). --define(wxStyledTextCtrl_GetWrapVisualFlags, 3189). --define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3190). --define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3191). --define(wxStyledTextCtrl_SetWrapStartIndent, 3192). --define(wxStyledTextCtrl_GetWrapStartIndent, 3193). --define(wxStyledTextCtrl_SetLayoutCache, 3194). --define(wxStyledTextCtrl_GetLayoutCache, 3195). --define(wxStyledTextCtrl_SetScrollWidth, 3196). --define(wxStyledTextCtrl_GetScrollWidth, 3197). --define(wxStyledTextCtrl_TextWidth, 3198). --define(wxStyledTextCtrl_GetEndAtLastLine, 3199). --define(wxStyledTextCtrl_TextHeight, 3200). --define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3201). --define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3202). --define(wxStyledTextCtrl_AppendText, 3203). --define(wxStyledTextCtrl_GetTwoPhaseDraw, 3204). --define(wxStyledTextCtrl_SetTwoPhaseDraw, 3205). --define(wxStyledTextCtrl_TargetFromSelection, 3206). --define(wxStyledTextCtrl_LinesJoin, 3207). --define(wxStyledTextCtrl_LinesSplit, 3208). --define(wxStyledTextCtrl_SetFoldMarginColour, 3209). --define(wxStyledTextCtrl_SetFoldMarginHiColour, 3210). --define(wxStyledTextCtrl_LineDown, 3211). --define(wxStyledTextCtrl_LineDownExtend, 3212). --define(wxStyledTextCtrl_LineUp, 3213). --define(wxStyledTextCtrl_LineUpExtend, 3214). --define(wxStyledTextCtrl_CharLeft, 3215). --define(wxStyledTextCtrl_CharLeftExtend, 3216). --define(wxStyledTextCtrl_CharRight, 3217). --define(wxStyledTextCtrl_CharRightExtend, 3218). --define(wxStyledTextCtrl_WordLeft, 3219). --define(wxStyledTextCtrl_WordLeftExtend, 3220). --define(wxStyledTextCtrl_WordRight, 3221). --define(wxStyledTextCtrl_WordRightExtend, 3222). --define(wxStyledTextCtrl_Home, 3223). --define(wxStyledTextCtrl_HomeExtend, 3224). --define(wxStyledTextCtrl_LineEnd, 3225). --define(wxStyledTextCtrl_LineEndExtend, 3226). --define(wxStyledTextCtrl_DocumentStart, 3227). --define(wxStyledTextCtrl_DocumentStartExtend, 3228). --define(wxStyledTextCtrl_DocumentEnd, 3229). --define(wxStyledTextCtrl_DocumentEndExtend, 3230). --define(wxStyledTextCtrl_PageUp, 3231). --define(wxStyledTextCtrl_PageUpExtend, 3232). --define(wxStyledTextCtrl_PageDown, 3233). --define(wxStyledTextCtrl_PageDownExtend, 3234). --define(wxStyledTextCtrl_EditToggleOvertype, 3235). --define(wxStyledTextCtrl_Cancel, 3236). --define(wxStyledTextCtrl_DeleteBack, 3237). --define(wxStyledTextCtrl_Tab, 3238). --define(wxStyledTextCtrl_BackTab, 3239). --define(wxStyledTextCtrl_NewLine, 3240). --define(wxStyledTextCtrl_FormFeed, 3241). --define(wxStyledTextCtrl_VCHome, 3242). --define(wxStyledTextCtrl_VCHomeExtend, 3243). --define(wxStyledTextCtrl_ZoomIn, 3244). --define(wxStyledTextCtrl_ZoomOut, 3245). --define(wxStyledTextCtrl_DelWordLeft, 3246). --define(wxStyledTextCtrl_DelWordRight, 3247). --define(wxStyledTextCtrl_LineCut, 3248). --define(wxStyledTextCtrl_LineDelete, 3249). --define(wxStyledTextCtrl_LineTranspose, 3250). --define(wxStyledTextCtrl_LineDuplicate, 3251). --define(wxStyledTextCtrl_LowerCase, 3252). --define(wxStyledTextCtrl_UpperCase, 3253). --define(wxStyledTextCtrl_LineScrollDown, 3254). --define(wxStyledTextCtrl_LineScrollUp, 3255). --define(wxStyledTextCtrl_DeleteBackNotLine, 3256). --define(wxStyledTextCtrl_HomeDisplay, 3257). --define(wxStyledTextCtrl_HomeDisplayExtend, 3258). --define(wxStyledTextCtrl_LineEndDisplay, 3259). --define(wxStyledTextCtrl_LineEndDisplayExtend, 3260). --define(wxStyledTextCtrl_HomeWrapExtend, 3261). --define(wxStyledTextCtrl_LineEndWrap, 3262). --define(wxStyledTextCtrl_LineEndWrapExtend, 3263). --define(wxStyledTextCtrl_VCHomeWrap, 3264). --define(wxStyledTextCtrl_VCHomeWrapExtend, 3265). --define(wxStyledTextCtrl_LineCopy, 3266). --define(wxStyledTextCtrl_MoveCaretInsideView, 3267). --define(wxStyledTextCtrl_LineLength, 3268). --define(wxStyledTextCtrl_BraceHighlight, 3269). --define(wxStyledTextCtrl_BraceBadLight, 3270). --define(wxStyledTextCtrl_BraceMatch, 3271). --define(wxStyledTextCtrl_GetViewEOL, 3272). --define(wxStyledTextCtrl_SetViewEOL, 3273). --define(wxStyledTextCtrl_SetModEventMask, 3274). --define(wxStyledTextCtrl_GetEdgeColumn, 3275). --define(wxStyledTextCtrl_SetEdgeColumn, 3276). --define(wxStyledTextCtrl_SetEdgeMode, 3277). --define(wxStyledTextCtrl_GetEdgeMode, 3278). --define(wxStyledTextCtrl_GetEdgeColour, 3279). --define(wxStyledTextCtrl_SetEdgeColour, 3280). --define(wxStyledTextCtrl_SearchAnchor, 3281). --define(wxStyledTextCtrl_SearchNext, 3282). --define(wxStyledTextCtrl_SearchPrev, 3283). --define(wxStyledTextCtrl_LinesOnScreen, 3284). --define(wxStyledTextCtrl_UsePopUp, 3285). --define(wxStyledTextCtrl_SelectionIsRectangle, 3286). --define(wxStyledTextCtrl_SetZoom, 3287). --define(wxStyledTextCtrl_GetZoom, 3288). --define(wxStyledTextCtrl_GetModEventMask, 3289). --define(wxStyledTextCtrl_SetSTCFocus, 3290). --define(wxStyledTextCtrl_GetSTCFocus, 3291). --define(wxStyledTextCtrl_SetStatus, 3292). --define(wxStyledTextCtrl_GetStatus, 3293). --define(wxStyledTextCtrl_SetMouseDownCaptures, 3294). --define(wxStyledTextCtrl_GetMouseDownCaptures, 3295). --define(wxStyledTextCtrl_SetSTCCursor, 3296). --define(wxStyledTextCtrl_GetSTCCursor, 3297). --define(wxStyledTextCtrl_SetControlCharSymbol, 3298). --define(wxStyledTextCtrl_GetControlCharSymbol, 3299). --define(wxStyledTextCtrl_WordPartLeft, 3300). --define(wxStyledTextCtrl_WordPartLeftExtend, 3301). --define(wxStyledTextCtrl_WordPartRight, 3302). --define(wxStyledTextCtrl_WordPartRightExtend, 3303). --define(wxStyledTextCtrl_SetVisiblePolicy, 3304). --define(wxStyledTextCtrl_DelLineLeft, 3305). --define(wxStyledTextCtrl_DelLineRight, 3306). --define(wxStyledTextCtrl_GetXOffset, 3307). --define(wxStyledTextCtrl_ChooseCaretX, 3308). --define(wxStyledTextCtrl_SetXCaretPolicy, 3309). --define(wxStyledTextCtrl_SetYCaretPolicy, 3310). --define(wxStyledTextCtrl_GetPrintWrapMode, 3311). --define(wxStyledTextCtrl_SetHotspotActiveForeground, 3312). --define(wxStyledTextCtrl_SetHotspotActiveBackground, 3313). --define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3314). --define(wxStyledTextCtrl_SetHotspotSingleLine, 3315). --define(wxStyledTextCtrl_ParaDownExtend, 3316). --define(wxStyledTextCtrl_ParaUp, 3317). --define(wxStyledTextCtrl_ParaUpExtend, 3318). --define(wxStyledTextCtrl_PositionBefore, 3319). --define(wxStyledTextCtrl_PositionAfter, 3320). --define(wxStyledTextCtrl_CopyRange, 3321). --define(wxStyledTextCtrl_CopyText, 3322). --define(wxStyledTextCtrl_SetSelectionMode, 3323). --define(wxStyledTextCtrl_GetSelectionMode, 3324). --define(wxStyledTextCtrl_LineDownRectExtend, 3325). --define(wxStyledTextCtrl_LineUpRectExtend, 3326). --define(wxStyledTextCtrl_CharLeftRectExtend, 3327). --define(wxStyledTextCtrl_CharRightRectExtend, 3328). --define(wxStyledTextCtrl_HomeRectExtend, 3329). --define(wxStyledTextCtrl_VCHomeRectExtend, 3330). --define(wxStyledTextCtrl_LineEndRectExtend, 3331). --define(wxStyledTextCtrl_PageUpRectExtend, 3332). --define(wxStyledTextCtrl_PageDownRectExtend, 3333). --define(wxStyledTextCtrl_StutteredPageUp, 3334). --define(wxStyledTextCtrl_StutteredPageUpExtend, 3335). --define(wxStyledTextCtrl_StutteredPageDown, 3336). --define(wxStyledTextCtrl_StutteredPageDownExtend, 3337). --define(wxStyledTextCtrl_WordLeftEnd, 3338). --define(wxStyledTextCtrl_WordLeftEndExtend, 3339). --define(wxStyledTextCtrl_WordRightEnd, 3340). --define(wxStyledTextCtrl_WordRightEndExtend, 3341). --define(wxStyledTextCtrl_SetWhitespaceChars, 3342). --define(wxStyledTextCtrl_SetCharsDefault, 3343). --define(wxStyledTextCtrl_AutoCompGetCurrent, 3344). --define(wxStyledTextCtrl_Allocate, 3345). --define(wxStyledTextCtrl_FindColumn, 3346). --define(wxStyledTextCtrl_GetCaretSticky, 3347). --define(wxStyledTextCtrl_SetCaretSticky, 3348). --define(wxStyledTextCtrl_ToggleCaretSticky, 3349). --define(wxStyledTextCtrl_SetPasteConvertEndings, 3350). --define(wxStyledTextCtrl_GetPasteConvertEndings, 3351). --define(wxStyledTextCtrl_SelectionDuplicate, 3352). --define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3353). --define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3354). --define(wxStyledTextCtrl_StartRecord, 3355). --define(wxStyledTextCtrl_StopRecord, 3356). --define(wxStyledTextCtrl_SetLexer, 3357). --define(wxStyledTextCtrl_GetLexer, 3358). --define(wxStyledTextCtrl_Colourise, 3359). --define(wxStyledTextCtrl_SetProperty, 3360). --define(wxStyledTextCtrl_SetKeyWords, 3361). --define(wxStyledTextCtrl_SetLexerLanguage, 3362). --define(wxStyledTextCtrl_GetProperty, 3363). --define(wxStyledTextCtrl_GetStyleBitsNeeded, 3364). --define(wxStyledTextCtrl_GetCurrentLine, 3365). --define(wxStyledTextCtrl_StyleSetSpec, 3366). --define(wxStyledTextCtrl_StyleSetFont, 3367). --define(wxStyledTextCtrl_StyleSetFontAttr, 3368). --define(wxStyledTextCtrl_StyleSetCharacterSet, 3369). --define(wxStyledTextCtrl_StyleSetFontEncoding, 3370). --define(wxStyledTextCtrl_CmdKeyExecute, 3371). --define(wxStyledTextCtrl_SetMargins, 3372). --define(wxStyledTextCtrl_GetSelection, 3373). --define(wxStyledTextCtrl_PointFromPosition, 3374). --define(wxStyledTextCtrl_ScrollToLine, 3375). --define(wxStyledTextCtrl_ScrollToColumn, 3376). --define(wxStyledTextCtrl_SetVScrollBar, 3377). --define(wxStyledTextCtrl_SetHScrollBar, 3378). --define(wxStyledTextCtrl_GetLastKeydownProcessed, 3379). --define(wxStyledTextCtrl_SetLastKeydownProcessed, 3380). --define(wxStyledTextCtrl_SaveFile, 3381). --define(wxStyledTextCtrl_LoadFile, 3382). --define(wxStyledTextCtrl_DoDragOver, 3383). --define(wxStyledTextCtrl_DoDropText, 3384). --define(wxStyledTextCtrl_GetUseAntiAliasing, 3385). --define(wxStyledTextCtrl_AddTextRaw, 3386). --define(wxStyledTextCtrl_InsertTextRaw, 3387). --define(wxStyledTextCtrl_GetCurLineRaw, 3388). --define(wxStyledTextCtrl_GetLineRaw, 3389). --define(wxStyledTextCtrl_GetSelectedTextRaw, 3390). --define(wxStyledTextCtrl_GetTextRangeRaw, 3391). --define(wxStyledTextCtrl_SetTextRaw, 3392). --define(wxStyledTextCtrl_GetTextRaw, 3393). --define(wxStyledTextCtrl_AppendTextRaw, 3394). --define(wxArtProvider_GetBitmap, 3395). --define(wxArtProvider_GetIcon, 3396). --define(wxTreeEvent_GetKeyCode, 3397). --define(wxTreeEvent_GetItem, 3398). --define(wxTreeEvent_GetKeyEvent, 3399). --define(wxTreeEvent_GetLabel, 3400). --define(wxTreeEvent_GetOldItem, 3401). --define(wxTreeEvent_GetPoint, 3402). --define(wxTreeEvent_IsEditCancelled, 3403). --define(wxTreeEvent_SetToolTip, 3404). --define(wxNotebookEvent_GetOldSelection, 3405). --define(wxNotebookEvent_GetSelection, 3406). --define(wxNotebookEvent_SetOldSelection, 3407). --define(wxNotebookEvent_SetSelection, 3408). --define(wxFileDataObject_new, 3409). --define(wxFileDataObject_AddFile, 3410). --define(wxFileDataObject_GetFilenames, 3411). --define(wxFileDataObject_destroy, 3412). --define(wxTextDataObject_new, 3413). --define(wxTextDataObject_GetTextLength, 3414). --define(wxTextDataObject_GetText, 3415). --define(wxTextDataObject_SetText, 3416). --define(wxTextDataObject_destroy, 3417). --define(wxBitmapDataObject_new_1_1, 3418). --define(wxBitmapDataObject_new_1_0, 3419). --define(wxBitmapDataObject_GetBitmap, 3420). --define(wxBitmapDataObject_SetBitmap, 3421). --define(wxBitmapDataObject_destroy, 3422). --define(wxClipboard_new, 3424). --define(wxClipboard_destruct, 3425). --define(wxClipboard_AddData, 3426). --define(wxClipboard_Clear, 3427). --define(wxClipboard_Close, 3428). --define(wxClipboard_Flush, 3429). --define(wxClipboard_GetData, 3430). --define(wxClipboard_IsOpened, 3431). --define(wxClipboard_Open, 3432). --define(wxClipboard_SetData, 3433). --define(wxClipboard_UsePrimarySelection, 3435). --define(wxClipboard_IsSupported, 3436). --define(wxClipboard_Get, 3437). --define(wxSpinEvent_GetPosition, 3438). --define(wxSpinEvent_SetPosition, 3439). --define(wxSplitterWindow_new_0, 3440). --define(wxSplitterWindow_new_2, 3441). --define(wxSplitterWindow_destruct, 3442). --define(wxSplitterWindow_Create, 3443). --define(wxSplitterWindow_GetMinimumPaneSize, 3444). --define(wxSplitterWindow_GetSashGravity, 3445). --define(wxSplitterWindow_GetSashPosition, 3446). --define(wxSplitterWindow_GetSplitMode, 3447). --define(wxSplitterWindow_GetWindow1, 3448). --define(wxSplitterWindow_GetWindow2, 3449). --define(wxSplitterWindow_Initialize, 3450). --define(wxSplitterWindow_IsSplit, 3451). --define(wxSplitterWindow_ReplaceWindow, 3452). --define(wxSplitterWindow_SetSashGravity, 3453). --define(wxSplitterWindow_SetSashPosition, 3454). --define(wxSplitterWindow_SetSashSize, 3455). --define(wxSplitterWindow_SetMinimumPaneSize, 3456). --define(wxSplitterWindow_SetSplitMode, 3457). --define(wxSplitterWindow_SplitHorizontally, 3458). --define(wxSplitterWindow_SplitVertically, 3459). --define(wxSplitterWindow_Unsplit, 3460). --define(wxSplitterWindow_UpdateSize, 3461). --define(wxSplitterEvent_GetSashPosition, 3462). --define(wxSplitterEvent_GetX, 3463). --define(wxSplitterEvent_GetY, 3464). --define(wxSplitterEvent_GetWindowBeingRemoved, 3465). --define(wxSplitterEvent_SetSashPosition, 3466). --define(wxHtmlWindow_new_0, 3467). --define(wxHtmlWindow_new_2, 3468). --define(wxHtmlWindow_AppendToPage, 3469). --define(wxHtmlWindow_GetOpenedAnchor, 3470). --define(wxHtmlWindow_GetOpenedPage, 3471). --define(wxHtmlWindow_GetOpenedPageTitle, 3472). --define(wxHtmlWindow_GetRelatedFrame, 3473). --define(wxHtmlWindow_HistoryBack, 3474). --define(wxHtmlWindow_HistoryCanBack, 3475). --define(wxHtmlWindow_HistoryCanForward, 3476). --define(wxHtmlWindow_HistoryClear, 3477). --define(wxHtmlWindow_HistoryForward, 3478). --define(wxHtmlWindow_LoadFile, 3479). --define(wxHtmlWindow_LoadPage, 3480). --define(wxHtmlWindow_SelectAll, 3481). --define(wxHtmlWindow_SelectionToText, 3482). --define(wxHtmlWindow_SelectLine, 3483). --define(wxHtmlWindow_SelectWord, 3484). --define(wxHtmlWindow_SetBorders, 3485). --define(wxHtmlWindow_SetFonts, 3486). --define(wxHtmlWindow_SetPage, 3487). --define(wxHtmlWindow_SetRelatedFrame, 3488). --define(wxHtmlWindow_SetRelatedStatusBar, 3489). --define(wxHtmlWindow_ToText, 3490). --define(wxHtmlWindow_destroy, 3491). --define(wxHtmlLinkEvent_GetLinkInfo, 3492). --define(wxSystemSettings_GetColour, 3493). --define(wxSystemSettings_GetFont, 3494). --define(wxSystemSettings_GetMetric, 3495). --define(wxSystemSettings_GetScreenType, 3496). --define(wxSystemOptions_GetOption, 3497). --define(wxSystemOptions_GetOptionInt, 3498). --define(wxSystemOptions_HasOption, 3499). --define(wxSystemOptions_IsFalse, 3500). --define(wxSystemOptions_SetOption_2_1, 3501). --define(wxSystemOptions_SetOption_2_0, 3502). --define(wxAuiNotebookEvent_SetSelection, 3503). --define(wxAuiNotebookEvent_GetSelection, 3504). --define(wxAuiNotebookEvent_SetOldSelection, 3505). --define(wxAuiNotebookEvent_GetOldSelection, 3506). --define(wxAuiNotebookEvent_SetDragSource, 3507). --define(wxAuiNotebookEvent_GetDragSource, 3508). --define(wxAuiManagerEvent_SetManager, 3509). --define(wxAuiManagerEvent_GetManager, 3510). --define(wxAuiManagerEvent_SetPane, 3511). --define(wxAuiManagerEvent_GetPane, 3512). --define(wxAuiManagerEvent_SetButton, 3513). --define(wxAuiManagerEvent_GetButton, 3514). --define(wxAuiManagerEvent_SetDC, 3515). --define(wxAuiManagerEvent_GetDC, 3516). --define(wxAuiManagerEvent_Veto, 3517). --define(wxAuiManagerEvent_GetVeto, 3518). --define(wxAuiManagerEvent_SetCanVeto, 3519). --define(wxAuiManagerEvent_CanVeto, 3520). --define(wxLogNull_new, 3521). --define(wxLogNull_destroy, 3522). --define(wxTaskBarIcon_new, 3523). --define(wxTaskBarIcon_destruct, 3524). --define(wxTaskBarIcon_PopupMenu, 3525). --define(wxTaskBarIcon_RemoveIcon, 3526). --define(wxTaskBarIcon_SetIcon, 3527). --define(wxLocale_new_0, 3528). --define(wxLocale_new_2, 3530). --define(wxLocale_destruct, 3531). --define(wxLocale_Init, 3533). --define(wxLocale_AddCatalog_1, 3534). --define(wxLocale_AddCatalog_3, 3535). --define(wxLocale_AddCatalogLookupPathPrefix, 3536). --define(wxLocale_GetCanonicalName, 3537). --define(wxLocale_GetLanguage, 3538). --define(wxLocale_GetLanguageName, 3539). --define(wxLocale_GetLocale, 3540). --define(wxLocale_GetName, 3541). --define(wxLocale_GetString_2, 3542). --define(wxLocale_GetString_4, 3543). --define(wxLocale_GetHeaderValue, 3544). --define(wxLocale_GetSysName, 3545). --define(wxLocale_GetSystemEncoding, 3546). --define(wxLocale_GetSystemEncodingName, 3547). --define(wxLocale_GetSystemLanguage, 3548). --define(wxLocale_IsLoaded, 3549). --define(wxLocale_IsOk, 3550). --define(wxActivateEvent_GetActive, 3551). --define(wxPopupWindow_new_2, 3553). --define(wxPopupWindow_new_0, 3554). --define(wxPopupWindow_destruct, 3556). --define(wxPopupWindow_Create, 3557). --define(wxPopupWindow_Position, 3558). --define(wxPopupTransientWindow_new_0, 3559). --define(wxPopupTransientWindow_new_2, 3560). --define(wxPopupTransientWindow_destruct, 3561). --define(wxPopupTransientWindow_Popup, 3562). --define(wxPopupTransientWindow_Dismiss, 3563). +-define(wxAuiTabArt_SetFlags, 2675). +-define(wxAuiTabArt_SetMeasuringFont, 2676). +-define(wxAuiTabArt_SetNormalFont, 2677). +-define(wxAuiTabArt_SetSelectedFont, 2678). +-define(wxAuiTabArt_SetColour, 2679). +-define(wxAuiTabArt_SetActiveColour, 2680). +-define(wxAuiDockArt_GetColour, 2681). +-define(wxAuiDockArt_GetFont, 2682). +-define(wxAuiDockArt_GetMetric, 2683). +-define(wxAuiDockArt_SetColour, 2684). +-define(wxAuiDockArt_SetFont, 2685). +-define(wxAuiDockArt_SetMetric, 2686). +-define(wxAuiSimpleTabArt_new, 2687). +-define(wxAuiSimpleTabArt_destroy, 2688). +-define(wxMDIParentFrame_new_0, 2689). +-define(wxMDIParentFrame_new_4, 2690). +-define(wxMDIParentFrame_destruct, 2691). +-define(wxMDIParentFrame_ActivateNext, 2692). +-define(wxMDIParentFrame_ActivatePrevious, 2693). +-define(wxMDIParentFrame_ArrangeIcons, 2694). +-define(wxMDIParentFrame_Cascade, 2695). +-define(wxMDIParentFrame_Create, 2696). +-define(wxMDIParentFrame_GetActiveChild, 2697). +-define(wxMDIParentFrame_GetClientWindow, 2698). +-define(wxMDIParentFrame_Tile, 2699). +-define(wxMDIChildFrame_new_0, 2700). +-define(wxMDIChildFrame_new_4, 2701). +-define(wxMDIChildFrame_destruct, 2702). +-define(wxMDIChildFrame_Activate, 2703). +-define(wxMDIChildFrame_Create, 2704). +-define(wxMDIChildFrame_Maximize, 2705). +-define(wxMDIChildFrame_Restore, 2706). +-define(wxMDIClientWindow_new_0, 2707). +-define(wxMDIClientWindow_new_2, 2708). +-define(wxMDIClientWindow_destruct, 2709). +-define(wxMDIClientWindow_CreateClient, 2710). +-define(wxLayoutAlgorithm_new, 2711). +-define(wxLayoutAlgorithm_LayoutFrame, 2712). +-define(wxLayoutAlgorithm_LayoutMDIFrame, 2713). +-define(wxLayoutAlgorithm_LayoutWindow, 2714). +-define(wxLayoutAlgorithm_destroy, 2715). +-define(wxEvent_GetId, 2716). +-define(wxEvent_GetSkipped, 2717). +-define(wxEvent_GetTimestamp, 2718). +-define(wxEvent_IsCommandEvent, 2719). +-define(wxEvent_ResumePropagation, 2720). +-define(wxEvent_ShouldPropagate, 2721). +-define(wxEvent_Skip, 2722). +-define(wxEvent_StopPropagation, 2723). +-define(wxCommandEvent_getClientData, 2724). +-define(wxCommandEvent_GetExtraLong, 2725). +-define(wxCommandEvent_GetInt, 2726). +-define(wxCommandEvent_GetSelection, 2727). +-define(wxCommandEvent_GetString, 2728). +-define(wxCommandEvent_IsChecked, 2729). +-define(wxCommandEvent_IsSelection, 2730). +-define(wxCommandEvent_SetInt, 2731). +-define(wxCommandEvent_SetString, 2732). +-define(wxScrollEvent_GetOrientation, 2733). +-define(wxScrollEvent_GetPosition, 2734). +-define(wxScrollWinEvent_GetOrientation, 2735). +-define(wxScrollWinEvent_GetPosition, 2736). +-define(wxMouseEvent_AltDown, 2737). +-define(wxMouseEvent_Button, 2738). +-define(wxMouseEvent_ButtonDClick, 2739). +-define(wxMouseEvent_ButtonDown, 2740). +-define(wxMouseEvent_ButtonUp, 2741). +-define(wxMouseEvent_CmdDown, 2742). +-define(wxMouseEvent_ControlDown, 2743). +-define(wxMouseEvent_Dragging, 2744). +-define(wxMouseEvent_Entering, 2745). +-define(wxMouseEvent_GetButton, 2746). +-define(wxMouseEvent_GetPosition, 2749). +-define(wxMouseEvent_GetLogicalPosition, 2750). +-define(wxMouseEvent_GetLinesPerAction, 2751). +-define(wxMouseEvent_GetWheelRotation, 2752). +-define(wxMouseEvent_GetWheelDelta, 2753). +-define(wxMouseEvent_GetX, 2754). +-define(wxMouseEvent_GetY, 2755). +-define(wxMouseEvent_IsButton, 2756). +-define(wxMouseEvent_IsPageScroll, 2757). +-define(wxMouseEvent_Leaving, 2758). +-define(wxMouseEvent_LeftDClick, 2759). +-define(wxMouseEvent_LeftDown, 2760). +-define(wxMouseEvent_LeftIsDown, 2761). +-define(wxMouseEvent_LeftUp, 2762). +-define(wxMouseEvent_MetaDown, 2763). +-define(wxMouseEvent_MiddleDClick, 2764). +-define(wxMouseEvent_MiddleDown, 2765). +-define(wxMouseEvent_MiddleIsDown, 2766). +-define(wxMouseEvent_MiddleUp, 2767). +-define(wxMouseEvent_Moving, 2768). +-define(wxMouseEvent_RightDClick, 2769). +-define(wxMouseEvent_RightDown, 2770). +-define(wxMouseEvent_RightIsDown, 2771). +-define(wxMouseEvent_RightUp, 2772). +-define(wxMouseEvent_ShiftDown, 2773). +-define(wxSetCursorEvent_GetCursor, 2774). +-define(wxSetCursorEvent_GetX, 2775). +-define(wxSetCursorEvent_GetY, 2776). +-define(wxSetCursorEvent_HasCursor, 2777). +-define(wxSetCursorEvent_SetCursor, 2778). +-define(wxKeyEvent_AltDown, 2779). +-define(wxKeyEvent_CmdDown, 2780). +-define(wxKeyEvent_ControlDown, 2781). +-define(wxKeyEvent_GetKeyCode, 2782). +-define(wxKeyEvent_GetModifiers, 2783). +-define(wxKeyEvent_GetPosition, 2786). +-define(wxKeyEvent_GetRawKeyCode, 2787). +-define(wxKeyEvent_GetRawKeyFlags, 2788). +-define(wxKeyEvent_GetUnicodeKey, 2789). +-define(wxKeyEvent_GetX, 2790). +-define(wxKeyEvent_GetY, 2791). +-define(wxKeyEvent_HasModifiers, 2792). +-define(wxKeyEvent_MetaDown, 2793). +-define(wxKeyEvent_ShiftDown, 2794). +-define(wxSizeEvent_GetSize, 2795). +-define(wxMoveEvent_GetPosition, 2796). +-define(wxEraseEvent_GetDC, 2797). +-define(wxFocusEvent_GetWindow, 2798). +-define(wxChildFocusEvent_GetWindow, 2799). +-define(wxMenuEvent_GetMenu, 2800). +-define(wxMenuEvent_GetMenuId, 2801). +-define(wxMenuEvent_IsPopup, 2802). +-define(wxCloseEvent_CanVeto, 2803). +-define(wxCloseEvent_GetLoggingOff, 2804). +-define(wxCloseEvent_SetCanVeto, 2805). +-define(wxCloseEvent_SetLoggingOff, 2806). +-define(wxCloseEvent_Veto, 2807). +-define(wxShowEvent_SetShow, 2808). +-define(wxShowEvent_GetShow, 2809). +-define(wxIconizeEvent_Iconized, 2810). +-define(wxJoystickEvent_ButtonDown, 2811). +-define(wxJoystickEvent_ButtonIsDown, 2812). +-define(wxJoystickEvent_ButtonUp, 2813). +-define(wxJoystickEvent_GetButtonChange, 2814). +-define(wxJoystickEvent_GetButtonState, 2815). +-define(wxJoystickEvent_GetJoystick, 2816). +-define(wxJoystickEvent_GetPosition, 2817). +-define(wxJoystickEvent_GetZPosition, 2818). +-define(wxJoystickEvent_IsButton, 2819). +-define(wxJoystickEvent_IsMove, 2820). +-define(wxJoystickEvent_IsZMove, 2821). +-define(wxUpdateUIEvent_CanUpdate, 2822). +-define(wxUpdateUIEvent_Check, 2823). +-define(wxUpdateUIEvent_Enable, 2824). +-define(wxUpdateUIEvent_Show, 2825). +-define(wxUpdateUIEvent_GetChecked, 2826). +-define(wxUpdateUIEvent_GetEnabled, 2827). +-define(wxUpdateUIEvent_GetShown, 2828). +-define(wxUpdateUIEvent_GetSetChecked, 2829). +-define(wxUpdateUIEvent_GetSetEnabled, 2830). +-define(wxUpdateUIEvent_GetSetShown, 2831). +-define(wxUpdateUIEvent_GetSetText, 2832). +-define(wxUpdateUIEvent_GetText, 2833). +-define(wxUpdateUIEvent_GetMode, 2834). +-define(wxUpdateUIEvent_GetUpdateInterval, 2835). +-define(wxUpdateUIEvent_ResetUpdateTime, 2836). +-define(wxUpdateUIEvent_SetMode, 2837). +-define(wxUpdateUIEvent_SetText, 2838). +-define(wxUpdateUIEvent_SetUpdateInterval, 2839). +-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2840). +-define(wxPaletteChangedEvent_SetChangedWindow, 2841). +-define(wxPaletteChangedEvent_GetChangedWindow, 2842). +-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2843). +-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2844). +-define(wxNavigationKeyEvent_GetDirection, 2845). +-define(wxNavigationKeyEvent_SetDirection, 2846). +-define(wxNavigationKeyEvent_IsWindowChange, 2847). +-define(wxNavigationKeyEvent_SetWindowChange, 2848). +-define(wxNavigationKeyEvent_IsFromTab, 2849). +-define(wxNavigationKeyEvent_SetFromTab, 2850). +-define(wxNavigationKeyEvent_GetCurrentFocus, 2851). +-define(wxNavigationKeyEvent_SetCurrentFocus, 2852). +-define(wxHelpEvent_GetOrigin, 2853). +-define(wxHelpEvent_GetPosition, 2854). +-define(wxHelpEvent_SetOrigin, 2855). +-define(wxHelpEvent_SetPosition, 2856). +-define(wxContextMenuEvent_GetPosition, 2857). +-define(wxContextMenuEvent_SetPosition, 2858). +-define(wxIdleEvent_CanSend, 2859). +-define(wxIdleEvent_GetMode, 2860). +-define(wxIdleEvent_RequestMore, 2861). +-define(wxIdleEvent_MoreRequested, 2862). +-define(wxIdleEvent_SetMode, 2863). +-define(wxGridEvent_AltDown, 2864). +-define(wxGridEvent_ControlDown, 2865). +-define(wxGridEvent_GetCol, 2866). +-define(wxGridEvent_GetPosition, 2867). +-define(wxGridEvent_GetRow, 2868). +-define(wxGridEvent_MetaDown, 2869). +-define(wxGridEvent_Selecting, 2870). +-define(wxGridEvent_ShiftDown, 2871). +-define(wxNotifyEvent_Allow, 2872). +-define(wxNotifyEvent_IsAllowed, 2873). +-define(wxNotifyEvent_Veto, 2874). +-define(wxSashEvent_GetEdge, 2875). +-define(wxSashEvent_GetDragRect, 2876). +-define(wxSashEvent_GetDragStatus, 2877). +-define(wxListEvent_GetCacheFrom, 2878). +-define(wxListEvent_GetCacheTo, 2879). +-define(wxListEvent_GetKeyCode, 2880). +-define(wxListEvent_GetIndex, 2881). +-define(wxListEvent_GetColumn, 2882). +-define(wxListEvent_GetPoint, 2883). +-define(wxListEvent_GetLabel, 2884). +-define(wxListEvent_GetText, 2885). +-define(wxListEvent_GetImage, 2886). +-define(wxListEvent_GetData, 2887). +-define(wxListEvent_GetMask, 2888). +-define(wxListEvent_GetItem, 2889). +-define(wxListEvent_IsEditCancelled, 2890). +-define(wxDateEvent_GetDate, 2891). +-define(wxCalendarEvent_GetWeekDay, 2892). +-define(wxFileDirPickerEvent_GetPath, 2893). +-define(wxColourPickerEvent_GetColour, 2894). +-define(wxFontPickerEvent_GetFont, 2895). +-define(wxStyledTextEvent_GetPosition, 2896). +-define(wxStyledTextEvent_GetKey, 2897). +-define(wxStyledTextEvent_GetModifiers, 2898). +-define(wxStyledTextEvent_GetModificationType, 2899). +-define(wxStyledTextEvent_GetText, 2900). +-define(wxStyledTextEvent_GetLength, 2901). +-define(wxStyledTextEvent_GetLinesAdded, 2902). +-define(wxStyledTextEvent_GetLine, 2903). +-define(wxStyledTextEvent_GetFoldLevelNow, 2904). +-define(wxStyledTextEvent_GetFoldLevelPrev, 2905). +-define(wxStyledTextEvent_GetMargin, 2906). +-define(wxStyledTextEvent_GetMessage, 2907). +-define(wxStyledTextEvent_GetWParam, 2908). +-define(wxStyledTextEvent_GetLParam, 2909). +-define(wxStyledTextEvent_GetListType, 2910). +-define(wxStyledTextEvent_GetX, 2911). +-define(wxStyledTextEvent_GetY, 2912). +-define(wxStyledTextEvent_GetDragText, 2913). +-define(wxStyledTextEvent_GetDragAllowMove, 2914). +-define(wxStyledTextEvent_GetDragResult, 2915). +-define(wxStyledTextEvent_GetShift, 2916). +-define(wxStyledTextEvent_GetControl, 2917). +-define(wxStyledTextEvent_GetAlt, 2918). +-define(utils_wxGetKeyState, 2919). +-define(utils_wxGetMousePosition, 2920). +-define(utils_wxGetMouseState, 2921). +-define(utils_wxSetDetectableAutoRepeat, 2922). +-define(utils_wxBell, 2923). +-define(utils_wxFindMenuItemId, 2924). +-define(utils_wxGenericFindWindowAtPoint, 2925). +-define(utils_wxFindWindowAtPoint, 2926). +-define(utils_wxBeginBusyCursor, 2927). +-define(utils_wxEndBusyCursor, 2928). +-define(utils_wxIsBusy, 2929). +-define(utils_wxShutdown, 2930). +-define(utils_wxShell, 2931). +-define(utils_wxLaunchDefaultBrowser, 2932). +-define(utils_wxGetEmailAddress, 2933). +-define(utils_wxGetUserId, 2934). +-define(utils_wxGetHomeDir, 2935). +-define(utils_wxNewId, 2936). +-define(utils_wxRegisterId, 2937). +-define(utils_wxGetCurrentId, 2938). +-define(utils_wxGetOsDescription, 2939). +-define(utils_wxIsPlatformLittleEndian, 2940). +-define(utils_wxIsPlatform64Bit, 2941). +-define(gdicmn_wxDisplaySize, 2942). +-define(gdicmn_wxSetCursor, 2943). +-define(wxPrintout_new, 2944). +-define(wxPrintout_destruct, 2945). +-define(wxPrintout_GetDC, 2946). +-define(wxPrintout_GetPageSizeMM, 2947). +-define(wxPrintout_GetPageSizePixels, 2948). +-define(wxPrintout_GetPaperRectPixels, 2949). +-define(wxPrintout_GetPPIPrinter, 2950). +-define(wxPrintout_GetPPIScreen, 2951). +-define(wxPrintout_GetTitle, 2952). +-define(wxPrintout_IsPreview, 2953). +-define(wxPrintout_FitThisSizeToPaper, 2954). +-define(wxPrintout_FitThisSizeToPage, 2955). +-define(wxPrintout_FitThisSizeToPageMargins, 2956). +-define(wxPrintout_MapScreenSizeToPaper, 2957). +-define(wxPrintout_MapScreenSizeToPage, 2958). +-define(wxPrintout_MapScreenSizeToPageMargins, 2959). +-define(wxPrintout_MapScreenSizeToDevice, 2960). +-define(wxPrintout_GetLogicalPaperRect, 2961). +-define(wxPrintout_GetLogicalPageRect, 2962). +-define(wxPrintout_GetLogicalPageMarginsRect, 2963). +-define(wxPrintout_SetLogicalOrigin, 2964). +-define(wxPrintout_OffsetLogicalOrigin, 2965). +-define(wxStyledTextCtrl_new_2, 2966). +-define(wxStyledTextCtrl_new_0, 2967). +-define(wxStyledTextCtrl_destruct, 2968). +-define(wxStyledTextCtrl_Create, 2969). +-define(wxStyledTextCtrl_AddText, 2970). +-define(wxStyledTextCtrl_AddStyledText, 2971). +-define(wxStyledTextCtrl_InsertText, 2972). +-define(wxStyledTextCtrl_ClearAll, 2973). +-define(wxStyledTextCtrl_ClearDocumentStyle, 2974). +-define(wxStyledTextCtrl_GetLength, 2975). +-define(wxStyledTextCtrl_GetCharAt, 2976). +-define(wxStyledTextCtrl_GetCurrentPos, 2977). +-define(wxStyledTextCtrl_GetAnchor, 2978). +-define(wxStyledTextCtrl_GetStyleAt, 2979). +-define(wxStyledTextCtrl_Redo, 2980). +-define(wxStyledTextCtrl_SetUndoCollection, 2981). +-define(wxStyledTextCtrl_SelectAll, 2982). +-define(wxStyledTextCtrl_SetSavePoint, 2983). +-define(wxStyledTextCtrl_GetStyledText, 2984). +-define(wxStyledTextCtrl_CanRedo, 2985). +-define(wxStyledTextCtrl_MarkerLineFromHandle, 2986). +-define(wxStyledTextCtrl_MarkerDeleteHandle, 2987). +-define(wxStyledTextCtrl_GetUndoCollection, 2988). +-define(wxStyledTextCtrl_GetViewWhiteSpace, 2989). +-define(wxStyledTextCtrl_SetViewWhiteSpace, 2990). +-define(wxStyledTextCtrl_PositionFromPoint, 2991). +-define(wxStyledTextCtrl_PositionFromPointClose, 2992). +-define(wxStyledTextCtrl_GotoLine, 2993). +-define(wxStyledTextCtrl_GotoPos, 2994). +-define(wxStyledTextCtrl_SetAnchor, 2995). +-define(wxStyledTextCtrl_GetCurLine, 2996). +-define(wxStyledTextCtrl_GetEndStyled, 2997). +-define(wxStyledTextCtrl_ConvertEOLs, 2998). +-define(wxStyledTextCtrl_GetEOLMode, 2999). +-define(wxStyledTextCtrl_SetEOLMode, 3000). +-define(wxStyledTextCtrl_StartStyling, 3001). +-define(wxStyledTextCtrl_SetStyling, 3002). +-define(wxStyledTextCtrl_GetBufferedDraw, 3003). +-define(wxStyledTextCtrl_SetBufferedDraw, 3004). +-define(wxStyledTextCtrl_SetTabWidth, 3005). +-define(wxStyledTextCtrl_GetTabWidth, 3006). +-define(wxStyledTextCtrl_SetCodePage, 3007). +-define(wxStyledTextCtrl_MarkerDefine, 3008). +-define(wxStyledTextCtrl_MarkerSetForeground, 3009). +-define(wxStyledTextCtrl_MarkerSetBackground, 3010). +-define(wxStyledTextCtrl_MarkerAdd, 3011). +-define(wxStyledTextCtrl_MarkerDelete, 3012). +-define(wxStyledTextCtrl_MarkerDeleteAll, 3013). +-define(wxStyledTextCtrl_MarkerGet, 3014). +-define(wxStyledTextCtrl_MarkerNext, 3015). +-define(wxStyledTextCtrl_MarkerPrevious, 3016). +-define(wxStyledTextCtrl_MarkerDefineBitmap, 3017). +-define(wxStyledTextCtrl_MarkerAddSet, 3018). +-define(wxStyledTextCtrl_MarkerSetAlpha, 3019). +-define(wxStyledTextCtrl_SetMarginType, 3020). +-define(wxStyledTextCtrl_GetMarginType, 3021). +-define(wxStyledTextCtrl_SetMarginWidth, 3022). +-define(wxStyledTextCtrl_GetMarginWidth, 3023). +-define(wxStyledTextCtrl_SetMarginMask, 3024). +-define(wxStyledTextCtrl_GetMarginMask, 3025). +-define(wxStyledTextCtrl_SetMarginSensitive, 3026). +-define(wxStyledTextCtrl_GetMarginSensitive, 3027). +-define(wxStyledTextCtrl_StyleClearAll, 3028). +-define(wxStyledTextCtrl_StyleSetForeground, 3029). +-define(wxStyledTextCtrl_StyleSetBackground, 3030). +-define(wxStyledTextCtrl_StyleSetBold, 3031). +-define(wxStyledTextCtrl_StyleSetItalic, 3032). +-define(wxStyledTextCtrl_StyleSetSize, 3033). +-define(wxStyledTextCtrl_StyleSetFaceName, 3034). +-define(wxStyledTextCtrl_StyleSetEOLFilled, 3035). +-define(wxStyledTextCtrl_StyleResetDefault, 3036). +-define(wxStyledTextCtrl_StyleSetUnderline, 3037). +-define(wxStyledTextCtrl_StyleSetCase, 3038). +-define(wxStyledTextCtrl_StyleSetHotSpot, 3039). +-define(wxStyledTextCtrl_SetSelForeground, 3040). +-define(wxStyledTextCtrl_SetSelBackground, 3041). +-define(wxStyledTextCtrl_GetSelAlpha, 3042). +-define(wxStyledTextCtrl_SetSelAlpha, 3043). +-define(wxStyledTextCtrl_SetCaretForeground, 3044). +-define(wxStyledTextCtrl_CmdKeyAssign, 3045). +-define(wxStyledTextCtrl_CmdKeyClear, 3046). +-define(wxStyledTextCtrl_CmdKeyClearAll, 3047). +-define(wxStyledTextCtrl_SetStyleBytes, 3048). +-define(wxStyledTextCtrl_StyleSetVisible, 3049). +-define(wxStyledTextCtrl_GetCaretPeriod, 3050). +-define(wxStyledTextCtrl_SetCaretPeriod, 3051). +-define(wxStyledTextCtrl_SetWordChars, 3052). +-define(wxStyledTextCtrl_BeginUndoAction, 3053). +-define(wxStyledTextCtrl_EndUndoAction, 3054). +-define(wxStyledTextCtrl_IndicatorSetStyle, 3055). +-define(wxStyledTextCtrl_IndicatorGetStyle, 3056). +-define(wxStyledTextCtrl_IndicatorSetForeground, 3057). +-define(wxStyledTextCtrl_IndicatorGetForeground, 3058). +-define(wxStyledTextCtrl_SetWhitespaceForeground, 3059). +-define(wxStyledTextCtrl_SetWhitespaceBackground, 3060). +-define(wxStyledTextCtrl_GetStyleBits, 3061). +-define(wxStyledTextCtrl_SetLineState, 3062). +-define(wxStyledTextCtrl_GetLineState, 3063). +-define(wxStyledTextCtrl_GetMaxLineState, 3064). +-define(wxStyledTextCtrl_GetCaretLineVisible, 3065). +-define(wxStyledTextCtrl_SetCaretLineVisible, 3066). +-define(wxStyledTextCtrl_GetCaretLineBackground, 3067). +-define(wxStyledTextCtrl_SetCaretLineBackground, 3068). +-define(wxStyledTextCtrl_AutoCompShow, 3069). +-define(wxStyledTextCtrl_AutoCompCancel, 3070). +-define(wxStyledTextCtrl_AutoCompActive, 3071). +-define(wxStyledTextCtrl_AutoCompPosStart, 3072). +-define(wxStyledTextCtrl_AutoCompComplete, 3073). +-define(wxStyledTextCtrl_AutoCompStops, 3074). +-define(wxStyledTextCtrl_AutoCompSetSeparator, 3075). +-define(wxStyledTextCtrl_AutoCompGetSeparator, 3076). +-define(wxStyledTextCtrl_AutoCompSelect, 3077). +-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3078). +-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3079). +-define(wxStyledTextCtrl_AutoCompSetFillUps, 3080). +-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3081). +-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3082). +-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3083). +-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3084). +-define(wxStyledTextCtrl_UserListShow, 3085). +-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3086). +-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3087). +-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3088). +-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3089). +-define(wxStyledTextCtrl_RegisterImage, 3090). +-define(wxStyledTextCtrl_ClearRegisteredImages, 3091). +-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3092). +-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3093). +-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3094). +-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3095). +-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3096). +-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3097). +-define(wxStyledTextCtrl_SetIndent, 3098). +-define(wxStyledTextCtrl_GetIndent, 3099). +-define(wxStyledTextCtrl_SetUseTabs, 3100). +-define(wxStyledTextCtrl_GetUseTabs, 3101). +-define(wxStyledTextCtrl_SetLineIndentation, 3102). +-define(wxStyledTextCtrl_GetLineIndentation, 3103). +-define(wxStyledTextCtrl_GetLineIndentPosition, 3104). +-define(wxStyledTextCtrl_GetColumn, 3105). +-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3106). +-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3107). +-define(wxStyledTextCtrl_SetIndentationGuides, 3108). +-define(wxStyledTextCtrl_GetIndentationGuides, 3109). +-define(wxStyledTextCtrl_SetHighlightGuide, 3110). +-define(wxStyledTextCtrl_GetHighlightGuide, 3111). +-define(wxStyledTextCtrl_GetLineEndPosition, 3112). +-define(wxStyledTextCtrl_GetCodePage, 3113). +-define(wxStyledTextCtrl_GetCaretForeground, 3114). +-define(wxStyledTextCtrl_GetReadOnly, 3115). +-define(wxStyledTextCtrl_SetCurrentPos, 3116). +-define(wxStyledTextCtrl_SetSelectionStart, 3117). +-define(wxStyledTextCtrl_GetSelectionStart, 3118). +-define(wxStyledTextCtrl_SetSelectionEnd, 3119). +-define(wxStyledTextCtrl_GetSelectionEnd, 3120). +-define(wxStyledTextCtrl_SetPrintMagnification, 3121). +-define(wxStyledTextCtrl_GetPrintMagnification, 3122). +-define(wxStyledTextCtrl_SetPrintColourMode, 3123). +-define(wxStyledTextCtrl_GetPrintColourMode, 3124). +-define(wxStyledTextCtrl_FindText, 3125). +-define(wxStyledTextCtrl_FormatRange, 3126). +-define(wxStyledTextCtrl_GetFirstVisibleLine, 3127). +-define(wxStyledTextCtrl_GetLine, 3128). +-define(wxStyledTextCtrl_GetLineCount, 3129). +-define(wxStyledTextCtrl_SetMarginLeft, 3130). +-define(wxStyledTextCtrl_GetMarginLeft, 3131). +-define(wxStyledTextCtrl_SetMarginRight, 3132). +-define(wxStyledTextCtrl_GetMarginRight, 3133). +-define(wxStyledTextCtrl_GetModify, 3134). +-define(wxStyledTextCtrl_SetSelection, 3135). +-define(wxStyledTextCtrl_GetSelectedText, 3136). +-define(wxStyledTextCtrl_GetTextRange, 3137). +-define(wxStyledTextCtrl_HideSelection, 3138). +-define(wxStyledTextCtrl_LineFromPosition, 3139). +-define(wxStyledTextCtrl_PositionFromLine, 3140). +-define(wxStyledTextCtrl_LineScroll, 3141). +-define(wxStyledTextCtrl_EnsureCaretVisible, 3142). +-define(wxStyledTextCtrl_ReplaceSelection, 3143). +-define(wxStyledTextCtrl_SetReadOnly, 3144). +-define(wxStyledTextCtrl_CanPaste, 3145). +-define(wxStyledTextCtrl_CanUndo, 3146). +-define(wxStyledTextCtrl_EmptyUndoBuffer, 3147). +-define(wxStyledTextCtrl_Undo, 3148). +-define(wxStyledTextCtrl_Cut, 3149). +-define(wxStyledTextCtrl_Copy, 3150). +-define(wxStyledTextCtrl_Paste, 3151). +-define(wxStyledTextCtrl_Clear, 3152). +-define(wxStyledTextCtrl_SetText, 3153). +-define(wxStyledTextCtrl_GetText, 3154). +-define(wxStyledTextCtrl_GetTextLength, 3155). +-define(wxStyledTextCtrl_GetOvertype, 3156). +-define(wxStyledTextCtrl_SetCaretWidth, 3157). +-define(wxStyledTextCtrl_GetCaretWidth, 3158). +-define(wxStyledTextCtrl_SetTargetStart, 3159). +-define(wxStyledTextCtrl_GetTargetStart, 3160). +-define(wxStyledTextCtrl_SetTargetEnd, 3161). +-define(wxStyledTextCtrl_GetTargetEnd, 3162). +-define(wxStyledTextCtrl_ReplaceTarget, 3163). +-define(wxStyledTextCtrl_SearchInTarget, 3164). +-define(wxStyledTextCtrl_SetSearchFlags, 3165). +-define(wxStyledTextCtrl_GetSearchFlags, 3166). +-define(wxStyledTextCtrl_CallTipShow, 3167). +-define(wxStyledTextCtrl_CallTipCancel, 3168). +-define(wxStyledTextCtrl_CallTipActive, 3169). +-define(wxStyledTextCtrl_CallTipPosAtStart, 3170). +-define(wxStyledTextCtrl_CallTipSetHighlight, 3171). +-define(wxStyledTextCtrl_CallTipSetBackground, 3172). +-define(wxStyledTextCtrl_CallTipSetForeground, 3173). +-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3174). +-define(wxStyledTextCtrl_CallTipUseStyle, 3175). +-define(wxStyledTextCtrl_VisibleFromDocLine, 3176). +-define(wxStyledTextCtrl_DocLineFromVisible, 3177). +-define(wxStyledTextCtrl_WrapCount, 3178). +-define(wxStyledTextCtrl_SetFoldLevel, 3179). +-define(wxStyledTextCtrl_GetFoldLevel, 3180). +-define(wxStyledTextCtrl_GetLastChild, 3181). +-define(wxStyledTextCtrl_GetFoldParent, 3182). +-define(wxStyledTextCtrl_ShowLines, 3183). +-define(wxStyledTextCtrl_HideLines, 3184). +-define(wxStyledTextCtrl_GetLineVisible, 3185). +-define(wxStyledTextCtrl_SetFoldExpanded, 3186). +-define(wxStyledTextCtrl_GetFoldExpanded, 3187). +-define(wxStyledTextCtrl_ToggleFold, 3188). +-define(wxStyledTextCtrl_EnsureVisible, 3189). +-define(wxStyledTextCtrl_SetFoldFlags, 3190). +-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3191). +-define(wxStyledTextCtrl_SetTabIndents, 3192). +-define(wxStyledTextCtrl_GetTabIndents, 3193). +-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3194). +-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3195). +-define(wxStyledTextCtrl_SetMouseDwellTime, 3196). +-define(wxStyledTextCtrl_GetMouseDwellTime, 3197). +-define(wxStyledTextCtrl_WordStartPosition, 3198). +-define(wxStyledTextCtrl_WordEndPosition, 3199). +-define(wxStyledTextCtrl_SetWrapMode, 3200). +-define(wxStyledTextCtrl_GetWrapMode, 3201). +-define(wxStyledTextCtrl_SetWrapVisualFlags, 3202). +-define(wxStyledTextCtrl_GetWrapVisualFlags, 3203). +-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3204). +-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3205). +-define(wxStyledTextCtrl_SetWrapStartIndent, 3206). +-define(wxStyledTextCtrl_GetWrapStartIndent, 3207). +-define(wxStyledTextCtrl_SetLayoutCache, 3208). +-define(wxStyledTextCtrl_GetLayoutCache, 3209). +-define(wxStyledTextCtrl_SetScrollWidth, 3210). +-define(wxStyledTextCtrl_GetScrollWidth, 3211). +-define(wxStyledTextCtrl_TextWidth, 3212). +-define(wxStyledTextCtrl_GetEndAtLastLine, 3213). +-define(wxStyledTextCtrl_TextHeight, 3214). +-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3215). +-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3216). +-define(wxStyledTextCtrl_AppendText, 3217). +-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3218). +-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3219). +-define(wxStyledTextCtrl_TargetFromSelection, 3220). +-define(wxStyledTextCtrl_LinesJoin, 3221). +-define(wxStyledTextCtrl_LinesSplit, 3222). +-define(wxStyledTextCtrl_SetFoldMarginColour, 3223). +-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3224). +-define(wxStyledTextCtrl_LineDown, 3225). +-define(wxStyledTextCtrl_LineDownExtend, 3226). +-define(wxStyledTextCtrl_LineUp, 3227). +-define(wxStyledTextCtrl_LineUpExtend, 3228). +-define(wxStyledTextCtrl_CharLeft, 3229). +-define(wxStyledTextCtrl_CharLeftExtend, 3230). +-define(wxStyledTextCtrl_CharRight, 3231). +-define(wxStyledTextCtrl_CharRightExtend, 3232). +-define(wxStyledTextCtrl_WordLeft, 3233). +-define(wxStyledTextCtrl_WordLeftExtend, 3234). +-define(wxStyledTextCtrl_WordRight, 3235). +-define(wxStyledTextCtrl_WordRightExtend, 3236). +-define(wxStyledTextCtrl_Home, 3237). +-define(wxStyledTextCtrl_HomeExtend, 3238). +-define(wxStyledTextCtrl_LineEnd, 3239). +-define(wxStyledTextCtrl_LineEndExtend, 3240). +-define(wxStyledTextCtrl_DocumentStart, 3241). +-define(wxStyledTextCtrl_DocumentStartExtend, 3242). +-define(wxStyledTextCtrl_DocumentEnd, 3243). +-define(wxStyledTextCtrl_DocumentEndExtend, 3244). +-define(wxStyledTextCtrl_PageUp, 3245). +-define(wxStyledTextCtrl_PageUpExtend, 3246). +-define(wxStyledTextCtrl_PageDown, 3247). +-define(wxStyledTextCtrl_PageDownExtend, 3248). +-define(wxStyledTextCtrl_EditToggleOvertype, 3249). +-define(wxStyledTextCtrl_Cancel, 3250). +-define(wxStyledTextCtrl_DeleteBack, 3251). +-define(wxStyledTextCtrl_Tab, 3252). +-define(wxStyledTextCtrl_BackTab, 3253). +-define(wxStyledTextCtrl_NewLine, 3254). +-define(wxStyledTextCtrl_FormFeed, 3255). +-define(wxStyledTextCtrl_VCHome, 3256). +-define(wxStyledTextCtrl_VCHomeExtend, 3257). +-define(wxStyledTextCtrl_ZoomIn, 3258). +-define(wxStyledTextCtrl_ZoomOut, 3259). +-define(wxStyledTextCtrl_DelWordLeft, 3260). +-define(wxStyledTextCtrl_DelWordRight, 3261). +-define(wxStyledTextCtrl_LineCut, 3262). +-define(wxStyledTextCtrl_LineDelete, 3263). +-define(wxStyledTextCtrl_LineTranspose, 3264). +-define(wxStyledTextCtrl_LineDuplicate, 3265). +-define(wxStyledTextCtrl_LowerCase, 3266). +-define(wxStyledTextCtrl_UpperCase, 3267). +-define(wxStyledTextCtrl_LineScrollDown, 3268). +-define(wxStyledTextCtrl_LineScrollUp, 3269). +-define(wxStyledTextCtrl_DeleteBackNotLine, 3270). +-define(wxStyledTextCtrl_HomeDisplay, 3271). +-define(wxStyledTextCtrl_HomeDisplayExtend, 3272). +-define(wxStyledTextCtrl_LineEndDisplay, 3273). +-define(wxStyledTextCtrl_LineEndDisplayExtend, 3274). +-define(wxStyledTextCtrl_HomeWrapExtend, 3275). +-define(wxStyledTextCtrl_LineEndWrap, 3276). +-define(wxStyledTextCtrl_LineEndWrapExtend, 3277). +-define(wxStyledTextCtrl_VCHomeWrap, 3278). +-define(wxStyledTextCtrl_VCHomeWrapExtend, 3279). +-define(wxStyledTextCtrl_LineCopy, 3280). +-define(wxStyledTextCtrl_MoveCaretInsideView, 3281). +-define(wxStyledTextCtrl_LineLength, 3282). +-define(wxStyledTextCtrl_BraceHighlight, 3283). +-define(wxStyledTextCtrl_BraceBadLight, 3284). +-define(wxStyledTextCtrl_BraceMatch, 3285). +-define(wxStyledTextCtrl_GetViewEOL, 3286). +-define(wxStyledTextCtrl_SetViewEOL, 3287). +-define(wxStyledTextCtrl_SetModEventMask, 3288). +-define(wxStyledTextCtrl_GetEdgeColumn, 3289). +-define(wxStyledTextCtrl_SetEdgeColumn, 3290). +-define(wxStyledTextCtrl_SetEdgeMode, 3291). +-define(wxStyledTextCtrl_GetEdgeMode, 3292). +-define(wxStyledTextCtrl_GetEdgeColour, 3293). +-define(wxStyledTextCtrl_SetEdgeColour, 3294). +-define(wxStyledTextCtrl_SearchAnchor, 3295). +-define(wxStyledTextCtrl_SearchNext, 3296). +-define(wxStyledTextCtrl_SearchPrev, 3297). +-define(wxStyledTextCtrl_LinesOnScreen, 3298). +-define(wxStyledTextCtrl_UsePopUp, 3299). +-define(wxStyledTextCtrl_SelectionIsRectangle, 3300). +-define(wxStyledTextCtrl_SetZoom, 3301). +-define(wxStyledTextCtrl_GetZoom, 3302). +-define(wxStyledTextCtrl_GetModEventMask, 3303). +-define(wxStyledTextCtrl_SetSTCFocus, 3304). +-define(wxStyledTextCtrl_GetSTCFocus, 3305). +-define(wxStyledTextCtrl_SetStatus, 3306). +-define(wxStyledTextCtrl_GetStatus, 3307). +-define(wxStyledTextCtrl_SetMouseDownCaptures, 3308). +-define(wxStyledTextCtrl_GetMouseDownCaptures, 3309). +-define(wxStyledTextCtrl_SetSTCCursor, 3310). +-define(wxStyledTextCtrl_GetSTCCursor, 3311). +-define(wxStyledTextCtrl_SetControlCharSymbol, 3312). +-define(wxStyledTextCtrl_GetControlCharSymbol, 3313). +-define(wxStyledTextCtrl_WordPartLeft, 3314). +-define(wxStyledTextCtrl_WordPartLeftExtend, 3315). +-define(wxStyledTextCtrl_WordPartRight, 3316). +-define(wxStyledTextCtrl_WordPartRightExtend, 3317). +-define(wxStyledTextCtrl_SetVisiblePolicy, 3318). +-define(wxStyledTextCtrl_DelLineLeft, 3319). +-define(wxStyledTextCtrl_DelLineRight, 3320). +-define(wxStyledTextCtrl_GetXOffset, 3321). +-define(wxStyledTextCtrl_ChooseCaretX, 3322). +-define(wxStyledTextCtrl_SetXCaretPolicy, 3323). +-define(wxStyledTextCtrl_SetYCaretPolicy, 3324). +-define(wxStyledTextCtrl_GetPrintWrapMode, 3325). +-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3326). +-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3327). +-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3328). +-define(wxStyledTextCtrl_SetHotspotSingleLine, 3329). +-define(wxStyledTextCtrl_ParaDownExtend, 3330). +-define(wxStyledTextCtrl_ParaUp, 3331). +-define(wxStyledTextCtrl_ParaUpExtend, 3332). +-define(wxStyledTextCtrl_PositionBefore, 3333). +-define(wxStyledTextCtrl_PositionAfter, 3334). +-define(wxStyledTextCtrl_CopyRange, 3335). +-define(wxStyledTextCtrl_CopyText, 3336). +-define(wxStyledTextCtrl_SetSelectionMode, 3337). +-define(wxStyledTextCtrl_GetSelectionMode, 3338). +-define(wxStyledTextCtrl_LineDownRectExtend, 3339). +-define(wxStyledTextCtrl_LineUpRectExtend, 3340). +-define(wxStyledTextCtrl_CharLeftRectExtend, 3341). +-define(wxStyledTextCtrl_CharRightRectExtend, 3342). +-define(wxStyledTextCtrl_HomeRectExtend, 3343). +-define(wxStyledTextCtrl_VCHomeRectExtend, 3344). +-define(wxStyledTextCtrl_LineEndRectExtend, 3345). +-define(wxStyledTextCtrl_PageUpRectExtend, 3346). +-define(wxStyledTextCtrl_PageDownRectExtend, 3347). +-define(wxStyledTextCtrl_StutteredPageUp, 3348). +-define(wxStyledTextCtrl_StutteredPageUpExtend, 3349). +-define(wxStyledTextCtrl_StutteredPageDown, 3350). +-define(wxStyledTextCtrl_StutteredPageDownExtend, 3351). +-define(wxStyledTextCtrl_WordLeftEnd, 3352). +-define(wxStyledTextCtrl_WordLeftEndExtend, 3353). +-define(wxStyledTextCtrl_WordRightEnd, 3354). +-define(wxStyledTextCtrl_WordRightEndExtend, 3355). +-define(wxStyledTextCtrl_SetWhitespaceChars, 3356). +-define(wxStyledTextCtrl_SetCharsDefault, 3357). +-define(wxStyledTextCtrl_AutoCompGetCurrent, 3358). +-define(wxStyledTextCtrl_Allocate, 3359). +-define(wxStyledTextCtrl_FindColumn, 3360). +-define(wxStyledTextCtrl_GetCaretSticky, 3361). +-define(wxStyledTextCtrl_SetCaretSticky, 3362). +-define(wxStyledTextCtrl_ToggleCaretSticky, 3363). +-define(wxStyledTextCtrl_SetPasteConvertEndings, 3364). +-define(wxStyledTextCtrl_GetPasteConvertEndings, 3365). +-define(wxStyledTextCtrl_SelectionDuplicate, 3366). +-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3367). +-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3368). +-define(wxStyledTextCtrl_StartRecord, 3369). +-define(wxStyledTextCtrl_StopRecord, 3370). +-define(wxStyledTextCtrl_SetLexer, 3371). +-define(wxStyledTextCtrl_GetLexer, 3372). +-define(wxStyledTextCtrl_Colourise, 3373). +-define(wxStyledTextCtrl_SetProperty, 3374). +-define(wxStyledTextCtrl_SetKeyWords, 3375). +-define(wxStyledTextCtrl_SetLexerLanguage, 3376). +-define(wxStyledTextCtrl_GetProperty, 3377). +-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3378). +-define(wxStyledTextCtrl_GetCurrentLine, 3379). +-define(wxStyledTextCtrl_StyleSetSpec, 3380). +-define(wxStyledTextCtrl_StyleSetFont, 3381). +-define(wxStyledTextCtrl_StyleSetFontAttr, 3382). +-define(wxStyledTextCtrl_StyleSetCharacterSet, 3383). +-define(wxStyledTextCtrl_StyleSetFontEncoding, 3384). +-define(wxStyledTextCtrl_CmdKeyExecute, 3385). +-define(wxStyledTextCtrl_SetMargins, 3386). +-define(wxStyledTextCtrl_GetSelection, 3387). +-define(wxStyledTextCtrl_PointFromPosition, 3388). +-define(wxStyledTextCtrl_ScrollToLine, 3389). +-define(wxStyledTextCtrl_ScrollToColumn, 3390). +-define(wxStyledTextCtrl_SetVScrollBar, 3391). +-define(wxStyledTextCtrl_SetHScrollBar, 3392). +-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3393). +-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3394). +-define(wxStyledTextCtrl_SaveFile, 3395). +-define(wxStyledTextCtrl_LoadFile, 3396). +-define(wxStyledTextCtrl_DoDragOver, 3397). +-define(wxStyledTextCtrl_DoDropText, 3398). +-define(wxStyledTextCtrl_GetUseAntiAliasing, 3399). +-define(wxStyledTextCtrl_AddTextRaw, 3400). +-define(wxStyledTextCtrl_InsertTextRaw, 3401). +-define(wxStyledTextCtrl_GetCurLineRaw, 3402). +-define(wxStyledTextCtrl_GetLineRaw, 3403). +-define(wxStyledTextCtrl_GetSelectedTextRaw, 3404). +-define(wxStyledTextCtrl_GetTextRangeRaw, 3405). +-define(wxStyledTextCtrl_SetTextRaw, 3406). +-define(wxStyledTextCtrl_GetTextRaw, 3407). +-define(wxStyledTextCtrl_AppendTextRaw, 3408). +-define(wxArtProvider_GetBitmap, 3409). +-define(wxArtProvider_GetIcon, 3410). +-define(wxTreeEvent_GetKeyCode, 3411). +-define(wxTreeEvent_GetItem, 3412). +-define(wxTreeEvent_GetKeyEvent, 3413). +-define(wxTreeEvent_GetLabel, 3414). +-define(wxTreeEvent_GetOldItem, 3415). +-define(wxTreeEvent_GetPoint, 3416). +-define(wxTreeEvent_IsEditCancelled, 3417). +-define(wxTreeEvent_SetToolTip, 3418). +-define(wxNotebookEvent_GetOldSelection, 3419). +-define(wxNotebookEvent_GetSelection, 3420). +-define(wxNotebookEvent_SetOldSelection, 3421). +-define(wxNotebookEvent_SetSelection, 3422). +-define(wxFileDataObject_new, 3423). +-define(wxFileDataObject_AddFile, 3424). +-define(wxFileDataObject_GetFilenames, 3425). +-define(wxFileDataObject_destroy, 3426). +-define(wxTextDataObject_new, 3427). +-define(wxTextDataObject_GetTextLength, 3428). +-define(wxTextDataObject_GetText, 3429). +-define(wxTextDataObject_SetText, 3430). +-define(wxTextDataObject_destroy, 3431). +-define(wxBitmapDataObject_new_1_1, 3432). +-define(wxBitmapDataObject_new_1_0, 3433). +-define(wxBitmapDataObject_GetBitmap, 3434). +-define(wxBitmapDataObject_SetBitmap, 3435). +-define(wxBitmapDataObject_destroy, 3436). +-define(wxClipboard_new, 3438). +-define(wxClipboard_destruct, 3439). +-define(wxClipboard_AddData, 3440). +-define(wxClipboard_Clear, 3441). +-define(wxClipboard_Close, 3442). +-define(wxClipboard_Flush, 3443). +-define(wxClipboard_GetData, 3444). +-define(wxClipboard_IsOpened, 3445). +-define(wxClipboard_Open, 3446). +-define(wxClipboard_SetData, 3447). +-define(wxClipboard_UsePrimarySelection, 3449). +-define(wxClipboard_IsSupported, 3450). +-define(wxClipboard_Get, 3451). +-define(wxSpinEvent_GetPosition, 3452). +-define(wxSpinEvent_SetPosition, 3453). +-define(wxSplitterWindow_new_0, 3454). +-define(wxSplitterWindow_new_2, 3455). +-define(wxSplitterWindow_destruct, 3456). +-define(wxSplitterWindow_Create, 3457). +-define(wxSplitterWindow_GetMinimumPaneSize, 3458). +-define(wxSplitterWindow_GetSashGravity, 3459). +-define(wxSplitterWindow_GetSashPosition, 3460). +-define(wxSplitterWindow_GetSplitMode, 3461). +-define(wxSplitterWindow_GetWindow1, 3462). +-define(wxSplitterWindow_GetWindow2, 3463). +-define(wxSplitterWindow_Initialize, 3464). +-define(wxSplitterWindow_IsSplit, 3465). +-define(wxSplitterWindow_ReplaceWindow, 3466). +-define(wxSplitterWindow_SetSashGravity, 3467). +-define(wxSplitterWindow_SetSashPosition, 3468). +-define(wxSplitterWindow_SetSashSize, 3469). +-define(wxSplitterWindow_SetMinimumPaneSize, 3470). +-define(wxSplitterWindow_SetSplitMode, 3471). +-define(wxSplitterWindow_SplitHorizontally, 3472). +-define(wxSplitterWindow_SplitVertically, 3473). +-define(wxSplitterWindow_Unsplit, 3474). +-define(wxSplitterWindow_UpdateSize, 3475). +-define(wxSplitterEvent_GetSashPosition, 3476). +-define(wxSplitterEvent_GetX, 3477). +-define(wxSplitterEvent_GetY, 3478). +-define(wxSplitterEvent_GetWindowBeingRemoved, 3479). +-define(wxSplitterEvent_SetSashPosition, 3480). +-define(wxHtmlWindow_new_0, 3481). +-define(wxHtmlWindow_new_2, 3482). +-define(wxHtmlWindow_AppendToPage, 3483). +-define(wxHtmlWindow_GetOpenedAnchor, 3484). +-define(wxHtmlWindow_GetOpenedPage, 3485). +-define(wxHtmlWindow_GetOpenedPageTitle, 3486). +-define(wxHtmlWindow_GetRelatedFrame, 3487). +-define(wxHtmlWindow_HistoryBack, 3488). +-define(wxHtmlWindow_HistoryCanBack, 3489). +-define(wxHtmlWindow_HistoryCanForward, 3490). +-define(wxHtmlWindow_HistoryClear, 3491). +-define(wxHtmlWindow_HistoryForward, 3492). +-define(wxHtmlWindow_LoadFile, 3493). +-define(wxHtmlWindow_LoadPage, 3494). +-define(wxHtmlWindow_SelectAll, 3495). +-define(wxHtmlWindow_SelectionToText, 3496). +-define(wxHtmlWindow_SelectLine, 3497). +-define(wxHtmlWindow_SelectWord, 3498). +-define(wxHtmlWindow_SetBorders, 3499). +-define(wxHtmlWindow_SetFonts, 3500). +-define(wxHtmlWindow_SetPage, 3501). +-define(wxHtmlWindow_SetRelatedFrame, 3502). +-define(wxHtmlWindow_SetRelatedStatusBar, 3503). +-define(wxHtmlWindow_ToText, 3504). +-define(wxHtmlWindow_destroy, 3505). +-define(wxHtmlLinkEvent_GetLinkInfo, 3506). +-define(wxSystemSettings_GetColour, 3507). +-define(wxSystemSettings_GetFont, 3508). +-define(wxSystemSettings_GetMetric, 3509). +-define(wxSystemSettings_GetScreenType, 3510). +-define(wxSystemOptions_GetOption, 3511). +-define(wxSystemOptions_GetOptionInt, 3512). +-define(wxSystemOptions_HasOption, 3513). +-define(wxSystemOptions_IsFalse, 3514). +-define(wxSystemOptions_SetOption_2_1, 3515). +-define(wxSystemOptions_SetOption_2_0, 3516). +-define(wxAuiNotebookEvent_SetSelection, 3517). +-define(wxAuiNotebookEvent_GetSelection, 3518). +-define(wxAuiNotebookEvent_SetOldSelection, 3519). +-define(wxAuiNotebookEvent_GetOldSelection, 3520). +-define(wxAuiNotebookEvent_SetDragSource, 3521). +-define(wxAuiNotebookEvent_GetDragSource, 3522). +-define(wxAuiManagerEvent_SetManager, 3523). +-define(wxAuiManagerEvent_GetManager, 3524). +-define(wxAuiManagerEvent_SetPane, 3525). +-define(wxAuiManagerEvent_GetPane, 3526). +-define(wxAuiManagerEvent_SetButton, 3527). +-define(wxAuiManagerEvent_GetButton, 3528). +-define(wxAuiManagerEvent_SetDC, 3529). +-define(wxAuiManagerEvent_GetDC, 3530). +-define(wxAuiManagerEvent_Veto, 3531). +-define(wxAuiManagerEvent_GetVeto, 3532). +-define(wxAuiManagerEvent_SetCanVeto, 3533). +-define(wxAuiManagerEvent_CanVeto, 3534). +-define(wxLogNull_new, 3535). +-define(wxLogNull_destroy, 3536). +-define(wxTaskBarIcon_new, 3537). +-define(wxTaskBarIcon_destruct, 3538). +-define(wxTaskBarIcon_PopupMenu, 3539). +-define(wxTaskBarIcon_RemoveIcon, 3540). +-define(wxTaskBarIcon_SetIcon, 3541). +-define(wxLocale_new_0, 3542). +-define(wxLocale_new_2, 3544). +-define(wxLocale_destruct, 3545). +-define(wxLocale_Init, 3547). +-define(wxLocale_AddCatalog_1, 3548). +-define(wxLocale_AddCatalog_3, 3549). +-define(wxLocale_AddCatalogLookupPathPrefix, 3550). +-define(wxLocale_GetCanonicalName, 3551). +-define(wxLocale_GetLanguage, 3552). +-define(wxLocale_GetLanguageName, 3553). +-define(wxLocale_GetLocale, 3554). +-define(wxLocale_GetName, 3555). +-define(wxLocale_GetString_2, 3556). +-define(wxLocale_GetString_4, 3557). +-define(wxLocale_GetHeaderValue, 3558). +-define(wxLocale_GetSysName, 3559). +-define(wxLocale_GetSystemEncoding, 3560). +-define(wxLocale_GetSystemEncodingName, 3561). +-define(wxLocale_GetSystemLanguage, 3562). +-define(wxLocale_IsLoaded, 3563). +-define(wxLocale_IsOk, 3564). +-define(wxActivateEvent_GetActive, 3565). +-define(wxPopupWindow_new_2, 3567). +-define(wxPopupWindow_new_0, 3568). +-define(wxPopupWindow_destruct, 3570). +-define(wxPopupWindow_Create, 3571). +-define(wxPopupWindow_Position, 3572). +-define(wxPopupTransientWindow_new_0, 3573). +-define(wxPopupTransientWindow_new_2, 3574). +-define(wxPopupTransientWindow_destruct, 3575). +-define(wxPopupTransientWindow_Popup, 3576). +-define(wxPopupTransientWindow_Dismiss, 3577). -- cgit v1.2.3 From 657def9c42b096217b9a4483b8c8c3d462f181dc Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 28 Aug 2015 14:51:08 +0200 Subject: ssh: update vsn.mk --- lib/ssh/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index cef9992f1b..b305eedcdc 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.0 +SSH_VSN = 4.1 APP_VSN = "ssh-$(SSH_VSN)" -- cgit v1.2.3 From bba382165f48cace97ac64e580d533d998c0fe80 Mon Sep 17 00:00:00 2001 From: Constantin Rack Date: Fri, 28 Aug 2015 18:30:30 +0200 Subject: Fix typo in call_last/3 spec --- lib/compiler/src/genop.tab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab index ab227e5452..3a877f2403 100755 --- a/lib/compiler/src/genop.tab +++ b/lib/compiler/src/genop.tab @@ -45,7 +45,7 @@ BEAM_FORMAT_NUMBER=0 ## Save the next instruction as the return address in the CP register. 4: call/2 -## @spec call_last Arity Label Dellocate +## @spec call_last Arity Label Deallocate ## @doc Deallocate and do a tail recursive call to the function at Label. ## Do not update the CP register. ## Before the call deallocate Deallocate words of stack. -- cgit v1.2.3 From ba7b10c4fa2787e11bde6ddacc97ab90fe858484 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 5 Aug 2015 22:12:18 +0200 Subject: ssh: Elliptic Curve Diffie-Hellman (ECDH) Adds ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp512 and OTP-12938 hmac-sha2-512 --- lib/ssh/src/ssh_connection_handler.erl | 44 +++++++- lib/ssh/src/ssh_message.erl | 49 ++++++-- lib/ssh/src/ssh_transport.erl | 197 ++++++++++++++++++++++++++------- lib/ssh/src/ssh_transport.hrl | 47 +++++++- lib/ssh/test/ssh_basic_SUITE.erl | 14 ++- lib/ssh/test/ssh_protocol_SUITE.erl | 27 +++-- lib/ssh/test/ssh_to_openssh_SUITE.erl | 21 ++-- lib/ssh/test/ssh_trpt_test_lib.erl | 20 +++- 8 files changed, 338 insertions(+), 81 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 180698d741..fcd66b80c0 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -429,7 +429,21 @@ key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg, #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> {ok, KexGexInit, Ssh} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0), send_msg(KexGexInit, State), - {next_state, key_exchange_dh_gex_reply, next_packet(State#state{ssh_params = Ssh})}. + {next_state, key_exchange_dh_gex_reply, next_packet(State#state{ssh_params = Ssh})}; + +key_exchange(#ssh_msg_kex_ecdh_init{} = Msg, + #state{ssh_params = #ssh{role = server} = Ssh0} = State) -> + {ok, KexEcdhReply, Ssh1} = ssh_transport:handle_kex_ecdh_init(Msg, Ssh0), + send_msg(KexEcdhReply, State), + {ok, NewKeys, Ssh} = ssh_transport:new_keys_message(Ssh1), + send_msg(NewKeys, State), + {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}; + +key_exchange(#ssh_msg_kex_ecdh_reply{} = Msg, + #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> + {ok, NewKeys, Ssh} = ssh_transport:handle_kex_ecdh_reply(Msg, Ssh0), + send_msg(NewKeys, State), + {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}. %%-------------------------------------------------------------------- -spec key_exchange_dh_gex_init(#ssh_msg_kex_dh_gex_init{}, #state{}) -> gen_fsm_state_return(). @@ -1307,7 +1321,7 @@ event(Event, StateName, State) -> handle_disconnect(DisconnectMsg, State); throw:{ErrorToDisplay, #ssh_msg_disconnect{} = DisconnectMsg} -> handle_disconnect(DisconnectMsg, State, ErrorToDisplay); - _:_ -> + _C:_Error -> handle_disconnect(#ssh_msg_disconnect{code = error_code(StateName), description = "Invalid state", language = "en"}, State) @@ -1376,9 +1390,10 @@ generate_event(<> = Msg, StateName, {stop, {shutdown, Error}, State#state{connection_state = Connection}} end; + generate_event(Msg, StateName, State0, EncData) -> try - Event = ssh_message:decode(Msg), + Event = ssh_message:decode(set_prefix_if_trouble(Msg,State0)), State = generate_event_new_state(State0, EncData), case Event of #ssh_msg_kexinit{} -> @@ -1388,7 +1403,7 @@ generate_event(Msg, StateName, State0, EncData) -> event(Event, StateName, State) end catch - _:_ -> + _C:_E -> DisconnectMsg = #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, description = "Encountered unexpected input", @@ -1397,6 +1412,26 @@ generate_event(Msg, StateName, State0, EncData) -> end. +set_prefix_if_trouble(Msg = <>, #state{ssh_params=SshParams}) + when Op == 30; + Op == 31 + -> + case catch atom_to_list(kex(SshParams)) of + "ecdh-sha2-" ++ _ -> + <<"ecdh",Msg/binary>>; + "diffie-hellman-group-exchange-" ++ _ -> + <<"dh_gex",Msg/binary>>; + "diffie-hellman-group" ++ _ -> + <<"dh",Msg/binary>>; + _ -> + Msg + end; +set_prefix_if_trouble(Msg, _) -> + Msg. + +kex(#ssh{algorithms=#alg{kex=Kex}}) -> Kex; +kex(_) -> undefined. + handle_request(ChannelPid, ChannelId, Type, Data, WantReply, From, #state{connection_state = @@ -1491,6 +1526,7 @@ new_channel_id(#state{connection_state = #connection{channel_id_seed = Id} = = State) -> {Id, State#state{connection_state = Connection#connection{channel_id_seed = Id + 1}}}. + generate_event_new_state(#state{ssh_params = #ssh{recv_sequence = SeqNum0} = Ssh} = State, EncData) -> diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index 7b786b8fff..cb1dcb67c5 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -259,6 +259,14 @@ encode(#ssh_msg_kex_dh_gex_reply{ EncSign = encode_sign(Key, Signature), ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); +encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) -> + ssh_bits:encode([?SSH_MSG_KEX_ECDH_INIT, Q_c], [byte, mpint]); + +encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) -> + EncKey = encode_host_key(Key), + EncSign = encode_sign(Key, Sign), + ssh_bits:encode([?SSH_MSG_KEX_ECDH_REPLY, EncKey, Q_s, EncSign], [byte, binary, mpint, binary]); + encode(#ssh_msg_ignore{data = Data}) -> ssh_bits:encode([?SSH_MSG_IGNORE, Data], [byte, string]); @@ -422,30 +430,45 @@ decode(<>) -> decode(<>) -> decode_kex_init(Data, [Cookie, ssh_msg_kexinit], 10); -decode(<>) -> +decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?UINT32(Len), E:Len/big-signed-integer-unit:8>>) -> #ssh_msg_kexdh_init{e = E }; + +decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY), + ?UINT32(Len0), Key:Len0/binary, + ?UINT32(Len1), F:Len1/big-signed-integer-unit:8, + ?UINT32(Len2), Hashsign:Len2/binary>>) -> + #ssh_msg_kexdh_reply{ + public_host_key = decode_host_key(Key), + f = F, + h_sig = decode_sign(Hashsign) + }; + decode(<>) -> #ssh_msg_kex_dh_gex_request{ min = Min, n = N, max = Max }; -decode(<>) -> + +decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_REQUEST_OLD), ?UINT32(N)>>) -> #ssh_msg_kex_dh_gex_request_old{ n = N }; -decode(<>) -> #ssh_msg_kex_dh_gex_group{ p = Prime, g = Generator }; + decode(<>) -> #ssh_msg_kex_dh_gex_init{ e = E }; + decode(<>) -> - #ssh_msg_kexdh_reply{ + +decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), + ?UINT32(Len0), Q_c:Len0/big-signed-integer-unit:8>>) -> + #ssh_msg_kex_ecdh_init{ + q_c = Q_c + }; + +decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY), + ?UINT32(Len1), Key:Len1/binary, + ?UINT32(Len2), Q_s:Len2/big-signed-integer-unit:8, + ?UINT32(Len3), Sig:Len3/binary>>) -> + #ssh_msg_kex_ecdh_reply{ public_host_key = decode_host_key(Key), - f = F, - h_sig = decode_sign(Hashsign) + q_s = Q_s, + h_sig = decode_sign(Sig) }; decode(<>) -> diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 9ed6c85ff7..235d8918f3 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -42,6 +42,8 @@ handle_kex_dh_gex_group/2, handle_kex_dh_gex_init/2, handle_kex_dh_gex_reply/2, handle_new_keys/2, handle_kex_dh_gex_request/2, handle_kexdh_reply/2, + handle_kex_ecdh_init/2, + handle_kex_ecdh_reply/2, unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1, sign/3, verify/4]). @@ -53,7 +55,7 @@ %%% user. %%% %%% A supported algorithm can be requested in the option 'preferred_algorithms', -%%% but may give unexpected results because of being promoted to default. +%%% but may give unexpected results before being promoted to default. %%% %%% This makes it possible to add experimental algorithms (in supported_algorithms) %%% and test them without letting the default users know about them. @@ -66,8 +68,6 @@ algo_classes() -> [kex, public_key, cipher, mac, compression]. default_algorithms(compression) -> %% Do not announce 'zlib@openssh.com' because there seem to be problems supported_algorithms(compression, same(['zlib@openssh.com'])); -default_algorithms(kex) -> - supported_algorithms(kex, []); default_algorithms(Alg) -> supported_algorithms(Alg). @@ -76,10 +76,14 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()]. supported_algorithms(kex) -> select_crypto_supported( - [{'diffie-hellman-group14-sha1', [{hashs,sha}]}, - {'diffie-hellman-group1-sha1', [{hashs,sha}]}, - {'diffie-hellman-group-exchange-sha256', [{hashs,sha256}]}, - {'diffie-hellman-group-exchange-sha1', [{hashs,sha}]} + [ + {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]}, + {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]}, + {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]}, + {'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]}, + {'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]}, + {'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]}, + {'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]} ]); supported_algorithms(public_key) -> ssh_auth:default_public_key_algorithms(); @@ -94,7 +98,8 @@ supported_algorithms(cipher) -> supported_algorithms(mac) -> same( select_crypto_supported( - [{'hmac-sha2-256', [{hashs,sha256}]}, + [{'hmac-sha2-512', [{hashs,sha512}]}, + {'hmac-sha2-256', [{hashs,sha256}]}, {'hmac-sha1', [{hashs,sha}]} ] )); @@ -109,14 +114,19 @@ supported_algorithms(Key, BlackList) -> supported_algorithms(Key) -- BlackList. select_crypto_supported(L) -> - Sup = crypto:supports(), + Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()], [Name || {Name,CryptoRequires} <- L, crypto_supported(CryptoRequires, Sup)]. +crypto_supported_curves() -> + try crypto:ec_curves() + catch _:_ -> [] + end. + crypto_supported(Conditions, Supported) -> - lists:all(fun({Tag,CryptoName}) -> - lists:member(CryptoName, proplists:get_value(Tag,Supported,[])) - end, Conditions). + lists:all( fun({Tag,CryptoName}) -> + lists:member(CryptoName, proplists:get_value(Tag,Supported,[])) + end, Conditions). same(Algs) -> [{client2server,Algs}, {server2client,Algs}]. @@ -294,10 +304,7 @@ verify_algorithm(#alg{decrypt = undefined}) -> false; verify_algorithm(#alg{compress = undefined}) -> false; verify_algorithm(#alg{decompress = undefined}) -> false; -verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) -> true; -verify_algorithm(#alg{kex = 'diffie-hellman-group14-sha1'}) -> true; -verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) -> true; -verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha256'}) -> true; +verify_algorithm(#alg{kex = Kex}) -> lists:member(Kex, supported_algorithms(kex)); verify_algorithm(_) -> false. %%%---------------------------------------------------------------- @@ -307,8 +314,7 @@ verify_algorithm(_) -> false. key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group1-sha1' ; Kex == 'diffie-hellman-group14-sha1' -> {G, P} = dh_group(Kex), - {Private, Public} = dh_gen_key(G, P, 1024), - %% Public = G^Private mod P (def) + {Public, Private} = generate_key(dh, [P,G]), {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0), {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}; @@ -324,7 +330,16 @@ key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group-exchange-sha max = Max}, Ssh0), {ok, SshPacket, - Ssh1#ssh{keyex_info = {Min, Max, NBits}}}. + Ssh1#ssh{keyex_info = {Min, Max, NBits}}}; + +key_exchange_first_msg(Kex, Ssh0) when Kex == 'ecdh-sha2-nistp256' ; + Kex == 'ecdh-sha2-nistp384' ; + Kex == 'ecdh-sha2-nistp521' -> + Curve = ecdh_curve(Kex), + {Public, Private} = generate_key(ecdh, Curve), + {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kex_ecdh_init{q_c=Public}, Ssh0), + {ok, SshPacket, + Ssh1#ssh{keyex_key = {{Public,Private},Curve}}}. %%%---------------------------------------------------------------- %%% @@ -337,8 +352,8 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, {G, P} = dh_group(Kex), if 1= - {Private, Public} = dh_gen_key(G, P, 1024), - K = dh_compute_key(G, P, E, Private), + {Public, Private} = generate_key(dh, [P,G]), + K = compute_key(dh, E, Private, [P,G]), Key = get_host_key(Ssh0), H = kex_h(Ssh0, Key, E, Public, K), H_SIG = sign_host_key(Ssh0, Key, H), @@ -367,7 +382,7 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, %% client if 1= - K = dh_compute_key(G, P, F, Private), + K = compute_key(dh, F, Private, [P,G]), H = kex_h(Ssh0, HostKey, Public, F, K), case verify_host_key(Ssh0, HostKey, H, H_SIG) of @@ -405,7 +420,7 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, Ssh0=#ssh{opts=Opts}) when Min= %% server {G, P} = dh_gex_group(Min, NBits, Max, proplists:get_value(dh_gex_groups,Opts)), - {Private, Public} = dh_gen_key(G, P, 1024), + {Public, Private} = generate_key(dh, [P,G]), {SshPacket, Ssh} = ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), {ok, SshPacket, @@ -422,7 +437,7 @@ handle_kex_dh_gex_request(_, _) -> handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) -> %% client - {Private, Public} = dh_gen_key(G, P, 1024), + {Public, Private} = generate_key(dh, [P,G]), {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0), % Pub = G^Priv mod P (def) @@ -436,7 +451,7 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, %% server if 1= - K = dh_compute_key(G, P, E, Private), + K = compute_key(dh, E, Private, [P,G]), if 1 HostKey = get_host_key(Ssh0), @@ -476,7 +491,7 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, %% client if 1= - K = dh_compute_key(G, P, F, Private), + K = compute_key(dh, F, Private, [P,G]), if 1 H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K), @@ -512,13 +527,84 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, }) end. +%%%---------------------------------------------------------------- +%%% +%%% diffie-hellman-ecdh-sha2-* +%%% +handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, + Ssh0 = #ssh{algorithms = #alg{kex=Kex}}) -> + %% at server + Curve = ecdh_curve(Kex), + case ecdh_validate_public_key(PeerPublic, Curve) of + true -> + {MyPublic, MyPrivate} = generate_key(ecdh, Curve), + K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), + HostKey = get_host_key(Ssh0), + H = kex_h(Ssh0, Curve, HostKey, PeerPublic, MyPublic, K), + H_SIG = sign_host_key(Ssh0, HostKey, H), + {SshPacket, Ssh1} = + ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, + q_s = MyPublic, + h_sig = H_SIG}, + Ssh0), + {ok, SshPacket, Ssh1#ssh{keyex_key = {{MyPublic,MyPrivate},Curve}, + shared_secret = K, + exchanged_hash = H, + session_id = sid(Ssh1, H)}}; + + false -> + throw({{error,invalid_peer_public_key}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Peer ECDH public key is invalid", + language = ""} + }) + end. + +handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, + q_s = PeerPublic, + h_sig = H_SIG}, + #ssh{keyex_key = {{MyPublic,MyPrivate}, Curve}} = Ssh0 + ) -> + %% at client + case ecdh_validate_public_key(PeerPublic, Curve) of + true -> + K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), + H = kex_h(Ssh0, Curve, HostKey, MyPublic, PeerPublic, K), + case verify_host_key(Ssh0, HostKey, H, H_SIG) of + ok -> + {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), + {ok, SshPacket, Ssh#ssh{shared_secret = K, + exchanged_hash = H, + session_id = sid(Ssh, H)}}; + Error -> + throw({Error, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Key exchange failed", + language = ""} + }) + end; + + false -> + throw({{error,invalid_peer_public_key}, + #ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + description = "Peer ECDH public key is invalid", + language = ""} + }) + end. + + +ecdh_validate_public_key(_, _) -> true. % FIXME: Far too many false positives :) + %%%---------------------------------------------------------------- handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> try install_alg(Ssh0) of #ssh{} = Ssh -> {ok, Ssh} catch - error:_Error -> %% TODO: Throw earlier .... + _C:_Error -> %% TODO: Throw earlier .... throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, description = "Install alg failed", language = "en"}) @@ -546,10 +632,10 @@ get_host_key(SSH) -> end. sign_host_key(_Ssh, #'RSAPrivateKey'{} = Private, H) -> - Hash = sha, %% Option ?! + Hash = sha, _Signature = sign(H, Hash, Private); sign_host_key(_Ssh, #'DSAPrivateKey'{} = Private, H) -> - Hash = sha, %% Option ?! + Hash = sha, _RawSignature = sign(H, Hash, Private). verify_host_key(SSH, PublicKey, Digest, Signature) -> @@ -1134,7 +1220,9 @@ mac('hmac-md5', Key, SeqNum, Data) -> mac('hmac-md5-96', Key, SeqNum, Data) -> crypto:hmac(md5, Key, [<>, Data], mac_digest_size('hmac-md5-96')); mac('hmac-sha2-256', Key, SeqNum, Data) -> - crypto:hmac(sha256, Key, [<>, Data]). + crypto:hmac(sha256, Key, [<>, Data]); +mac('hmac-sha2-512', Key, SeqNum, Data) -> + crypto:hmac(sha512, Key, [<>, Data]). %% return N hash bytes (HASH) hash(SSH, Char, Bits) -> @@ -1144,10 +1232,18 @@ hash(SSH, Char, Bits) -> fun(Data) -> crypto:hash(sha, Data) end; 'diffie-hellman-group14-sha1' -> fun(Data) -> crypto:hash(sha, Data) end; + 'diffie-hellman-group-exchange-sha1' -> fun(Data) -> crypto:hash(sha, Data) end; 'diffie-hellman-group-exchange-sha256' -> fun(Data) -> crypto:hash(sha256, Data) end; + + 'ecdh-sha2-nistp256' -> + fun(Data) -> crypto:hash(sha256,Data) end; + 'ecdh-sha2-nistp384' -> + fun(Data) -> crypto:hash(sha384,Data) end; + 'ecdh-sha2-nistp521' -> + fun(Data) -> crypto:hash(sha512,Data) end; _ -> exit({bad_algorithm,SSH#ssh.kex}) end, @@ -1176,8 +1272,16 @@ kex_h(SSH, Key, E, F, K) -> ssh_message:encode_host_key(Key), E,F,K], [string,string,binary,binary,binary, mpint,mpint,mpint]), - crypto:hash(sha,L). - + crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). +%% crypto:hash(sha,L). + +kex_h(SSH, Curve, Key, Q_c, Q_s, K) -> + L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version, + SSH#ssh.c_keyinit, SSH#ssh.s_keyinit, + ssh_message:encode_host_key(Key), Q_c, Q_s, K], + [string,string,binary,binary,binary, + mpint,mpint,mpint]), + crypto:hash(sha(Curve), L). kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> L = if Min==-1; Max==-1 -> @@ -1199,6 +1303,14 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> end, crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). +sha('nistp256') -> sha256; +sha('secp256r1')-> sha256; +sha('nistp384') -> sha384; +sha('secp384r1')-> sha384; +sha('nistp521') -> sha512; +sha('secp521r1')-> sha512; +sha('diffie-hellman-group1-sha1') -> sha; +sha('diffie-hellman-group14-sha1') -> sha; sha('diffie-hellman-group-exchange-sha1') -> sha; sha('diffie-hellman-group-exchange-sha256') -> sha256. @@ -1207,6 +1319,7 @@ mac_key_size('hmac-sha1-96') -> 20*8; mac_key_size('hmac-md5') -> 16*8; mac_key_size('hmac-md5-96') -> 16*8; mac_key_size('hmac-sha2-256')-> 32*8; +mac_key_size('hmac-sha2-512')-> 512; mac_key_size(none) -> 0. mac_digest_size('hmac-sha1') -> 20; @@ -1214,6 +1327,7 @@ mac_digest_size('hmac-sha1-96') -> 12; mac_digest_size('hmac-md5') -> 20; mac_digest_size('hmac-md5-96') -> 12; mac_digest_size('hmac-sha2-256') -> 32; +mac_digest_size('hmac-sha2-512') -> 64; mac_digest_size(none) -> 0. peer_name({Host, _}) -> @@ -1267,14 +1381,19 @@ dh_gex_group(Min, N, Max, Groups) -> end. -dh_gen_key(G, P, _) -> - {Public, Private} = crypto:generate_key(dh, [P, G]), - {crypto:bytes_to_integer(Private), crypto:bytes_to_integer(Public)}. +generate_key(Algorithm, Args) -> + {Public,Private} = crypto:generate_key(Algorithm, Args), + {crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}. + + +compute_key(Algorithm, OthersPublic, MyPrivate, Args) -> + Shared = crypto:compute_key(Algorithm, OthersPublic, MyPrivate, Args), + crypto:bytes_to_integer(Shared). + -dh_compute_key(G, P, OthersPublic, MyPrivate) -> - crypto:bytes_to_integer( - crypto:compute_key(dh, OthersPublic, MyPrivate, [P,G]) - ). +ecdh_curve('ecdh-sha2-nistp256') -> secp256r1; +ecdh_curve('ecdh-sha2-nistp384') -> secp384r1; +ecdh_curve('ecdh-sha2-nistp521') -> secp521r1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 9e1de171c2..e6449e93c5 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -29,9 +29,6 @@ -define(DEFAULT_CLIENT_VERSION, {2, 0}). -define(DEFAULT_SERVER_VERSION, {2, 0}). --define(DEFAULT_DH_GROUP_MIN, 512). --define(DEFAULT_DH_GROUP_NBITS, 1024). --define(DEFAULT_DH_GROUP_MAX, 4096). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% @@ -109,8 +106,8 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% diffie-hellman-group1-sha1 --define(SSH_MSG_KEXDH_INIT, 30). +%% diffie-hellman-group1-sha1 | diffie-hellman-group14-sha1 +-define(SSH_MSG_KEXDH_INIT, 30). -define(SSH_MSG_KEXDH_REPLY, 31). -record(ssh_msg_kexdh_init, @@ -134,7 +131,11 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% diffie-hellman-group-exchange-sha1 +%% diffie-hellman-group-exchange-sha1 | diffie-hellman-group-exchange-sha256 +-define(DEFAULT_DH_GROUP_MIN, 512). +-define(DEFAULT_DH_GROUP_NBITS, 1024). +-define(DEFAULT_DH_GROUP_MAX, 4096). + -define(SSH_MSG_KEX_DH_GEX_REQUEST_OLD, 30). -define(SSH_MSG_KEX_DH_GEX_REQUEST, 34). -define(SSH_MSG_KEX_DH_GEX_GROUP, 31). @@ -171,7 +172,36 @@ h_sig }). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% KEY ECDH messages +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% ecdh-sha2-nistp256 | ecdh-sha2-nistp384 | ecdh-sha2-nistp521 + +-define(SSH_MSG_KEX_ECDH_INIT, 30). +-define(SSH_MSG_KEX_ECDH_REPLY, 31). + +-record(ssh_msg_kex_ecdh_init, + { + q_c % string (client's ephemeral public key octet string) + }). + +-record(ssh_msg_kex_ecdh_reply, + { + public_host_key, % string (server's public host key) (k_s) + q_s, % string (server's ephemeral public key octet string) + h_sig % string (the signature on the exchange hash) + }). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% error codes +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + -define(SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, 1). -define(SSH_DISCONNECT_PROTOCOL_ERROR, 2). -define(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 3). @@ -188,7 +218,12 @@ -define(SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, 14). -define(SSH_DISCONNECT_ILLEGAL_USER_NAME, 15). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% groups +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% rfc 2489, ch 6.2 -define(dh_group1, diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 6dfff945ac..27b611780d 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -96,7 +96,10 @@ groups() -> {key_exchange, [], ['diffie-hellman-group-exchange-sha1', 'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group1-sha1', - 'diffie-hellman-group14-sha1' + 'diffie-hellman-group14-sha1', + 'ecdh-sha2-nistp256', + 'ecdh-sha2-nistp384', + 'ecdh-sha2-nistp521' ]}, {dir_options, [], [user_dir_option, system_dir_option]} @@ -845,6 +848,15 @@ ssh_msg_debug_fun_option_client(Config) -> 'diffie-hellman-group14-sha1'(Config) -> kextest('diffie-hellman-group14-sha1',Config). +'ecdh-sha2-nistp256'(Config) -> + kextest('ecdh-sha2-nistp256',Config). + +'ecdh-sha2-nistp384'(Config) -> + kextest('ecdh-sha2-nistp384',Config). + +'ecdh-sha2-nistp521'(Config) -> + kextest('ecdh-sha2-nistp521',Config). + kextest(Kex, Config) -> case lists:member(Kex, ssh_transport:supported_algorithms(kex)) of diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index dc02b940d7..132be3beb2 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -115,7 +115,8 @@ lib_works_as_client(Config) -> [{set_options, [print_ops, print_seqnums, print_messages]}, {connect, server_host(Config),server_port(Config), - [{silently_accept_hosts, true}, + [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}, + {silently_accept_hosts, true}, {user_dir, user_dir(Config)}, {user_interaction, false}]}, receive_hello, @@ -207,7 +208,9 @@ lib_works_as_server(Config) -> end), %% and finally connect to it with a regular Erlang SSH client: - {ok,_} = std_connect(HostPort, Config). + {ok,_} = std_connect(HostPort, Config, + [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}] + ). %%-------------------------------------------------------------------- %%% Matching @@ -449,24 +452,24 @@ server_user_password(N, Config) -> lists:nth(N, ?v(user_passwords,Config)). std_connect(Config) -> - {User,Pwd} = server_user_password(Config), - std_connect(server_host(Config), server_port(Config), - Config, - [{user,User},{password,Pwd}]). + std_connect({server_host(Config), server_port(Config)}, Config). std_connect({Host,Port}, Config) -> - {User,Pwd} = server_user_password(Config), - std_connect(Host, Port, Config, [{user,User},{password,Pwd}]). + std_connect({Host,Port}, Config, []). std_connect({Host,Port}, Config, Opts) -> std_connect(Host, Port, Config, Opts). std_connect(Host, Port, Config, Opts) -> + {User,Pwd} = server_user_password(Config), ssh:connect(Host, Port, - [{silently_accept_hosts, true}, - {user_dir, user_dir(Config)}, - {user_interaction, false} | Opts], + %% Prefere User's Opts to the default opts + [O || O = {Tag,_} <- [{user,User},{password,Pwd}, + {silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}], + not lists:keymember(Tag, 1, Opts) + ] ++ Opts, 30000). - %%%---------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 06bf264033..663168b169 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -204,6 +204,7 @@ erlang_client_openssh_server_kexs(Config) when is_list(Config) -> Success = lists:foldl( fun(Kex, Acc) -> + ct:log("============= ~p ============= ~p",[Kex,Acc]), ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, {user_interaction, false}, @@ -228,13 +229,14 @@ erlang_client_openssh_server_kexs(Config) when is_list(Config) -> Acc; Other -> ct:log("~p failed: ~p",[Kex,Other]), - false + [Kex|Acc] end - end, true, ssh_transport:supported_algorithms(kex)), + end, [], ssh_transport:supported_algorithms(kex)), case Success of - true -> + [] -> ok; - false -> + BadKex -> + ct:log("Bad kex algos: ~p",[BadKex]), {fail, "Kex failed for one or more algos"} end. @@ -412,7 +414,7 @@ erlang_server_openssh_client_kexs(Config) when is_list(Config) -> Acc after ?TIMEOUT -> ct:log("Did not receive answer for ~p",[Kex]), - false + [Kex|Acc] end; false -> receive @@ -420,17 +422,18 @@ erlang_server_openssh_client_kexs(Config) when is_list(Config) -> Acc after ?TIMEOUT -> ct:log("Did not receive no matching kex message for ~p",[Kex]), - false + [Kex|Acc] end end - end, true, Kexs), + end, [], Kexs), ssh:stop_daemon(Pid), case Success of - true -> + [] -> ok; - false -> + BadKex -> + ct:log("Bad kex algos: ~p",[BadKex]), {fail, "Kex failed for one or more algos"} end. diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 38b2789742..66df890f5c 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -533,7 +533,7 @@ receive_binary_msg(S0=#s{ssh=C0=#ssh{decrypt_block_size = BlockSize, <> = EncRest, case {ssh_transport:is_valid_mac(Mac, SshPacket, C2), - catch ssh_message:decode(Payload)} + catch ssh_message:decode(set_prefix_if_trouble(Payload,S1))} of {false, _} -> fail(bad_mac,S1); {_, {'EXIT',_}} -> fail(decode_failed,S1); @@ -557,6 +557,24 @@ receive_binary_msg(S0=#s{ssh=C0=#ssh{decrypt_block_size = BlockSize, end. +set_prefix_if_trouble(Msg = <>, #s{alg=#alg{kex=Kex}}) + when Op == 30; + Op == 31 + -> + case catch atom_to_list(Kex) of + "ecdh-sha2-" ++ _ -> + <<"ecdh",Msg/binary>>; + "diffie-hellman-group-exchange-" ++ _ -> + <<"dh_gex",Msg/binary>>; + "diffie-hellman-group" ++ _ -> + <<"dh",Msg/binary>>; + _ -> + Msg + end; +set_prefix_if_trouble(Msg, _) -> + Msg. + + receive_poll(S=#s{socket=Sock}) -> inet:setopts(Sock, [{active,once}]), receive -- cgit v1.2.3 From badee37e8ad95a9da4d497f12e5e291a66561989 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 25 Aug 2015 12:57:39 +0200 Subject: ssh: Reorganize and extend the test suites Add ssh_trpt_test_lib:instantiate/2, ssh_test_lib:default_algoritms/2 and algo_intersection/2 ssh_to_openssh_SUITE uses only algos that sshd and ssh client supports raised timeout limit in ssh_basic_SUITE:ssh_connect_arg4_timeout Break out ssh_renegotiate_SUITE from ssh_basic_SUITE Move std_daemon/4 to ssh_test_lib.erl Add ssh_algorithms_SUITE Add ssh_options_SUITE Add assymetric testing of algorithms Add openssh tests to ssh_algorithms_SUITE Remove algo tests from ssh_sftp_SUITE (now in ssh_algorithms_SUITE) Removed kex algo tests from in ssh_basic_SUITE because they are now in ssh_algorithm_SUITE. fixed test case ssh_protocol_SUITE:no_common_alg_server_disconnects/1 --- lib/ssh/src/ssh_transport.erl | 9 +- lib/ssh/src/ssh_transport.hrl | 11 +- lib/ssh/test/Makefile | 15 +- lib/ssh/test/ssh_algorithms_SUITE.erl | 297 +++++ lib/ssh/test/ssh_algorithms_SUITE_data/id_dsa | 13 + lib/ssh/test/ssh_algorithms_SUITE_data/id_rsa | 15 + .../ssh_algorithms_SUITE_data/ssh_host_dsa_key | 13 + .../ssh_algorithms_SUITE_data/ssh_host_dsa_key.pub | 11 + .../ssh_algorithms_SUITE_data/ssh_host_rsa_key | 16 + .../ssh_algorithms_SUITE_data/ssh_host_rsa_key.pub | 5 + lib/ssh/test/ssh_basic_SUITE.erl | 1305 +------------------- lib/ssh/test/ssh_options_SUITE.erl | 1024 +++++++++++++++ lib/ssh/test/ssh_options_SUITE_data/id_dsa | 13 + lib/ssh/test/ssh_options_SUITE_data/id_rsa | 15 + .../test/ssh_options_SUITE_data/ssh_host_dsa_key | 13 + .../ssh_options_SUITE_data/ssh_host_dsa_key.pub | 11 + .../test/ssh_options_SUITE_data/ssh_host_rsa_key | 16 + .../ssh_options_SUITE_data/ssh_host_rsa_key.pub | 5 + lib/ssh/test/ssh_protocol_SUITE.erl | 11 +- lib/ssh/test/ssh_renegotiate_SUITE.erl | 223 ++++ lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa | 13 + lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa | 15 + .../ssh_renegotiate_SUITE_data/ssh_host_dsa_key | 13 + .../ssh_host_dsa_key.pub | 11 + .../ssh_renegotiate_SUITE_data/ssh_host_rsa_key | 16 + .../ssh_host_rsa_key.pub | 5 + lib/ssh/test/ssh_sftp_SUITE.erl | 99 +- lib/ssh/test/ssh_test_lib.erl | 181 +++ lib/ssh/test/ssh_to_openssh_SUITE.erl | 309 +++-- lib/ssh/test/ssh_trpt_test_lib.erl | 1 + 30 files changed, 2209 insertions(+), 1495 deletions(-) create mode 100644 lib/ssh/test/ssh_algorithms_SUITE.erl create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/id_dsa create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/id_rsa create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key.pub create mode 100644 lib/ssh/test/ssh_options_SUITE.erl create mode 100644 lib/ssh/test/ssh_options_SUITE_data/id_dsa create mode 100644 lib/ssh/test/ssh_options_SUITE_data/id_rsa create mode 100644 lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key create mode 100644 lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key.pub create mode 100644 lib/ssh/test/ssh_renegotiate_SUITE.erl create mode 100644 lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa create mode 100644 lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa create mode 100644 lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key create mode 100644 lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 235d8918f3..1914b223bc 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -801,14 +801,15 @@ alg_final(SSH0) -> {ok,SSH6} = decompress_final(SSH5), SSH6. -select_all(CL, SL) when length(CL) + length(SL) < 50 -> +select_all(CL, SL) when length(CL) + length(SL) < ?MAX_NUM_ALGORITHMS -> A = CL -- SL, %% algortihms only used by client %% algorithms used by client and server (client pref) lists:map(fun(ALG) -> list_to_atom(ALG) end, (CL -- A)); -select_all(_CL, _SL) -> +select_all(CL, SL) -> + Err = lists:concat(["Received too many algorithms (",length(CL),"+",length(SL)," >= ",?MAX_NUM_ALGORITHMS,")."]), throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "Too many algorithms", - language = "en"}). + description = Err, + language = ""}). select([], []) -> diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index e6449e93c5..0bc6b7953b 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -30,6 +30,13 @@ -define(DEFAULT_CLIENT_VERSION, {2, 0}). -define(DEFAULT_SERVER_VERSION, {2, 0}). +-define(MAX_NUM_ALGORITHMS, 100). + +-define(DEFAULT_DH_GROUP_MIN, 512). +-define(DEFAULT_DH_GROUP_NBITS, 1024). +-define(DEFAULT_DH_GROUP_MAX, 4096). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% BASIC transport messages @@ -132,10 +139,6 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% diffie-hellman-group-exchange-sha1 | diffie-hellman-group-exchange-sha256 --define(DEFAULT_DH_GROUP_MIN, 512). --define(DEFAULT_DH_GROUP_NBITS, 1024). --define(DEFAULT_DH_GROUP_MAX, 4096). - -define(SSH_MSG_KEX_DH_GEX_REQUEST_OLD, 30). -define(SSH_MSG_KEX_DH_GEX_REQUEST, 34). -define(SSH_MSG_KEX_DH_GEX_GROUP, 31). diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 47c189c162..96c74c6c8a 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -32,17 +32,22 @@ VSN=$(GS_VSN) # ---------------------------------------------------- MODULES= \ - ssh_test_lib \ - ssh_trpt_test_lib \ - ssh_sup_SUITE \ + ssh_algorithms_SUITE \ + ssh_options_SUITE \ + ssh_renegotiate_SUITE \ + \ ssh_basic_SUITE \ + \ + ssh_connection_SUITE \ ssh_protocol_SUITE \ - ssh_to_openssh_SUITE \ ssh_sftp_SUITE \ ssh_sftpd_SUITE \ ssh_sftpd_erlclient_SUITE \ + ssh_sup_SUITE \ + ssh_to_openssh_SUITE \ ssh_upgrade_SUITE \ - ssh_connection_SUITE \ + ssh_test_lib \ + ssh_trpt_test_lib \ ssh_echo_server \ ssh_peername_sockname_server \ ssh_test_cli \ diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl new file mode 100644 index 0000000000..e67fa2469f --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -0,0 +1,297 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssh_algorithms_SUITE). + +-include_lib("common_test/include/ct.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-define(TIMEOUT, 50000). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + %% [{group,kex},{group,cipher}... etc + [{group,C} || C <- tags()]. + + +groups() -> + ErlAlgos = extract_algos(ssh:default_algorithms()), + SshcAlgos = extract_algos(ssh_test_lib:default_algorithms(sshc)), + SshdAlgos = extract_algos(ssh_test_lib:default_algorithms(sshd)), + + DoubleAlgos = + [{Tag, double(Algs)} || {Tag,Algs} <- ErlAlgos, + length(Algs) > 1, + lists:member(Tag, two_way_tags())], + TagGroupSet = + [{Tag, [], group_members_for_tag(Tag,Algs,DoubleAlgos)} + || {Tag,Algs} <- ErlAlgos, + lists:member(Tag,tags()) + ], + + AlgoTcSet = + [{Alg, [], specific_test_cases(Tag,Alg,SshcAlgos,SshdAlgos)} + || {Tag,Algs} <- ErlAlgos ++ DoubleAlgos, + Alg <- Algs], + + TagGroupSet ++ AlgoTcSet. + +tags() -> [kex,cipher,mac,compression]. +two_way_tags() -> [cipher,mac,compression]. + +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + ct:log("~n~n" + "OS ssh:~n=======~n~p~n~n~n" + "Erl ssh:~n========~n~p~n~n~n" + "Installed ssh client:~n=====================~n~p~n~n~n" + "Installed ssh server:~n=====================~n~p~n~n~n", + [os:cmd("ssh -V"), + ssh:default_algorithms(), + ssh_test_lib:default_algorithms(sshc), + ssh_test_lib:default_algorithms(sshd)]), + ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]), + catch crypto:stop(), + case catch crypto:start() of + ok -> + ssh:start(), + [{std_simple_sftp_size,25000} % Sftp transferred data size + | setup_pubkey(Config)]; + _Else -> + {skip, "Crypto could not be started!"} + end. +end_per_suite(_Config) -> + ssh:stop(), + crypto:stop(). + + +init_per_group(Group, Config) -> + case lists:member(Group, tags()) of + true -> + %% A tag group + Tag = Group, + ct:comment("==== ~p ====",[Tag]), + Config; + false -> + %% An algorithm group + [[{name,Tag}]|_] = ?config(tc_group_path, Config), + Alg = Group, + PA = + case split(Alg) of + [_] -> + [Alg]; + [A1,A2] -> + [{client2server,[A1]}, + {server2client,[A2]}] + end, + ct:log("Init tests for tag=~p alg=~p",[Tag,PA]), + PrefAlgs = {preferred_algorithms,[{Tag,PA}]}, + start_std_daemon([PrefAlgs], + [{pref_algs,PrefAlgs} | Config]) + end. + +end_per_group(_Alg, Config) -> + case ?config(srvr_pid,Config) of + Pid when is_pid(Pid) -> + ssh:stop_daemon(Pid), + ct:log("stopped ~p",[?config(srvr_addr,Config)]); + _ -> + ok + end. + + + +init_per_testcase(sshc_simple_exec, Config) -> + start_pubkey_daemon([?config(pref_algs,Config)], Config); + +init_per_testcase(_TC, Config) -> + Config. + + +end_per_testcase(sshc_simple_exec, Config) -> + case ?config(srvr_pid,Config) of + Pid when is_pid(Pid) -> + ssh:stop_daemon(Pid), + ct:log("stopped ~p",[?config(srvr_addr,Config)]); + _ -> + ok + end; +end_per_testcase(_TC, Config) -> + Config. + + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +%% A simple sftp transfer +simple_sftp(Config) -> + {Host,Port} = ?config(srvr_addr, Config), + ssh_test_lib:std_simple_sftp(Host, Port, Config). + +%%-------------------------------------------------------------------- +%% A simple exec call +simple_exec(Config) -> + {Host,Port} = ?config(srvr_addr, Config), + ssh_test_lib:std_simple_exec(Host, Port, Config). + +%%-------------------------------------------------------------------- +%% Use the ssh client of the OS to connect +sshc_simple_exec(Config) -> + PrivDir = ?config(priv_dir, Config), + KnownHosts = filename:join(PrivDir, "known_hosts"), + {Host,Port} = ?config(srvr_addr, Config), + Cmd = lists:concat(["ssh -p ",Port, + " -C -o UserKnownHostsFile=",KnownHosts, + " ",Host," 1+1."]), + ct:log("~p",[Cmd]), + SshPort = open_port({spawn, Cmd}, [binary]), + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + ct:fail("Did not receive answer") + end. + +%%-------------------------------------------------------------------- +%% Connect to the ssh server of the OS +sshd_simple_exec(_Config) -> + ConnectionRef = ssh_test_lib:connect(22, [{silently_accept_hosts, true}, + {user_interaction, false}]), + {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId0, + "echo testing", infinity), + Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"testing\n">>}}, + case ssh_test_lib:receive_exec_result(Data0) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0); + {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} + = ExitStatus0} -> + ct:log("0: Collected data ~p", [ExitStatus0]), + ssh_test_lib:receive_exec_result(Data0, + ConnectionRef, ChannelId0); + Other0 -> + ct:fail(Other0) + end, + + {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId1, + "echo testing1", infinity), + Data1 = {ssh_cm, ConnectionRef, {data, ChannelId1, 0, <<"testing1\n">>}}, + case ssh_test_lib:receive_exec_result(Data1) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1); + {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId1, 0}} + = ExitStatus1} -> + ct:log("0: Collected data ~p", [ExitStatus1]), + ssh_test_lib:receive_exec_result(Data1, + ConnectionRef, ChannelId1); + Other1 -> + ct:fail(Other1) + end. + +%%%================================================================ +%%% +%%% Lib functions +%%% + +%%%---------------------------------------------------------------- +%%% +%%% For construction of the result of all/0 and groups/0 +%%% +group_members_for_tag(Tag, Algos, DoubleAlgos) -> + [{group,Alg} || Alg <- Algos++proplists:get_value(Tag,DoubleAlgos,[])]. + +double(Algs) -> [concat(A1,A2) || A1 <- Algs, + A2 <- Algs, + A1 =/= A2]. + +concat(A1, A2) -> list_to_atom(lists:concat([A1," + ",A2])). + +split(Alg) -> ssh_test_lib:to_atoms(string:tokens(atom_to_list(Alg), " + ")). + +specific_test_cases(Tag, Alg, SshcAlgos, SshdAlgos) -> + [simple_exec, simple_sftp] ++ + case supports(Tag, Alg, SshcAlgos) of + true -> + case ssh_test_lib:ssh_type() of + openSSH -> + [sshc_simple_exec]; + _ -> + [] + end; + false -> + [] + end ++ + case supports(Tag, Alg, SshdAlgos) of + true -> + [sshd_simple_exec]; + _ -> + [] + end. + +supports(Tag, Alg, Algos) -> + lists:all(fun(A) -> + lists:member(A, proplists:get_value(Tag, Algos,[])) + end, + split(Alg)). + + +extract_algos(Spec) -> + [{Tag,get_atoms(List)} || {Tag,List} <- Spec]. + +get_atoms(L) -> + lists:usort( + [ A || X <- L, + A <- case X of + {_,L1} when is_list(L1) -> L1; + Y when is_atom(Y) -> [Y] + end]). + +%%%---------------------------------------------------------------- +%%% +%%% Test case related +%%% +start_std_daemon(Opts, Config) -> + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config, Opts), + ct:log("started ~p:~p ~p",[Host,Port,Opts]), + [{srvr_pid,Pid},{srvr_addr,{Host,Port}} | Config]. + +start_pubkey_daemon(Opts, Config) -> + {Pid, Host, Port} = ssh_test_lib:std_daemon1(Config, Opts), + ct:log("started1 ~p:~p ~p",[Host,Port,Opts]), + [{srvr_pid,Pid},{srvr_addr,{Host,Port}} | Config]. + + +setup_pubkey(Config) -> + DataDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + ssh_test_lib:setup_dsa_known_host(DataDir, UserDir), + Config. + diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_dsa b/lib/ssh/test/ssh_algorithms_SUITE_data/id_dsa new file mode 100644 index 0000000000..d306f8b26e --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_dsa @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ +APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod +/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP +kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW +JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD +OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt ++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e +uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX +Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE +ZU8w8Q+H7z0j+a+70x2iAw== +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_rsa b/lib/ssh/test/ssh_algorithms_SUITE_data/id_rsa new file mode 100644 index 0000000000..9d7e0dd5fb --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_rsa @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU +DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl +zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB +AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V +TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3 +CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK +SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p +z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd +WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39 +sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3 +xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ +dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x +ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak= +-----END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..75d2025c71 --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_rsa_key.pub @@ -0,0 +1,5 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8 +semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW +RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 27b611780d..51431da48e 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -27,11 +27,44 @@ -include_lib("kernel/include/file.hrl"). %% Note: This directive should only be used in test suites. --compile(export_all). +%%-compile(export_all). + +%%% Test cases +-export([ + app_test/1, + appup_test/1, + cli/1, + close/1, + daemon_already_started/1, + double_close/1, + exec/1, + exec_compressed/1, + idle_time/1, + inet6_option/1, + inet_option/1, + internal_error/1, + known_hosts/1, + misc_ssh_options/1, + openssh_zlib_basic_test/1, + packet_size_zero/1, + pass_phrase/1, + peername_sockname/1, + send/1, + shell/1, + shell_no_unicode/1, + shell_unicode_string/1, + ssh_info_print/1 + ]). + +%%% Common test callbacks +-export([suite/0, all/0, groups/0, + init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, + init_per_testcase/2, end_per_testcase/2 + ]). -define(NEWLINE, <<"\r\n">>). --define(REKEY_DATA_TMO, 65000). %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- @@ -42,38 +75,14 @@ suite() -> all() -> [app_test, appup_test, - {group, key_exchange}, {group, dsa_key}, {group, rsa_key}, {group, dsa_pass_key}, {group, rsa_pass_key}, {group, internal_error}, - connectfun_disconnectfun_server, - connectfun_disconnectfun_client, - {group, renegotiate}, daemon_already_started, - server_password_option, - server_userpassword_option, - {group, dir_options}, double_close, - ssh_connect_timeout, - ssh_connect_arg4_timeout, packet_size_zero, - ssh_daemon_minimal_remote_max_packet_size_option, - ssh_msg_debug_fun_option_client, - ssh_msg_debug_fun_option_server, - disconnectfun_option_server, - disconnectfun_option_client, - unexpectedfun_option_server, - unexpectedfun_option_client, - preferred_algorithms, - id_string_no_opt_client, - id_string_own_string_client, - id_string_random_client, - id_string_no_opt_server, - id_string_own_string_server, - id_string_random_server, - {group, hardening_tests}, ssh_info_print ]. @@ -82,27 +91,7 @@ groups() -> {rsa_key, [], basic_tests()}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, - {internal_error, [], [internal_error]}, - {renegotiate, [], [rekey, rekey_limit, renegotiate1, renegotiate2]}, - {hardening_tests, [], [ssh_connect_nonegtimeout_connected_parallel, - ssh_connect_nonegtimeout_connected_sequential, - ssh_connect_negtimeout_parallel, - ssh_connect_negtimeout_sequential, - max_sessions_ssh_connect_parallel, - max_sessions_ssh_connect_sequential, - max_sessions_sftp_start_channel_parallel, - max_sessions_sftp_start_channel_sequential - ]}, - {key_exchange, [], ['diffie-hellman-group-exchange-sha1', - 'diffie-hellman-group-exchange-sha256', - 'diffie-hellman-group1-sha1', - 'diffie-hellman-group14-sha1', - 'ecdh-sha2-nistp256', - 'ecdh-sha2-nistp384', - 'ecdh-sha2-nistp521' - ]}, - {dir_options, [], [user_dir_option, - system_dir_option]} + {internal_error, [], [internal_error]} ]. @@ -111,7 +100,8 @@ basic_tests() -> exec, exec_compressed, shell, shell_no_unicode, shell_unicode_string, cli, known_hosts, - idle_time, openssh_zlib_basic_test, misc_ssh_options, inet_option]. + idle_time, openssh_zlib_basic_test, + misc_ssh_options, inet_option, inet6_option]. %%-------------------------------------------------------------------- @@ -155,11 +145,6 @@ init_per_group(internal_error, Config) -> ssh_test_lib:setup_dsa(DataDir, PrivDir), file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")), Config; -init_per_group(key_exchange, Config) -> - DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - ssh_test_lib:setup_rsa(DataDir, PrivDir), - Config; init_per_group(dir_options, Config) -> PrivDir = ?config(priv_dir, Config), %% Make unreadable dir: @@ -207,8 +192,6 @@ init_per_group(_, Config) -> end_per_group(hardening_tests, Config) -> end_per_group(dsa_key, Config); -end_per_group(key_exchange, Config) -> - end_per_group(rsa_key, Config); end_per_group(dsa_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:clean_dsa(PrivDir), @@ -279,21 +262,18 @@ end_per_testcase(_Config) -> %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- -app_test() -> - [{doc, "App lication consistency test."}]. +%%% Application consistency test. app_test(Config) when is_list(Config) -> ?t:app_test(ssh), ok. %%-------------------------------------------------------------------- -appup_test() -> - [{doc, "Appup file consistency test."}]. +%%% Appup file consistency test. appup_test(Config) when is_list(Config) -> ok = ?t:appup_test(ssh). %%-------------------------------------------------------------------- -misc_ssh_options() -> - [{doc, "Test that we can set some misc options not tested elsewhere, " - "some options not yet present are not decided if we should support or " - "if they need thier own test case."}]. +%%% Test that we can set some misc options not tested elsewhere +%%% some options not yet present are not decided if we should support or +%%% if they need thier own test case. misc_ssh_options(Config) when is_list(Config) -> SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), @@ -307,8 +287,7 @@ misc_ssh_options(Config) when is_list(Config) -> basic_test([{client_opts, CMiscOpt1}, {server_opts, SMiscOpt1}]). %%-------------------------------------------------------------------- -inet_option() -> - [{doc, "Test configuring IPv4"}]. +%%% Test configuring IPv4 inet_option(Config) when is_list(Config) -> SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), @@ -324,8 +303,7 @@ inet_option(Config) when is_list(Config) -> {server_opts, [{inet, inet} | ServerOpts]}]). %%-------------------------------------------------------------------- -inet6_option() -> - [{doc, "Test configuring IPv6"}]. +%%% Test configuring IPv6 inet6_option(Config) when is_list(Config) -> SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), @@ -341,8 +319,7 @@ inet6_option(Config) when is_list(Config) -> {server_opts, [{inet, inet6} | ServerOpts]}]). %%-------------------------------------------------------------------- -exec() -> - [{doc, "Test api function ssh_connection:exec"}]. +%%% Test api function ssh_connection:exec exec(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -383,8 +360,7 @@ exec(Config) when is_list(Config) -> ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- -exec_compressed() -> - [{doc, "Test that compression option works"}]. +%%% Test that compression option works exec_compressed(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -412,8 +388,7 @@ exec_compressed(Config) when is_list(Config) -> ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- -idle_time() -> - [{doc, "Idle timeout test"}]. +%%% Idle timeout test idle_time(Config) -> SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), @@ -433,183 +408,9 @@ idle_time(Config) -> {error, closed} = ssh_connection:session_channel(ConnectionRef, 1000) end, ssh:stop_daemon(Pid). -%%-------------------------------------------------------------------- -rekey() -> - [{doc, "Idle timeout test"}]. -rekey(Config) -> - SystemDir = ?config(data_dir, Config), - UserDir = ?config(priv_dir, Config), - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {failfun, fun ssh_test_lib:failfun/2}, - {user_passwords, - [{"simon", "says"}]}, - {rekey_limit, 0}]), - - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user_dir, UserDir}, - {user, "simon"}, - {password, "says"}, - {user_interaction, false}, - {rekey_limit, 0}]), - receive - after ?REKEY_DATA_TMO -> - %%By this time rekeying would have been done - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid) - end. %%-------------------------------------------------------------------- -rekey_limit() -> - [{doc, "Test rekeying by data volume"}]. -rekey_limit(Config) -> - SystemDir = ?config(data_dir, Config), - UserDir = ?config(priv_dir, Config), - DataFile = filename:join(UserDir, "rekey.data"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {max_random_length_padding, 0}, - {user_dir, UserDir}, - {user_passwords, - [{"simon", "says"}]}]), - {ok, SftpPid, ConnectionRef} = - ssh_sftp:start_channel(Host, Port, [{system_dir, SystemDir}, - {user_dir, UserDir}, - {user, "simon"}, - {password, "says"}, - {rekey_limit, 2500}, - {max_random_length_padding, 0}, - {user_interaction, false}, - {silently_accept_hosts, true}]), - - Kex1 = get_kex_init(ConnectionRef), - - timer:sleep(?REKEY_DATA_TMO), - Kex1 = get_kex_init(ConnectionRef), - - Data = lists:duplicate(9000,1), - ok = ssh_sftp:write_file(SftpPid, DataFile, Data), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = get_kex_init(ConnectionRef), - - ok = ssh_sftp:write_file(SftpPid, DataFile, "hi\n"), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - timer:sleep(?REKEY_DATA_TMO), - Kex2 = get_kex_init(ConnectionRef), - - - ssh_sftp:stop_channel(SftpPid), - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -renegotiate1() -> - [{doc, "Test rekeying with simulataneous send request"}]. -renegotiate1(Config) -> - SystemDir = ?config(data_dir, Config), - UserDir = ?config(priv_dir, Config), - DataFile = filename:join(UserDir, "renegotiate1.data"), - - {Pid, Host, DPort} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {user_passwords, - [{"simon", "says"}]}]), - RPort = ssh_test_lib:inet_port(), - - {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - - {ok, SftpPid, ConnectionRef} = - ssh_sftp:start_channel(Host, RPort, [{system_dir, SystemDir}, - {user_dir, UserDir}, - {user, "simon"}, - {password, "says"}, - {user_interaction, false}, - {silently_accept_hosts, true}]), - - Kex1 = get_kex_init(ConnectionRef), - - {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), - - ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), - - ssh_relay:hold(RelayPid, rx, 20, 1000), - ssh_connection_handler:renegotiate(ConnectionRef), - spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), - - timer:sleep(2000), - - Kex2 = get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - ssh_relay:stop(RelayPid), - ssh_sftp:stop_channel(SftpPid), - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -renegotiate2() -> - [{doc, "Test rekeying with inflight messages from peer"}]. -renegotiate2(Config) -> - SystemDir = ?config(data_dir, Config), - UserDir = ?config(priv_dir, Config), - DataFile = filename:join(UserDir, "renegotiate1.data"), - - {Pid, Host, DPort} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {user_passwords, - [{"simon", "says"}]}]), - RPort = ssh_test_lib:inet_port(), - - {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - - {ok, SftpPid, ConnectionRef} = - ssh_sftp:start_channel(Host, RPort, [{system_dir, SystemDir}, - {user_dir, UserDir}, - {user, "simon"}, - {password, "says"}, - {user_interaction, false}, - {silently_accept_hosts, true}]), - - Kex1 = get_kex_init(ConnectionRef), - - {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), - - ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), - - ssh_relay:hold(RelayPid, rx, 20, infinity), - spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), - %% need a small pause here to ensure ssh_sftp:write is executed - ct:sleep(10), - ssh_connection_handler:renegotiate(ConnectionRef), - ssh_relay:release(RelayPid, rx), - - timer:sleep(2000), - - Kex2 = get_kex_init(ConnectionRef), - - false = (Kex2 == Kex1), - - ssh_relay:stop(RelayPid), - ssh_sftp:stop_channel(SftpPid), - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -shell() -> - [{doc, "Test that ssh:shell/2 works"}]. +%%% Test that ssh:shell/2 works shell(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -630,8 +431,6 @@ shell(Config) when is_list(Config) -> end. %%-------------------------------------------------------------------- -cli() -> - [{doc, ""}]. cli(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -665,9 +464,8 @@ cli(Config) when is_list(Config) -> end. %%-------------------------------------------------------------------- -daemon_already_started() -> - [{doc, "Test that get correct error message if you try to start a daemon", - "on an adress that already runs a daemon see also seq10667"}]. +%%% Test that get correct error message if you try to start a daemon +%%% on an adress that already runs a daemon see also seq10667 daemon_already_started(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), UserDir = ?config(priv_dir, Config), @@ -682,489 +480,7 @@ daemon_already_started(Config) when is_list(Config) -> ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- -server_password_option() -> - [{doc, "validate to server that uses the 'password' option"}]. -server_password_option(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}]), - - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), - - Reason = "Unable to connect using the available authentication methods", - - {error, Reason} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "vego"}, - {password, "foo"}, - {user_interaction, false}, - {user_dir, UserDir}]), - - ct:log("Test of wrong password: Error msg: ~p ~n", [Reason]), - - ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- - -server_userpassword_option() -> - [{doc, "validate to server that uses the 'password' option"}]. -server_userpassword_option(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, PrivDir}, - {user_passwords, [{"vego", "morot"}]}]), - - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "vego"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), - ssh:close(ConnectionRef), - - Reason = "Unable to connect using the available authentication methods", - - {error, Reason} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), - {error, Reason} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "vego"}, - {password, "foo"}, - {user_interaction, false}, - {user_dir, UserDir}]), - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -system_dir_option(Config) -> - DirUnread = proplists:get_value(unreadable_dir,Config), - FileRead = proplists:get_value(readable_file,Config), - - case ssh_test_lib:daemon([{system_dir, DirUnread}]) of - {error,{eoptions,{{system_dir,DirUnread},eacces}}} -> - ok; - {Pid1,_Host1,Port1} when is_pid(Pid1),is_integer(Port1) -> - ssh:stop_daemon(Pid1), - ct:fail("Didn't detect that dir is unreadable", []) - end, - - case ssh_test_lib:daemon([{system_dir, FileRead}]) of - {error,{eoptions,{{system_dir,FileRead},enotdir}}} -> - ok; - {Pid2,_Host2,Port2} when is_pid(Pid2),is_integer(Port2) -> - ssh:stop_daemon(Pid2), - ct:fail("Didn't detect that option is a plain file", []) - end. - - -user_dir_option(Config) -> - DirUnread = proplists:get_value(unreadable_dir,Config), - FileRead = proplists:get_value(readable_file,Config), - %% Any port will do (beware, implementation knowledge!): - Port = 65535, - - case ssh:connect("localhost", Port, [{user_dir, DirUnread}]) of - {error,{eoptions,{{user_dir,DirUnread},eacces}}} -> - ok; - {error,econnrefused} -> - ct:fail("Didn't detect that dir is unreadable", []) - end, - - case ssh:connect("localhost", Port, [{user_dir, FileRead}]) of - {error,{eoptions,{{user_dir,FileRead},enotdir}}} -> - ok; - {error,econnrefused} -> - ct:fail("Didn't detect that option is a plain file", []) - end. - -%%-------------------------------------------------------------------- -ssh_msg_debug_fun_option_client() -> - [{doc, "validate client that uses the 'ssh_msg_debug_fun' option"}]. -ssh_msg_debug_fun_option_client(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}]), - Parent = self(), - DbgFun = fun(ConnRef,Displ,Msg,Lang) -> Parent ! {msg_dbg,{ConnRef,Displ,Msg,Lang}} end, - - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {user_interaction, false}, - {ssh_msg_debug_fun,DbgFun}]), - %% Beware, implementation knowledge: - gen_fsm:send_all_state_event(ConnectionRef,{ssh_msg_debug,false,<<"Hello">>,<<>>}), - receive - {msg_dbg,X={ConnectionRef,false,<<"Hello">>,<<>>}} -> - ct:log("Got expected dbg msg ~p",[X]), - ssh:stop_daemon(Pid); - {msg_dbg,X={_,false,<<"Hello">>,<<>>}} -> - ct:log("Got dbg msg but bad ConnectionRef (~p expected) ~p",[ConnectionRef,X]), - ssh:stop_daemon(Pid), - {fail, "Bad ConnectionRef received"}; - {msg_dbg,X} -> - ct:log("Got bad dbg msg ~p",[X]), - ssh:stop_daemon(Pid), - {fail,"Bad msg received"} - after 1000 -> - ssh:stop_daemon(Pid), - {fail,timeout} - end. - -%%-------------------------------------------------------------------- -'diffie-hellman-group-exchange-sha1'(Config) -> - kextest('diffie-hellman-group-exchange-sha1',Config). - -'diffie-hellman-group-exchange-sha256'(Config) -> - kextest('diffie-hellman-group-exchange-sha256',Config). - -'diffie-hellman-group1-sha1'(Config) -> - kextest('diffie-hellman-group1-sha1',Config). - -'diffie-hellman-group14-sha1'(Config) -> - kextest('diffie-hellman-group14-sha1',Config). - -'ecdh-sha2-nistp256'(Config) -> - kextest('ecdh-sha2-nistp256',Config). - -'ecdh-sha2-nistp384'(Config) -> - kextest('ecdh-sha2-nistp384',Config). - -'ecdh-sha2-nistp521'(Config) -> - kextest('ecdh-sha2-nistp521',Config). - - -kextest(Kex, Config) -> - case lists:member(Kex, ssh_transport:supported_algorithms(kex)) of - true -> - process_flag(trap_exit, true), - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {user_passwords, [{"foo", "bar"}]}, - {preferred_algorithms, - [{kex, [Kex]}]}, - {failfun, fun ssh_test_lib:failfun/2}]), - - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "bar"}, - {user_dir, UserDir}, - {preferred_algorithms, - [{kex, [Kex]}]}, - {user_interaction, false}]), - - {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId, - "1+1.", infinity), - Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, - case ssh_test_lib:receive_exec_result(Data) of - expected -> - ok; - Other -> - ct:fail(Other) - end, - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), - ssh:stop_daemon(Pid); - false -> - {skip, lists:concat([Kex, " is not supported"])} - end. - -%%-------------------------------------------------------------------- -connectfun_disconnectfun_server(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - Parent = self(), - Ref = make_ref(), - ConnFun = fun(_,_,_) -> Parent ! {connect,Ref} end, - DiscFun = fun(R) -> Parent ! {disconnect,Ref,R} end, - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}, - {disconnectfun, DiscFun}, - {connectfun, ConnFun}]), - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {user_interaction, false}]), - receive - {connect,Ref} -> - ssh:close(ConnectionRef), - receive - {disconnect,Ref,R} -> - ct:log("Disconnect result: ~p",[R]), - ssh:stop_daemon(Pid) - after 2000 -> - {fail, "No disconnectfun action"} - end - after 2000 -> - {fail, "No connectfun action"} - end. - -%%-------------------------------------------------------------------- -connectfun_disconnectfun_client(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - Parent = self(), - Ref = make_ref(), - DiscFun = fun(R) -> Parent ! {disconnect,Ref,R} end, - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}]), - _ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {disconnectfun, DiscFun}, - {user_interaction, false}]), - ssh:stop_daemon(Pid), - receive - {disconnect,Ref,R} -> - ct:log("Disconnect result: ~p",[R]) - after 2000 -> - {fail, "No disconnectfun action"} - end. - -%%-------------------------------------------------------------------- -ssh_msg_debug_fun_option_server() -> - [{doc, "validate client that uses the 'ssh_msg_debug_fun' option"}]. -ssh_msg_debug_fun_option_server(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - Parent = self(), - DbgFun = fun(ConnRef,Displ,Msg,Lang) -> Parent ! {msg_dbg,{ConnRef,Displ,Msg,Lang}} end, - ConnFun = fun(_,_,_) -> Parent ! {connection_pid,self()} end, - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}, - {connectfun, ConnFun}, - {ssh_msg_debug_fun, DbgFun}]), - _ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {user_interaction, false}]), - receive - {connection_pid,Server} -> - %% Beware, implementation knowledge: - gen_fsm:send_all_state_event(Server,{ssh_msg_debug,false,<<"Hello">>,<<>>}), - receive - {msg_dbg,X={_,false,<<"Hello">>,<<>>}} -> - ct:log("Got expected dbg msg ~p",[X]), - ssh:stop_daemon(Pid); - {msg_dbg,X} -> - ct:log("Got bad dbg msg ~p",[X]), - ssh:stop_daemon(Pid), - {fail,"Bad msg received"} - after 3000 -> - ssh:stop_daemon(Pid), - {fail,timeout2} - end - after 3000 -> - ssh:stop_daemon(Pid), - {fail,timeout1} - end. - -%%-------------------------------------------------------------------- -disconnectfun_option_server(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - Parent = self(), - DisConnFun = fun(Reason) -> Parent ! {disconnect,Reason} end, - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}, - {disconnectfun, DisConnFun}]), - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {user_interaction, false}]), - ssh:close(ConnectionRef), - receive - {disconnect,Reason} -> - ct:log("Server detected disconnect: ~p",[Reason]), - ssh:stop_daemon(Pid), - ok - after 3000 -> - receive - X -> ct:log("received ~p",[X]) - after 0 -> ok - end, - {fail,"Timeout waiting for disconnect"} - end. - -%%-------------------------------------------------------------------- -disconnectfun_option_client(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - Parent = self(), - DisConnFun = fun(Reason) -> Parent ! {disconnect,Reason} end, - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}]), - _ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {user_interaction, false}, - {disconnectfun, DisConnFun}]), - ssh:stop_daemon(Pid), - receive - {disconnect,Reason} -> - ct:log("Client detected disconnect: ~p",[Reason]), - ok - after 3000 -> - receive - X -> ct:log("received ~p",[X]) - after 0 -> ok - end, - {fail,"Timeout waiting for disconnect"} - end. - -%%-------------------------------------------------------------------- -unexpectedfun_option_server(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - Parent = self(), - ConnFun = fun(_,_,_) -> Parent ! {connection_pid,self()} end, - UnexpFun = fun(Msg,Peer) -> - Parent ! {unexpected,Msg,Peer,self()}, - skip - end, - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}, - {connectfun, ConnFun}, - {unexpectedfun, UnexpFun}]), - _ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {user_interaction, false}]), - receive - {connection_pid,Server} -> - %% Beware, implementation knowledge: - Server ! unexpected_message, - receive - {unexpected, unexpected_message, {{_,_,_,_},_}, _} -> ok; - {unexpected, unexpected_message, Peer, _} -> ct:fail("Bad peer ~p",[Peer]); - M = {unexpected, _, _, _} -> ct:fail("Bad msg ~p",[M]) - after 3000 -> - ssh:stop_daemon(Pid), - {fail,timeout2} - end - after 3000 -> - ssh:stop_daemon(Pid), - {fail,timeout1} - end. - -%%-------------------------------------------------------------------- -unexpectedfun_option_client(Config) -> - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - SysDir = ?config(data_dir, Config), - - Parent = self(), - UnexpFun = fun(Msg,Peer) -> - Parent ! {unexpected,Msg,Peer,self()}, - skip - end, - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, UserDir}, - {password, "morot"}, - {failfun, fun ssh_test_lib:failfun/2}]), - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_dir, UserDir}, - {user_interaction, false}, - {unexpectedfun, UnexpFun}]), - %% Beware, implementation knowledge: - ConnectionRef ! unexpected_message, - - receive - {unexpected, unexpected_message, {{_,_,_,_},_}, ConnectionRef} -> - ok; - {unexpected, unexpected_message, Peer, ConnectionRef} -> - ct:fail("Bad peer ~p",[Peer]); - M = {unexpected, _, _, _} -> - ct:fail("Bad msg ~p",[M]) - after 3000 -> - ssh:stop_daemon(Pid), - {fail,timeout} - end. - -%%-------------------------------------------------------------------- -known_hosts() -> - [{doc, "check that known_hosts is updated correctly"}]. +%%% check that known_hosts is updated correctly known_hosts(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), @@ -1190,8 +506,7 @@ known_hosts(Config) when is_list(Config) -> ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- -pass_phrase() -> - [{doc, "Test that we can use keyes protected by pass phrases"}]. +%%% Test that we can use keyes protected by pass phrases pass_phrase(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -1209,28 +524,26 @@ pass_phrase(Config) when is_list(Config) -> {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), ssh:stop_daemon(Pid). -%%-------------------------------------------------------------------- -internal_error() -> - [{doc,"Test that client does not hang if disconnects due to internal error"}]. +%%-------------------------------------------------------------------- +%%% Test that client does not hang if disconnects due to internal error internal_error(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {failfun, fun ssh_test_lib:failfun/2}]), + {user_dir, UserDir}, + {failfun, fun ssh_test_lib:failfun/2}]), {error, Error} = - ssh:connect(Host, Port, [{silently_accept_hosts, true}, - {user_dir, UserDir}, - {user_interaction, false}]), + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}]), check_error(Error), ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- -send() -> - [{doc, "Test ssh_connection:send/3"}]. +%%% Test ssh_connection:send/3 send(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -1250,8 +563,7 @@ send(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -peername_sockname() -> - [{doc, "Test ssh:connection_info([peername, sockname])"}]. +%%% Test ssh:connection_info([peername, sockname]) peername_sockname(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -1301,8 +613,7 @@ ips(Name) when is_list(Name) -> %%-------------------------------------------------------------------- -close() -> - [{doc, "Client receives close when server closes"}]. +%%% Client receives close when server closes close(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = filename:join(?config(priv_dir, Config), system), @@ -1326,8 +637,7 @@ close(Config) when is_list(Config) -> end. %%-------------------------------------------------------------------- -double_close() -> - [{doc, "Simulate that we try to close an already closed connection"}]. +%%% Simulate that we try to close an already closed connection double_close(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), @@ -1347,91 +657,6 @@ double_close(Config) when is_list(Config) -> exit(CM, {shutdown, normal}), ok = ssh:close(CM). -%%-------------------------------------------------------------------- -ssh_connect_timeout() -> - [{doc, "Test connect_timeout option in ssh:connect/4"}]. -ssh_connect_timeout(_Config) -> - ConnTimeout = 2000, - {error,{faked_transport,connect,TimeoutToTransport}} = - ssh:connect("localhost", 12345, - [{transport,{tcp,?MODULE,tcp_closed}}, - {connect_timeout,ConnTimeout}], - 1000), - case TimeoutToTransport of - ConnTimeout -> ok; - Other -> - ct:log("connect_timeout is ~p but transport received ~p",[ConnTimeout,Other]), - {fail,"ssh:connect/4 wrong connect_timeout received in transport"} - end. - -%% Help for the test above -connect(_Host, _Port, _Opts, Timeout) -> - {error, {faked_transport,connect,Timeout}}. - - -%%-------------------------------------------------------------------- -ssh_connect_arg4_timeout() -> - [{doc, "Test fourth argument in ssh:connect/4"}]. -ssh_connect_arg4_timeout(_Config) -> - Timeout = 1000, - Parent = self(), - %% start the server - Server = spawn(fun() -> - {ok,Sl} = gen_tcp:listen(0,[]), - {ok,{_,Port}} = inet:sockname(Sl), - Parent ! {port,self(),Port}, - Rsa = gen_tcp:accept(Sl), - ct:log("Server gen_tcp:accept got ~p",[Rsa]), - receive after 2*Timeout -> ok end %% let client timeout first - end), - - %% Get listening port - Port = receive - {port,Server,ServerPort} -> ServerPort - end, - - %% try to connect with a timeout, but "supervise" it - Client = spawn(fun() -> - T0 = erlang:monotonic_time(), - Rc = ssh:connect("localhost",Port,[],Timeout), - ct:log("Client ssh:connect got ~p",[Rc]), - Parent ! {done,self(),Rc,T0} - end), - - %% Wait for client reaction on the connection try: - receive - {done, Client, {error,timeout}, T0} -> - Msp = ms_passed(T0), - exit(Server,hasta_la_vista___baby), - Low = 0.9*Timeout, - High = 1.1*Timeout, - ct:log("Timeout limits: ~.4f - ~.4f ms, timeout " - "was ~.4f ms, expected ~p ms",[Low,High,Msp,Timeout]), - if - Low ok; - true -> {fail, "timeout not within limits"} - end; - - {done, Client, {error,Other}, _T0} -> - ct:log("Error message \"~p\" from the client is unexpected.",[{error,Other}]), - {fail, "Unexpected error message"}; - - {done, Client, {ok,_Ref}, _T0} -> - {fail,"ssh-connected ???"} - after - 5000 -> - exit(Server,hasta_la_vista___baby), - exit(Client,hasta_la_vista___baby), - {fail, "Didn't timeout"} - end. - -%% Help function, elapsed milliseconds since T0 -ms_passed(T0) -> - %% OTP 18 - erlang:convert_time_unit(erlang:monotonic_time() - T0, - native, - micro_seconds) / 1000. - %%-------------------------------------------------------------------- packet_size_zero(Config) -> SystemDir = ?config(data_dir, Config), @@ -1463,249 +688,6 @@ packet_size_zero(Config) -> ok end. -%%-------------------------------------------------------------------- -ssh_daemon_minimal_remote_max_packet_size_option(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - - {Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {user_passwords, [{"vego", "morot"}]}, - {failfun, fun ssh_test_lib:failfun/2}, - {minimal_remote_max_packet_size, 14}]), - Conn = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user_dir, UserDir}, - {user_interaction, false}, - {user, "vego"}, - {password, "morot"}]), - - %% Try the limits of the minimal_remote_max_packet_size: - {ok, _ChannelId} = ssh_connection:session_channel(Conn, 100, 14, infinity), - {open_error,_,"Maximum packet size below 14 not supported",_} = - ssh_connection:session_channel(Conn, 100, 13, infinity), - - ssh:close(Conn), - ssh:stop_daemon(Server). - -%%-------------------------------------------------------------------- -%% This test try every algorithm by connecting to an Erlang server -preferred_algorithms(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - - {Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {user_passwords, [{"vego", "morot"}]}, - {failfun, fun ssh_test_lib:failfun/2}]), - Available = ssh:default_algorithms(), - Tests = [[{Tag,[Alg]}] || {Tag, SubAlgs} <- Available, - is_atom(hd(SubAlgs)), - Alg <- SubAlgs] - ++ [[{Tag,[{T1,[A1]},{T2,[A2]}]}] || {Tag, [{T1,As1},{T2,As2}]} <- Available, - A1 <- As1, - A2 <- As2], - ct:log("TESTS: ~p",[Tests]), - [connect_exec_channel(Host,Port,PrefAlgs) || PrefAlgs <- Tests], - ssh:stop_daemon(Server). - - -connect_exec_channel(_Host, Port, Algs) -> - ct:log("Try ~p",[Algs]), - ConnectionRef = ssh_test_lib:connect(Port, [{silently_accept_hosts, true}, - {user_interaction, false}, - {user, "vego"}, - {password, "morot"}, - {preferred_algorithms,Algs} - ]), - chan_exec(ConnectionRef, "2*21.", <<"42\n">>), - ssh:close(ConnectionRef). - -chan_exec(ConnectionRef, Cmnd, Expected) -> - {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId0,Cmnd, infinity), - Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, Expected}}, - case ssh_test_lib:receive_exec_result(Data0) of - expected -> - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0); - {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} - = ExitStatus0} -> - ct:log("0: Collected data ~p", [ExitStatus0]), - ssh_test_lib:receive_exec_result(Data0, - ConnectionRef, ChannelId0); - Other0 -> - ct:fail(Other0) - end. - -%%-------------------------------------------------------------------- -id_string_no_opt_client(Config) -> - {Server, _Host, Port} = fake_daemon(Config), - {error,_} = ssh:connect("localhost", Port, [], 1000), - receive - {id,Server,"SSH-2.0-Erlang/"++Vsn} -> - true = expected_ssh_vsn(Vsn); - {id,Server,Other} -> - ct:fail("Unexpected id: ~s.",[Other]) - after 5000 -> - {fail,timeout} - end. - -%%-------------------------------------------------------------------- -id_string_own_string_client(Config) -> - {Server, _Host, Port} = fake_daemon(Config), - {error,_} = ssh:connect("localhost", Port, [{id_string,"Pelle"}], 1000), - receive - {id,Server,"SSH-2.0-Pelle\r\n"} -> - ok; - {id,Server,Other} -> - ct:fail("Unexpected id: ~s.",[Other]) - after 5000 -> - {fail,timeout} - end. - -%%-------------------------------------------------------------------- -id_string_random_client(Config) -> - {Server, _Host, Port} = fake_daemon(Config), - {error,_} = ssh:connect("localhost", Port, [{id_string,random}], 1000), - receive - {id,Server,Id="SSH-2.0-Erlang"++_} -> - ct:fail("Unexpected id: ~s.",[Id]); - {id,Server,Rnd="SSH-2.0-"++_} -> - ct:log("Got correct ~s",[Rnd]); - {id,Server,Id} -> - ct:fail("Unexpected id: ~s.",[Id]) - after 5000 -> - {fail,timeout} - end. - -%%-------------------------------------------------------------------- -id_string_no_opt_server(Config) -> - {_Server, Host, Port} = std_daemon(Config, []), - {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), - {ok,"SSH-2.0-Erlang/"++Vsn} = gen_tcp:recv(S1, 0, 2000), - true = expected_ssh_vsn(Vsn). - -%%-------------------------------------------------------------------- -id_string_own_string_server(Config) -> - {_Server, Host, Port} = std_daemon(Config, [{id_string,"Olle"}]), - {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), - {ok,"SSH-2.0-Olle\r\n"} = gen_tcp:recv(S1, 0, 2000). - -%%-------------------------------------------------------------------- -id_string_random_server(Config) -> - {_Server, Host, Port} = std_daemon(Config, [{id_string,random}]), - {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), - {ok,"SSH-2.0-"++Rnd} = gen_tcp:recv(S1, 0, 2000), - case Rnd of - "Erlang"++_ -> ct:log("Id=~p",[Rnd]), - {fail,got_default_id}; - "Olle\r\n" -> {fail,got_previous_tests_value}; - _ -> ct:log("Got ~s.",[Rnd]) - end. - -%%-------------------------------------------------------------------- -ssh_connect_negtimeout_parallel(Config) -> ssh_connect_negtimeout(Config,true). -ssh_connect_negtimeout_sequential(Config) -> ssh_connect_negtimeout(Config,false). - -ssh_connect_negtimeout(Config, Parallel) -> - process_flag(trap_exit, true), - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), - NegTimeOut = 2000, % ms - ct:log("Parallel: ~p",[Parallel]), - - {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, - {parallel_login, Parallel}, - {negotiation_timeout, NegTimeOut}, - {failfun, fun ssh_test_lib:failfun/2}]), - - {ok,Socket} = gen_tcp:connect(Host, Port, []), - - Factor = 2, - ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), - ct:sleep(round(Factor * NegTimeOut)), - - case inet:sockname(Socket) of - {ok,_} -> ct:fail("Socket not closed"); - {error,_} -> ok - end. - -%%-------------------------------------------------------------------- -ssh_connect_nonegtimeout_connected_parallel() -> - [{doc, "Test that ssh connection does not timeout if the connection is established (parallel)"}]. -ssh_connect_nonegtimeout_connected_parallel(Config) -> - ssh_connect_nonegtimeout_connected(Config, true). - -ssh_connect_nonegtimeout_connected_sequential() -> - [{doc, "Test that ssh connection does not timeout if the connection is established (non-parallel)"}]. -ssh_connect_nonegtimeout_connected_sequential(Config) -> - ssh_connect_nonegtimeout_connected(Config, false). - - -ssh_connect_nonegtimeout_connected(Config, Parallel) -> - process_flag(trap_exit, true), - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), - NegTimeOut = 20000, % ms - ct:log("Parallel: ~p",[Parallel]), - - {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, - {parallel_login, Parallel}, - {negotiation_timeout, NegTimeOut}, - {failfun, fun ssh_test_lib:failfun/2}]), - ct:log("~p Listen ~p:~p",[_Pid,_Host,Port]), - ct:sleep(500), - - IO = ssh_test_lib:start_io_server(), - Shell = ssh_test_lib:start_shell(Port, IO, UserDir), - receive - Error = {'EXIT', _, _} -> - ct:log("~p",[Error]), - ct:fail(no_ssh_connection); - ErlShellStart -> - ct:log("---Erlang shell start: ~p~n", [ErlShellStart]), - one_shell_op(IO, NegTimeOut), - one_shell_op(IO, NegTimeOut), - - Factor = 2, - ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), - ct:sleep(round(Factor * NegTimeOut)), - - one_shell_op(IO, NegTimeOut) - end, - exit(Shell, kill). - - -one_shell_op(IO, TimeOut) -> - ct:log("One shell op: Waiting for prompter"), - receive - ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0]) - after TimeOut -> ct:fail("Timeout waiting for promter") - end, - - IO ! {input, self(), "2*3*7.\r\n"}, - receive - Echo0 -> ct:log("Echo: ~p ~n", [Echo0]) - after TimeOut -> ct:fail("Timeout waiting for echo") - end, - - receive - ?NEWLINE -> ct:log("NEWLINE received", []) - after TimeOut -> - receive Any1 -> ct:log("Bad NEWLINE: ~p",[Any1]) - after 0 -> ct:fail("Timeout waiting for NEWLINE") - end - end, - - receive - Result0 -> ct:log("Result: ~p~n", [Result0]) - after TimeOut -> ct:fail("Timeout waiting for result") - end. - %%-------------------------------------------------------------------- shell_no_unicode(Config) -> new_do_shell(?config(io,Config), @@ -1724,8 +706,7 @@ shell_unicode_string(Config) -> ]). %%-------------------------------------------------------------------- -openssh_zlib_basic_test() -> - [{doc, "Test basic connection with openssh_zlib"}]. +%%% Test basic connection with openssh_zlib openssh_zlib_basic_test(Config) -> SystemDir = filename:join(?config(priv_dir, Config), system), UserDir = ?config(priv_dir, Config), @@ -1744,102 +725,6 @@ openssh_zlib_basic_test(Config) -> ok = ssh:close(ConnectionRef), ssh:stop_daemon(Pid). -%%-------------------------------------------------------------------- - -max_sessions_ssh_connect_parallel(Config) -> - max_sessions(Config, true, connect_fun(ssh__connect,Config)). -max_sessions_ssh_connect_sequential(Config) -> - max_sessions(Config, false, connect_fun(ssh__connect,Config)). - -max_sessions_sftp_start_channel_parallel(Config) -> - max_sessions(Config, true, connect_fun(ssh_sftp__start_channel, Config)). -max_sessions_sftp_start_channel_sequential(Config) -> - max_sessions(Config, false, connect_fun(ssh_sftp__start_channel, Config)). - - -%%%---- helpers: -connect_fun(ssh__connect, Config) -> - fun(Host,Port) -> - ssh_test_lib:connect(Host, Port, - [{silently_accept_hosts, true}, - {user_dir, ?config(priv_dir,Config)}, - {user_interaction, false}, - {user, "carni"}, - {password, "meat"} - ]) - %% ssh_test_lib returns R when ssh:connect returns {ok,R} - end; -connect_fun(ssh_sftp__start_channel, _Config) -> - fun(Host,Port) -> - {ok,_Pid,ConnRef} = - ssh_sftp:start_channel(Host, Port, - [{silently_accept_hosts, true}, - {user, "carni"}, - {password, "meat"} - ]), - ConnRef - end. - - -max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> - Connect = fun(Host,Port) -> - R = Connect0(Host,Port), - ct:log("Connect(~p,~p) -> ~p",[Host,Port,R]), - R - end, - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), - MaxSessions = 5, - {Pid, Host, Port} = ssh_test_lib:daemon([ - {system_dir, SystemDir}, - {user_dir, UserDir}, - {user_passwords, [{"carni", "meat"}]}, - {parallel_login, ParallelLogin}, - {max_sessions, MaxSessions} - ]), - ct:log("~p Listen ~p:~p for max ~p sessions",[Pid,Host,Port,MaxSessions]), - try [Connect(Host,Port) || _ <- lists:seq(1,MaxSessions)] - of - Connections -> - %% Step 1 ok: could set up max_sessions connections - ct:log("Connections up: ~p",[Connections]), - [_|_] = Connections, - - %% Now try one more than alowed: - ct:log("Info Report might come here...",[]), - try Connect(Host,Port) - of - _ConnectionRef1 -> - ssh:stop_daemon(Pid), - {fail,"Too many connections accepted"} - catch - error:{badmatch,{error,"Connection closed"}} -> - %% Step 2 ok: could not set up max_sessions+1 connections - %% This is expected - %% Now stop one connection and try to open one more - ok = ssh:close(hd(Connections)), - receive after 250 -> ok end, % sleep so the supervisor has time to count down. Not nice... - try Connect(Host,Port) - of - _ConnectionRef1 -> - %% Step 3 ok: could set up one more connection after killing one - %% Thats good. - ssh:stop_daemon(Pid), - ok - catch - error:{badmatch,{error,"Connection closed"}} -> - %% Bad indeed. Could not set up one more connection even after killing - %% one existing. Very bad. - ssh:stop_daemon(Pid), - {fail,"Does not decrease # active sessions"} - end - end - catch - error:{badmatch,{error,"Connection closed"}} -> - ssh:stop_daemon(Pid), - {fail,"Too few connections accepted"} - end. - %%-------------------------------------------------------------------- ssh_info_print(Config) -> %% Just check that ssh_print:info() crashes @@ -1911,7 +796,6 @@ ssh_info_print(Config) -> %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- - %% Due to timing the error message may or may not be delivered to %% the "tcp-application" before the socket closed message is recived check_error("Invalid state") -> @@ -2070,62 +954,3 @@ new_do_shell_prompt(IO, N, Op, Str, More) -> new_do_shell(IO, N, [{Op,Str}|More]). %%-------------------------------------------------------------------- - - -std_daemon(Config, ExtraOpts) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth - file:make_dir(UserDir), - {_Server, _Host, _Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {failfun, fun ssh_test_lib:failfun/2} | ExtraOpts]). - -expected_ssh_vsn(Str) -> - try - {ok,L} = application:get_all_key(ssh), - proplists:get_value(vsn,L,"")++"\r\n" - of - Str -> true; - "\r\n" -> true; - _ -> false - catch - _:_ -> true %% ssh not started so we dont't know - end. - - -fake_daemon(_Config) -> - Parent = self(), - %% start the server - Server = spawn(fun() -> - {ok,Sl} = gen_tcp:listen(0,[{packet,line}]), - {ok,{Host,Port}} = inet:sockname(Sl), - ct:log("fake_daemon listening on ~p:~p~n",[Host,Port]), - Parent ! {sockname,self(),Host,Port}, - Rsa = gen_tcp:accept(Sl), - ct:log("Server gen_tcp:accept got ~p",[Rsa]), - {ok,S} = Rsa, - receive - {tcp, S, Id} -> Parent ! {id,self(),Id} - end - end), - %% Get listening host and port - receive - {sockname,Server,ServerHost,ServerPort} -> {Server, ServerHost, ServerPort} - end. - -%% get_kex_init - helper function to get key_exchange_init_msg -get_kex_init(Conn) -> - %% First, validate the key exchange is complete (StateName == connected) - {connected,S} = sys:get_state(Conn), - %% Next, walk through the elements of the #state record looking - %% for the #ssh_msg_kexinit record. This method is robust against - %% changes to either record. The KEXINIT message contains a cookie - %% unique to each invocation of the key exchange procedure (RFC4253) - SL = tuple_to_list(S), - case lists:keyfind(ssh_msg_kexinit, 1, SL) of - false -> - throw(not_found); - KexInit -> - KexInit - end. diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl new file mode 100644 index 0000000000..d64c78da35 --- /dev/null +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -0,0 +1,1024 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssh_options_SUITE). + +%%% This test suite tests different options for the ssh functions + + +-include_lib("common_test/include/ct.hrl"). +-include_lib("kernel/include/file.hrl"). + + +%%% Test cases +-export([connectfun_disconnectfun_client/1, + disconnectfun_option_client/1, + disconnectfun_option_server/1, + id_string_no_opt_client/1, + id_string_no_opt_server/1, + id_string_own_string_client/1, + id_string_own_string_server/1, + id_string_random_client/1, + id_string_random_server/1, + max_sessions_sftp_start_channel_parallel/1, + max_sessions_sftp_start_channel_sequential/1, + max_sessions_ssh_connect_parallel/1, + max_sessions_ssh_connect_sequential/1, + server_password_option/1, + server_userpassword_option/1, + ssh_connect_arg4_timeout/1, + ssh_connect_negtimeout_parallel/1, + ssh_connect_negtimeout_sequential/1, + ssh_connect_nonegtimeout_connected_parallel/1, + ssh_connect_nonegtimeout_connected_sequential/1, + ssh_connect_timeout/1, connect/4, + ssh_daemon_minimal_remote_max_packet_size_option/1, + ssh_msg_debug_fun_option_client/1, + ssh_msg_debug_fun_option_server/1, + system_dir_option/1, + unexpectedfun_option_client/1, + unexpectedfun_option_server/1, + user_dir_option/1, + connectfun_disconnectfun_server/1 + ]). + +%%% Common test callbacks +-export([suite/0, all/0, groups/0, + init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, + init_per_testcase/2, end_per_testcase/2 + ]). + + +-define(NEWLINE, <<"\r\n">>). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + [connectfun_disconnectfun_server, + connectfun_disconnectfun_client, + server_password_option, + server_userpassword_option, + {group, dir_options}, + ssh_connect_timeout, + ssh_connect_arg4_timeout, + ssh_daemon_minimal_remote_max_packet_size_option, + ssh_msg_debug_fun_option_client, + ssh_msg_debug_fun_option_server, + disconnectfun_option_server, + disconnectfun_option_client, + unexpectedfun_option_server, + unexpectedfun_option_client, + id_string_no_opt_client, + id_string_own_string_client, + id_string_random_client, + id_string_no_opt_server, + id_string_own_string_server, + id_string_random_server, + {group, hardening_tests} + ]. + +groups() -> + [{hardening_tests, [], [ssh_connect_nonegtimeout_connected_parallel, + ssh_connect_nonegtimeout_connected_sequential, + ssh_connect_negtimeout_parallel, + ssh_connect_negtimeout_sequential, + max_sessions_ssh_connect_parallel, + max_sessions_ssh_connect_sequential, + max_sessions_sftp_start_channel_parallel, + max_sessions_sftp_start_channel_sequential + ]}, + {dir_options, [], [user_dir_option, + system_dir_option]} + ]. + + +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + catch crypto:stop(), + case catch crypto:start() of + ok -> + Config; + _Else -> + {skip, "Crypto could not be started!"} + end. +end_per_suite(_Config) -> + ssh:stop(), + crypto:stop(). +%%-------------------------------------------------------------------- +init_per_group(hardening_tests, Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_dsa(DataDir, PrivDir), + Config; +init_per_group(dir_options, Config) -> + PrivDir = ?config(priv_dir, Config), + %% Make unreadable dir: + Dir_unreadable = filename:join(PrivDir, "unread"), + ok = file:make_dir(Dir_unreadable), + {ok,F1} = file:read_file_info(Dir_unreadable), + ok = file:write_file_info(Dir_unreadable, + F1#file_info{mode = F1#file_info.mode band (bnot 8#00444)}), + %% Make readable file: + File_readable = filename:join(PrivDir, "file"), + ok = file:write_file(File_readable, <<>>), + + %% Check: + case {file:read_file_info(Dir_unreadable), + file:read_file_info(File_readable)} of + {{ok, Id=#file_info{type=directory, access=Md}}, + {ok, If=#file_info{type=regular, access=Mf}}} -> + AccessOK = + case {Md, Mf} of + {read, _} -> false; + {read_write, _} -> false; + {_, read} -> true; + {_, read_write} -> true; + _ -> false + end, + + case AccessOK of + true -> + %% Save: + [{unreadable_dir, Dir_unreadable}, + {readable_file, File_readable} + | Config]; + false -> + ct:log("File#file_info : ~p~n" + "Dir#file_info : ~p",[If,Id]), + {skip, "File or dir mode settings failed"} + end; + + NotDirFile -> + ct:log("{Dir,File} -> ~p",[NotDirFile]), + {skip, "File/Dir creation failed"} + end; +init_per_group(_, Config) -> + Config. + +end_per_group(_, Config) -> + Config. +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + ssh:start(), + Config. + +end_per_testcase(TestCase, Config) when TestCase == server_password_option; + TestCase == server_userpassword_option -> + UserDir = filename:join(?config(priv_dir, Config), nopubkey), + ssh_test_lib:del_dirs(UserDir), + end_per_testcase(Config); +end_per_testcase(_TestCase, Config) -> + end_per_testcase(Config). + +end_per_testcase(_Config) -> + ssh:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +%%-------------------------------------------------------------------- + +%%% validate to server that uses the 'password' option +server_password_option(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}]), + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + + Reason = "Unable to connect using the available authentication methods", + + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + + ct:log("Test of wrong password: Error msg: ~p ~n", [Reason]), + + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- + +%%% validate to server that uses the 'password' option +server_userpassword_option(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, PrivDir}, + {user_passwords, [{"vego", "morot"}]}]), + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:close(ConnectionRef), + + Reason = "Unable to connect using the available authentication methods", + + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +system_dir_option(Config) -> + DirUnread = proplists:get_value(unreadable_dir,Config), + FileRead = proplists:get_value(readable_file,Config), + + case ssh_test_lib:daemon([{system_dir, DirUnread}]) of + {error,{eoptions,{{system_dir,DirUnread},eacces}}} -> + ok; + {Pid1,_Host1,Port1} when is_pid(Pid1),is_integer(Port1) -> + ssh:stop_daemon(Pid1), + ct:fail("Didn't detect that dir is unreadable", []) + end, + + case ssh_test_lib:daemon([{system_dir, FileRead}]) of + {error,{eoptions,{{system_dir,FileRead},enotdir}}} -> + ok; + {Pid2,_Host2,Port2} when is_pid(Pid2),is_integer(Port2) -> + ssh:stop_daemon(Pid2), + ct:fail("Didn't detect that option is a plain file", []) + end. + + +user_dir_option(Config) -> + DirUnread = proplists:get_value(unreadable_dir,Config), + FileRead = proplists:get_value(readable_file,Config), + %% Any port will do (beware, implementation knowledge!): + Port = 65535, + + case ssh:connect("localhost", Port, [{user_dir, DirUnread}]) of + {error,{eoptions,{{user_dir,DirUnread},eacces}}} -> + ok; + {error,econnrefused} -> + ct:fail("Didn't detect that dir is unreadable", []) + end, + + case ssh:connect("localhost", Port, [{user_dir, FileRead}]) of + {error,{eoptions,{{user_dir,FileRead},enotdir}}} -> + ok; + {error,econnrefused} -> + ct:fail("Didn't detect that option is a plain file", []) + end. + +%%-------------------------------------------------------------------- +%%% validate client that uses the 'ssh_msg_debug_fun' option +ssh_msg_debug_fun_option_client(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}]), + Parent = self(), + DbgFun = fun(ConnRef,Displ,Msg,Lang) -> Parent ! {msg_dbg,{ConnRef,Displ,Msg,Lang}} end, + + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {user_interaction, false}, + {ssh_msg_debug_fun,DbgFun}]), + %% Beware, implementation knowledge: + gen_fsm:send_all_state_event(ConnectionRef,{ssh_msg_debug,false,<<"Hello">>,<<>>}), + receive + {msg_dbg,X={ConnectionRef,false,<<"Hello">>,<<>>}} -> + ct:log("Got expected dbg msg ~p",[X]), + ssh:stop_daemon(Pid); + {msg_dbg,X={_,false,<<"Hello">>,<<>>}} -> + ct:log("Got dbg msg but bad ConnectionRef (~p expected) ~p",[ConnectionRef,X]), + ssh:stop_daemon(Pid), + {fail, "Bad ConnectionRef received"}; + {msg_dbg,X} -> + ct:log("Got bad dbg msg ~p",[X]), + ssh:stop_daemon(Pid), + {fail,"Bad msg received"} + after 1000 -> + ssh:stop_daemon(Pid), + {fail,timeout} + end. + +%%-------------------------------------------------------------------- +connectfun_disconnectfun_server(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + Parent = self(), + Ref = make_ref(), + ConnFun = fun(_,_,_) -> Parent ! {connect,Ref} end, + DiscFun = fun(R) -> Parent ! {disconnect,Ref,R} end, + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}, + {disconnectfun, DiscFun}, + {connectfun, ConnFun}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {user_interaction, false}]), + receive + {connect,Ref} -> + ssh:close(ConnectionRef), + receive + {disconnect,Ref,R} -> + ct:log("Disconnect result: ~p",[R]), + ssh:stop_daemon(Pid) + after 2000 -> + {fail, "No disconnectfun action"} + end + after 2000 -> + {fail, "No connectfun action"} + end. + +%%-------------------------------------------------------------------- +connectfun_disconnectfun_client(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + Parent = self(), + Ref = make_ref(), + DiscFun = fun(R) -> Parent ! {disconnect,Ref,R} end, + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}]), + _ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {disconnectfun, DiscFun}, + {user_interaction, false}]), + ssh:stop_daemon(Pid), + receive + {disconnect,Ref,R} -> + ct:log("Disconnect result: ~p",[R]) + after 2000 -> + {fail, "No disconnectfun action"} + end. + +%%-------------------------------------------------------------------- +%%% validate client that uses the 'ssh_msg_debug_fun' option +ssh_msg_debug_fun_option_server(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + Parent = self(), + DbgFun = fun(ConnRef,Displ,Msg,Lang) -> Parent ! {msg_dbg,{ConnRef,Displ,Msg,Lang}} end, + ConnFun = fun(_,_,_) -> Parent ! {connection_pid,self()} end, + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}, + {connectfun, ConnFun}, + {ssh_msg_debug_fun, DbgFun}]), + _ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {user_interaction, false}]), + receive + {connection_pid,Server} -> + %% Beware, implementation knowledge: + gen_fsm:send_all_state_event(Server,{ssh_msg_debug,false,<<"Hello">>,<<>>}), + receive + {msg_dbg,X={_,false,<<"Hello">>,<<>>}} -> + ct:log("Got expected dbg msg ~p",[X]), + ssh:stop_daemon(Pid); + {msg_dbg,X} -> + ct:log("Got bad dbg msg ~p",[X]), + ssh:stop_daemon(Pid), + {fail,"Bad msg received"} + after 3000 -> + ssh:stop_daemon(Pid), + {fail,timeout2} + end + after 3000 -> + ssh:stop_daemon(Pid), + {fail,timeout1} + end. + +%%-------------------------------------------------------------------- +disconnectfun_option_server(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + Parent = self(), + DisConnFun = fun(Reason) -> Parent ! {disconnect,Reason} end, + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}, + {disconnectfun, DisConnFun}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {user_interaction, false}]), + ssh:close(ConnectionRef), + receive + {disconnect,Reason} -> + ct:log("Server detected disconnect: ~p",[Reason]), + ssh:stop_daemon(Pid), + ok + after 3000 -> + receive + X -> ct:log("received ~p",[X]) + after 0 -> ok + end, + {fail,"Timeout waiting for disconnect"} + end. + +%%-------------------------------------------------------------------- +disconnectfun_option_client(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + Parent = self(), + DisConnFun = fun(Reason) -> Parent ! {disconnect,Reason} end, + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}]), + _ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {user_interaction, false}, + {disconnectfun, DisConnFun}]), + ssh:stop_daemon(Pid), + receive + {disconnect,Reason} -> + ct:log("Client detected disconnect: ~p",[Reason]), + ok + after 3000 -> + receive + X -> ct:log("received ~p",[X]) + after 0 -> ok + end, + {fail,"Timeout waiting for disconnect"} + end. + +%%-------------------------------------------------------------------- +unexpectedfun_option_server(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + Parent = self(), + ConnFun = fun(_,_,_) -> Parent ! {connection_pid,self()} end, + UnexpFun = fun(Msg,Peer) -> + Parent ! {unexpected,Msg,Peer,self()}, + skip + end, + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}, + {connectfun, ConnFun}, + {unexpectedfun, UnexpFun}]), + _ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {user_interaction, false}]), + receive + {connection_pid,Server} -> + %% Beware, implementation knowledge: + Server ! unexpected_message, + receive + {unexpected, unexpected_message, {{_,_,_,_},_}, _} -> ok; + {unexpected, unexpected_message, Peer, _} -> ct:fail("Bad peer ~p",[Peer]); + M = {unexpected, _, _, _} -> ct:fail("Bad msg ~p",[M]) + after 3000 -> + ssh:stop_daemon(Pid), + {fail,timeout2} + end + after 3000 -> + ssh:stop_daemon(Pid), + {fail,timeout1} + end. + +%%-------------------------------------------------------------------- +unexpectedfun_option_client(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + + Parent = self(), + UnexpFun = fun(Msg,Peer) -> + Parent ! {unexpected,Msg,Peer,self()}, + skip + end, + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_dir, UserDir}, + {user_interaction, false}, + {unexpectedfun, UnexpFun}]), + %% Beware, implementation knowledge: + ConnectionRef ! unexpected_message, + + receive + {unexpected, unexpected_message, {{_,_,_,_},_}, ConnectionRef} -> + ok; + {unexpected, unexpected_message, Peer, ConnectionRef} -> + ct:fail("Bad peer ~p",[Peer]); + M = {unexpected, _, _, _} -> + ct:fail("Bad msg ~p",[M]) + after 3000 -> + ssh:stop_daemon(Pid), + {fail,timeout} + end. + +%%-------------------------------------------------------------------- +%%% Test connect_timeout option in ssh:connect/4 +ssh_connect_timeout(_Config) -> + ConnTimeout = 2000, + {error,{faked_transport,connect,TimeoutToTransport}} = + ssh:connect("localhost", 12345, + [{transport,{tcp,?MODULE,tcp_closed}}, + {connect_timeout,ConnTimeout}], + 1000), + case TimeoutToTransport of + ConnTimeout -> ok; + Other -> + ct:log("connect_timeout is ~p but transport received ~p",[ConnTimeout,Other]), + {fail,"ssh:connect/4 wrong connect_timeout received in transport"} + end. + +%% Plugin function for the test above +connect(_Host, _Port, _Opts, Timeout) -> + {error, {faked_transport,connect,Timeout}}. + +%%-------------------------------------------------------------------- +%%% Test fourth argument in ssh:connect/4 +ssh_connect_arg4_timeout(_Config) -> + Timeout = 1000, + Parent = self(), + %% start the server + Server = spawn(fun() -> + {ok,Sl} = gen_tcp:listen(0,[]), + {ok,{_,Port}} = inet:sockname(Sl), + Parent ! {port,self(),Port}, + Rsa = gen_tcp:accept(Sl), + ct:log("Server gen_tcp:accept got ~p",[Rsa]), + receive after 2*Timeout -> ok end %% let client timeout first + end), + + %% Get listening port + Port = receive + {port,Server,ServerPort} -> ServerPort + end, + + %% try to connect with a timeout, but "supervise" it + Client = spawn(fun() -> + T0 = erlang:monotonic_time(), + Rc = ssh:connect("localhost",Port,[],Timeout), + ct:log("Client ssh:connect got ~p",[Rc]), + Parent ! {done,self(),Rc,T0} + end), + + %% Wait for client reaction on the connection try: + receive + {done, Client, {error,timeout}, T0} -> + Msp = ms_passed(T0), + exit(Server,hasta_la_vista___baby), + Low = 0.9*Timeout, + High = 2.5*Timeout, + ct:log("Timeout limits: ~.4f - ~.4f ms, timeout " + "was ~.4f ms, expected ~p ms",[Low,High,Msp,Timeout]), + if + Low ok; + true -> {fail, "timeout not within limits"} + end; + + {done, Client, {error,Other}, _T0} -> + ct:log("Error message \"~p\" from the client is unexpected.",[{error,Other}]), + {fail, "Unexpected error message"}; + + {done, Client, {ok,_Ref}, _T0} -> + {fail,"ssh-connected ???"} + after + 5000 -> + exit(Server,hasta_la_vista___baby), + exit(Client,hasta_la_vista___baby), + {fail, "Didn't timeout"} + end. + +%% Help function, elapsed milliseconds since T0 +ms_passed(T0) -> + %% OTP 18 + erlang:convert_time_unit(erlang:monotonic_time() - T0, + native, + micro_seconds) / 1000. + +%%-------------------------------------------------------------------- +ssh_daemon_minimal_remote_max_packet_size_option(Config) -> + SystemDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + + {Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{"vego", "morot"}]}, + {failfun, fun ssh_test_lib:failfun/2}, + {minimal_remote_max_packet_size, 14}]), + Conn = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}, + {user, "vego"}, + {password, "morot"}]), + + %% Try the limits of the minimal_remote_max_packet_size: + {ok, _ChannelId} = ssh_connection:session_channel(Conn, 100, 14, infinity), + {open_error,_,"Maximum packet size below 14 not supported",_} = + ssh_connection:session_channel(Conn, 100, 13, infinity), + + ssh:close(Conn), + ssh:stop_daemon(Server). + +%%-------------------------------------------------------------------- +%% This test try every algorithm by connecting to an Erlang server +id_string_no_opt_client(Config) -> + {Server, _Host, Port} = fake_daemon(Config), + {error,_} = ssh:connect("localhost", Port, [], 1000), + receive + {id,Server,"SSH-2.0-Erlang/"++Vsn} -> + true = expected_ssh_vsn(Vsn); + {id,Server,Other} -> + ct:fail("Unexpected id: ~s.",[Other]) + after 5000 -> + {fail,timeout} + end. + +%%-------------------------------------------------------------------- +id_string_own_string_client(Config) -> + {Server, _Host, Port} = fake_daemon(Config), + {error,_} = ssh:connect("localhost", Port, [{id_string,"Pelle"}], 1000), + receive + {id,Server,"SSH-2.0-Pelle\r\n"} -> + ok; + {id,Server,Other} -> + ct:fail("Unexpected id: ~s.",[Other]) + after 5000 -> + {fail,timeout} + end. + +%%-------------------------------------------------------------------- +id_string_random_client(Config) -> + {Server, _Host, Port} = fake_daemon(Config), + {error,_} = ssh:connect("localhost", Port, [{id_string,random}], 1000), + receive + {id,Server,Id="SSH-2.0-Erlang"++_} -> + ct:fail("Unexpected id: ~s.",[Id]); + {id,Server,Rnd="SSH-2.0-"++_} -> + ct:log("Got correct ~s",[Rnd]); + {id,Server,Id} -> + ct:fail("Unexpected id: ~s.",[Id]) + after 5000 -> + {fail,timeout} + end. + +%%-------------------------------------------------------------------- +id_string_no_opt_server(Config) -> + {_Server, Host, Port} = ssh_test_lib:std_daemon(Config, []), + {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), + {ok,"SSH-2.0-Erlang/"++Vsn} = gen_tcp:recv(S1, 0, 2000), + true = expected_ssh_vsn(Vsn). + +%%-------------------------------------------------------------------- +id_string_own_string_server(Config) -> + {_Server, Host, Port} = ssh_test_lib:std_daemon(Config, [{id_string,"Olle"}]), + {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), + {ok,"SSH-2.0-Olle\r\n"} = gen_tcp:recv(S1, 0, 2000). + +%%-------------------------------------------------------------------- +id_string_random_server(Config) -> + {_Server, Host, Port} = ssh_test_lib:std_daemon(Config, [{id_string,random}]), + {ok,S1}=gen_tcp:connect(Host,Port,[{active,false},{packet,line}]), + {ok,"SSH-2.0-"++Rnd} = gen_tcp:recv(S1, 0, 2000), + case Rnd of + "Erlang"++_ -> ct:log("Id=~p",[Rnd]), + {fail,got_default_id}; + "Olle\r\n" -> {fail,got_previous_tests_value}; + _ -> ct:log("Got ~s.",[Rnd]) + end. + +%%-------------------------------------------------------------------- +ssh_connect_negtimeout_parallel(Config) -> ssh_connect_negtimeout(Config,true). +ssh_connect_negtimeout_sequential(Config) -> ssh_connect_negtimeout(Config,false). + +ssh_connect_negtimeout(Config, Parallel) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + NegTimeOut = 2000, % ms + ct:log("Parallel: ~p",[Parallel]), + + {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, + {parallel_login, Parallel}, + {negotiation_timeout, NegTimeOut}, + {failfun, fun ssh_test_lib:failfun/2}]), + + {ok,Socket} = gen_tcp:connect(Host, Port, []), + + Factor = 2, + ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), + ct:sleep(round(Factor * NegTimeOut)), + + case inet:sockname(Socket) of + {ok,_} -> ct:fail("Socket not closed"); + {error,_} -> ok + end. + +%%-------------------------------------------------------------------- +%%% Test that ssh connection does not timeout if the connection is established (parallel) +ssh_connect_nonegtimeout_connected_parallel(Config) -> + ssh_connect_nonegtimeout_connected(Config, true). + +%%% Test that ssh connection does not timeout if the connection is established (non-parallel) +ssh_connect_nonegtimeout_connected_sequential(Config) -> + ssh_connect_nonegtimeout_connected(Config, false). + + +ssh_connect_nonegtimeout_connected(Config, Parallel) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + NegTimeOut = 20000, % ms + ct:log("Parallel: ~p",[Parallel]), + + {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, + {parallel_login, Parallel}, + {negotiation_timeout, NegTimeOut}, + {failfun, fun ssh_test_lib:failfun/2}]), + ct:log("~p Listen ~p:~p",[_Pid,_Host,Port]), + ct:sleep(500), + + IO = ssh_test_lib:start_io_server(), + Shell = ssh_test_lib:start_shell(Port, IO, UserDir), + receive + Error = {'EXIT', _, _} -> + ct:log("~p",[Error]), + ct:fail(no_ssh_connection); + ErlShellStart -> + ct:log("---Erlang shell start: ~p~n", [ErlShellStart]), + one_shell_op(IO, NegTimeOut), + one_shell_op(IO, NegTimeOut), + + Factor = 2, + ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]), + ct:sleep(round(Factor * NegTimeOut)), + + one_shell_op(IO, NegTimeOut) + end, + exit(Shell, kill). + + +one_shell_op(IO, TimeOut) -> + ct:log("One shell op: Waiting for prompter"), + receive + ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0]) + after TimeOut -> ct:fail("Timeout waiting for promter") + end, + + IO ! {input, self(), "2*3*7.\r\n"}, + receive + Echo0 -> ct:log("Echo: ~p ~n", [Echo0]) + after TimeOut -> ct:fail("Timeout waiting for echo") + end, + + receive + ?NEWLINE -> ct:log("NEWLINE received", []) + after TimeOut -> + receive Any1 -> ct:log("Bad NEWLINE: ~p",[Any1]) + after 0 -> ct:fail("Timeout waiting for NEWLINE") + end + end, + + receive + Result0 -> ct:log("Result: ~p~n", [Result0]) + after TimeOut -> ct:fail("Timeout waiting for result") + end. + +%%-------------------------------------------------------------------- +max_sessions_ssh_connect_parallel(Config) -> + max_sessions(Config, true, connect_fun(ssh__connect,Config)). +max_sessions_ssh_connect_sequential(Config) -> + max_sessions(Config, false, connect_fun(ssh__connect,Config)). + +max_sessions_sftp_start_channel_parallel(Config) -> + max_sessions(Config, true, connect_fun(ssh_sftp__start_channel, Config)). +max_sessions_sftp_start_channel_sequential(Config) -> + max_sessions(Config, false, connect_fun(ssh_sftp__start_channel, Config)). + + +%%%---- helpers: +connect_fun(ssh__connect, Config) -> + fun(Host,Port) -> + ssh_test_lib:connect(Host, Port, + [{silently_accept_hosts, true}, + {user_dir, ?config(priv_dir,Config)}, + {user_interaction, false}, + {user, "carni"}, + {password, "meat"} + ]) + %% ssh_test_lib returns R when ssh:connect returns {ok,R} + end; +connect_fun(ssh_sftp__start_channel, _Config) -> + fun(Host,Port) -> + {ok,_Pid,ConnRef} = + ssh_sftp:start_channel(Host, Port, + [{silently_accept_hosts, true}, + {user, "carni"}, + {password, "meat"} + ]), + ConnRef + end. + + +max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> + Connect = fun(Host,Port) -> + R = Connect0(Host,Port), + ct:log("Connect(~p,~p) -> ~p",[Host,Port,R]), + R + end, + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + MaxSessions = 5, + {Pid, Host, Port} = ssh_test_lib:daemon([ + {system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{"carni", "meat"}]}, + {parallel_login, ParallelLogin}, + {max_sessions, MaxSessions} + ]), + ct:log("~p Listen ~p:~p for max ~p sessions",[Pid,Host,Port,MaxSessions]), + try [Connect(Host,Port) || _ <- lists:seq(1,MaxSessions)] + of + Connections -> + %% Step 1 ok: could set up max_sessions connections + ct:log("Connections up: ~p",[Connections]), + [_|_] = Connections, + + %% Now try one more than alowed: + ct:log("Info Report might come here...",[]), + try Connect(Host,Port) + of + _ConnectionRef1 -> + ssh:stop_daemon(Pid), + {fail,"Too many connections accepted"} + catch + error:{badmatch,{error,"Connection closed"}} -> + %% Step 2 ok: could not set up max_sessions+1 connections + %% This is expected + %% Now stop one connection and try to open one more + ok = ssh:close(hd(Connections)), + receive after 250 -> ok end, % sleep so the supervisor has time to count down. Not nice... + try Connect(Host,Port) + of + _ConnectionRef1 -> + %% Step 3 ok: could set up one more connection after killing one + %% Thats good. + ssh:stop_daemon(Pid), + ok + catch + error:{badmatch,{error,"Connection closed"}} -> + %% Bad indeed. Could not set up one more connection even after killing + %% one existing. Very bad. + ssh:stop_daemon(Pid), + {fail,"Does not decrease # active sessions"} + end + end + catch + error:{badmatch,{error,"Connection closed"}} -> + ssh:stop_daemon(Pid), + {fail,"Too few connections accepted"} + end. + +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- + +expected_ssh_vsn(Str) -> + try + {ok,L} = application:get_all_key(ssh), + proplists:get_value(vsn,L,"")++"\r\n" + of + Str -> true; + "\r\n" -> true; + _ -> false + catch + _:_ -> true %% ssh not started so we dont't know + end. + + +fake_daemon(_Config) -> + Parent = self(), + %% start the server + Server = spawn(fun() -> + {ok,Sl} = gen_tcp:listen(0,[{packet,line}]), + {ok,{Host,Port}} = inet:sockname(Sl), + ct:log("fake_daemon listening on ~p:~p~n",[Host,Port]), + Parent ! {sockname,self(),Host,Port}, + Rsa = gen_tcp:accept(Sl), + ct:log("Server gen_tcp:accept got ~p",[Rsa]), + {ok,S} = Rsa, + receive + {tcp, S, Id} -> Parent ! {id,self(),Id} + end + end), + %% Get listening host and port + receive + {sockname,Server,ServerHost,ServerPort} -> {Server, ServerHost, ServerPort} + end. diff --git a/lib/ssh/test/ssh_options_SUITE_data/id_dsa b/lib/ssh/test/ssh_options_SUITE_data/id_dsa new file mode 100644 index 0000000000..d306f8b26e --- /dev/null +++ b/lib/ssh/test/ssh_options_SUITE_data/id_dsa @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ +APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod +/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP +kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW +JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD +OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt ++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e +uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX +Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE +ZU8w8Q+H7z0j+a+70x2iAw== +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_options_SUITE_data/id_rsa b/lib/ssh/test/ssh_options_SUITE_data/id_rsa new file mode 100644 index 0000000000..9d7e0dd5fb --- /dev/null +++ b/lib/ssh/test/ssh_options_SUITE_data/id_rsa @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU +DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl +zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB +AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V +TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3 +CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK +SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p +z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd +WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39 +sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3 +xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ +dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x +ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak= +-----END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..75d2025c71 --- /dev/null +++ b/lib/ssh/test/ssh_options_SUITE_data/ssh_host_rsa_key.pub @@ -0,0 +1,5 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8 +semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW +RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 132be3beb2..cf2df5028a 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -73,6 +73,9 @@ end_per_suite(Config) -> +init_per_testcase(no_common_alg_server_disconnects, Config) -> + start_std_daemon(Config, [{preferred_algorithms,[{public_key,['ssh-rsa']}]}]); + init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; TC == gex_client_init_default_exact ; TC == gex_client_init_option_groups ; @@ -93,6 +96,8 @@ init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; init_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). +end_per_testcase(no_common_alg_server_disconnects, Config) -> + stop_std_daemon(Config); end_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; TC == gex_client_init_default_exact ; TC == gex_client_init_option_groups ; @@ -101,7 +106,6 @@ end_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; end_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). - %%%-------------------------------------------------------------------- %%% Test Cases -------------------------------------------------------- %%%-------------------------------------------------------------------- @@ -412,8 +416,9 @@ start_std_daemon(Config, ExtraOpts) -> UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth file:make_dir(UserDir), UserPasswords = [{"user1","pwd1"}], - Options = [{system_dir, system_dir(Config)}, - {user_dir, user_dir(Config)}, + Options = [%%{preferred_algorithms,[{public_key,['ssh-rsa']}]}, %% For some test cases + {system_dir, system_dir(Config)}, + {user_dir, UserDir}, {user_passwords, UserPasswords}, {failfun, fun ssh_test_lib:failfun/2} | ExtraOpts], diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl new file mode 100644 index 0000000000..9daa6efc02 --- /dev/null +++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl @@ -0,0 +1,223 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(ssh_renegotiate_SUITE). + +-include_lib("common_test/include/ct.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-define(REKEY_DATA_TMO, 65000). +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> [rekey, rekey_limit, renegotiate1, renegotiate2]. + +groups() -> []. + +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + catch crypto:stop(), + case catch crypto:start() of + ok -> + Config; + _Else -> + {skip, "Crypto could not be started!"} + end. +end_per_suite(_Config) -> + ssh:stop(), + crypto:stop(). + +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + ssh:start(), + Config. + +end_per_testcase(_TestCase, _Config) -> + ssh:stop(), + ok. + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- + +%%% Idle timeout test + +rekey(Config) -> + {Pid, Host, Port} = + ssh_test_lib:std_daemon(Config, + [{rekey_limit, 0}]), + ConnectionRef = + ssh_test_lib:std_connect(Config, Host, Port, + [{rekey_limit, 0}]), + Kex1 = get_kex_init(ConnectionRef), + receive + after ?REKEY_DATA_TMO -> + %%By this time rekeying would have been done + Kex2 = get_kex_init(ConnectionRef), + false = (Kex2 == Kex1), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid) + end. + +%%-------------------------------------------------------------------- + +%%% Test rekeying by data volume + +rekey_limit(Config) -> + UserDir = ?config(priv_dir, Config), + DataFile = filename:join(UserDir, "rekey.data"), + + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[]), + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 4500}]), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + Kex1 = get_kex_init(ConnectionRef), + + timer:sleep(?REKEY_DATA_TMO), + Kex1 = get_kex_init(ConnectionRef), + + Data = lists:duplicate(159000,1), + ok = ssh_sftp:write_file(SftpPid, DataFile, Data), + + timer:sleep(?REKEY_DATA_TMO), + Kex2 = get_kex_init(ConnectionRef), + + false = (Kex2 == Kex1), + + timer:sleep(?REKEY_DATA_TMO), + Kex2 = get_kex_init(ConnectionRef), + + ok = ssh_sftp:write_file(SftpPid, DataFile, "hi\n"), + + timer:sleep(?REKEY_DATA_TMO), + Kex2 = get_kex_init(ConnectionRef), + + false = (Kex2 == Kex1), + + timer:sleep(?REKEY_DATA_TMO), + Kex2 = get_kex_init(ConnectionRef), + + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- + +%%% Test rekeying with simulataneous send request + +renegotiate1(Config) -> + UserDir = ?config(priv_dir, Config), + DataFile = filename:join(UserDir, "renegotiate1.data"), + + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + + RPort = ssh_test_lib:inet_port(), + {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), + + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + Kex1 = get_kex_init(ConnectionRef), + + {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), + + ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), + + ssh_relay:hold(RelayPid, rx, 20, 1000), + ssh_connection_handler:renegotiate(ConnectionRef), + spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), + + timer:sleep(2000), + + Kex2 = get_kex_init(ConnectionRef), + + false = (Kex2 == Kex1), + + ssh_relay:stop(RelayPid), + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- + +%%% Test rekeying with inflight messages from peer + +renegotiate2(Config) -> + UserDir = ?config(priv_dir, Config), + DataFile = filename:join(UserDir, "renegotiate2.data"), + + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + + RPort = ssh_test_lib:inet_port(), + {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), + + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), + + Kex1 = get_kex_init(ConnectionRef), + + {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]), + + ok = ssh_sftp:write(SftpPid, Handle, "hi\n"), + + ssh_relay:hold(RelayPid, rx, 20, infinity), + spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end), + %% need a small pause here to ensure ssh_sftp:write is executed + ct:sleep(10), + ssh_connection_handler:renegotiate(ConnectionRef), + ssh_relay:release(RelayPid, rx), + + timer:sleep(2000), + + Kex2 = get_kex_init(ConnectionRef), + + false = (Kex2 == Kex1), + + ssh_relay:stop(RelayPid), + ssh_sftp:stop_channel(SftpPid), + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- +%% get_kex_init - helper function to get key_exchange_init_msg +get_kex_init(Conn) -> + %% First, validate the key exchange is complete (StateName == connected) + {connected,S} = sys:get_state(Conn), + %% Next, walk through the elements of the #state record looking + %% for the #ssh_msg_kexinit record. This method is robust against + %% changes to either record. The KEXINIT message contains a cookie + %% unique to each invocation of the key exchange procedure (RFC4253) + SL = tuple_to_list(S), + case lists:keyfind(ssh_msg_kexinit, 1, SL) of + false -> + throw(not_found); + KexInit -> + KexInit + end. + diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa new file mode 100644 index 0000000000..d306f8b26e --- /dev/null +++ b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ +APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod +/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP +kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW +JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD +OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt ++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e +uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX +Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE +ZU8w8Q+H7z0j+a+70x2iAw== +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa new file mode 100644 index 0000000000..9d7e0dd5fb --- /dev/null +++ b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU +DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl +zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB +AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V +TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3 +CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK +SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p +z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd +WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39 +sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3 +xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ +dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x +ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak= +-----END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..75d2025c71 --- /dev/null +++ b/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub @@ -0,0 +1,5 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8 +semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW +RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 8d0b887d83..32fdec9842 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -27,7 +27,7 @@ -include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/file.hrl"). -% Default timetrap timeout + % Default timetrap timeout -define(default_timeout, ?t:minutes(1)). %%-------------------------------------------------------------------- @@ -64,19 +64,11 @@ end_per_suite(Config) -> groups() -> [{not_unicode, [], [{group,erlang_server}, {group,openssh_server}, - {group,'diffie-hellman-group-exchange-sha1'}, - {group,'diffie-hellman-group-exchange-sha256'}, sftp_nonexistent_subsystem]}, {unicode, [], [{group,erlang_server}, {group,openssh_server}, sftp_nonexistent_subsystem]}, - - {'diffie-hellman-group-exchange-sha1', [], [{group,erlang_server}, - {group,openssh_server}]}, - - {'diffie-hellman-group-exchange-sha256', [], [{group,erlang_server}, - {group,openssh_server}]}, {erlang_server, [], [{group,write_read_tests}, version_option, @@ -159,7 +151,7 @@ init_per_group(unicode, Config) -> _ -> {skip, "Not unicode file encoding"} end; - + init_per_group(erlang_server, Config) -> ct:comment("Begin ~p",[grps(Config)]), PrivDir = ?config(priv_dir, Config), @@ -167,20 +159,18 @@ init_per_group(erlang_server, Config) -> User = ?config(user, Config), Passwd = ?config(passwd, Config), Sftpd = {_, HostX, PortX} = - ssh_test_lib:daemon(extra_opts(Config) ++ - [{system_dir, SysDir}, - {user_dir, PrivDir}, - {user_passwords, - [{User, Passwd}]}]), + ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, PrivDir}, + {user_passwords, + [{User, Passwd}]}]), [{peer, {fmt_host(HostX),PortX}}, {group, erlang_server}, {sftpd, Sftpd} | Config]; init_per_group(openssh_server, Config) -> ct:comment("Begin ~p",[grps(Config)]), Host = ssh_test_lib:hostname(), case (catch ssh_sftp:start_channel(Host, - extra_opts(Config) ++ - [{user_interaction, false}, - {silently_accept_hosts, true}])) of + [{user_interaction, false}, + {silently_accept_hosts, true}])) of {ok, _ChannelPid, Connection} -> [{peer, {_HostName,{IPx,Portx}}}] = ssh:connection_info(Connection,[peer]), ssh:close(Connection), @@ -201,11 +191,10 @@ init_per_group(remote_tar, Config) -> case ?config(group, Config) of erlang_server -> ssh:connect(Host, Port, - extra_opts(Config) ++ - [{user, User}, - {password, Passwd}, - {user_interaction, false}, - {silently_accept_hosts, true}]); + [{user, User}, + {password, Passwd}, + {user_interaction, false}, + {silently_accept_hosts, true}]); openssh_server -> ssh:connect(Host, Port, [{user_interaction, false}, @@ -214,28 +203,6 @@ init_per_group(remote_tar, Config) -> [{remote_tar, true}, {connection, Connection} | Config]; -init_per_group('diffie-hellman-group-exchange-sha1', Config) -> - case lists:member('diffie-hellman-group-exchange-sha1', - ssh_transport:supported_algorithms(kex)) of - true -> - [{extra_opts, [{preferred_algorithms, [{kex,['diffie-hellman-group-exchange-sha1']}]}]} - | Config]; - - false -> - {skip,"'diffie-hellman-group-exchange-sha1' not supported by this version of erlang ssh"} - end; - -init_per_group('diffie-hellman-group-exchange-sha256', Config) -> - case lists:member('diffie-hellman-group-exchange-sha256', - ssh_transport:supported_algorithms(kex)) of - true -> - [{extra_opts, [{preferred_algorithms, [{kex,['diffie-hellman-group-exchange-sha256']}]}]} - | Config]; - - false -> - {skip,"'diffie-hellman-group-exchange-sha256' not supported by this version of erlang ssh"} - end; - init_per_group(write_read_tests, Config) -> ct:comment("Begin ~p",[grps(Config)]), Config. @@ -278,12 +245,11 @@ init_per_testcase(version_option, Config) -> Passwd = ?config(passwd, Config), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, Port, - extra_opts(Config) ++ - [{sftp_vsn, 3}, - {user, User}, - {password, Passwd}, - {user_interaction, false}, - {silently_accept_hosts, true}]), + [{sftp_vsn, 3}, + {user, User}, + {password, Passwd}, + {user_interaction, false}, + {silently_accept_hosts, true}]), Sftp = {ChannelPid, Connection}, [{sftp,Sftp}, {watchdog, Dog} | TmpConfig]; @@ -301,11 +267,10 @@ init_per_testcase(Case, Config0) -> {_,Host, Port} = ?config(sftpd, Config2), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, Port, - extra_opts(Config2) ++ - [{user, User}, - {password, Passwd}, - {user_interaction, false}, - {silently_accept_hosts, true}] + [{user, User}, + {password, Passwd}, + {user_interaction, false}, + {silently_accept_hosts, true}] ), Sftp = {ChannelPid, Connection}, [{sftp, Sftp}, {watchdog, Dog} | Config2]; @@ -315,9 +280,8 @@ init_per_testcase(Case, Config0) -> Host = ssh_test_lib:hostname(), {ok, ChannelPid, Connection} = ssh_sftp:start_channel(Host, - extra_opts(Config2) ++ - [{user_interaction, false}, - {silently_accept_hosts, true}]), + [{user_interaction, false}, + {silently_accept_hosts, true}]), Sftp = {ChannelPid, Connection}, [{sftp, Sftp}, {watchdog, Dog} | Config2] end, @@ -494,7 +458,7 @@ mk_rm_dir() -> mk_rm_dir(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), {Sftp, _} = ?config(sftp, Config), - + DirName = filename:join(PrivDir, "test"), ok = ssh_sftp:make_dir(Sftp, DirName), ok = ssh_sftp:del_dir(Sftp, DirName), @@ -767,7 +731,7 @@ directory_to_tar(Config) -> ok = erl_tar:add(Handle, fn("d1",Config), "d1", [verbose]), ok = erl_tar:close(Handle), chk_tar(["d1"], Config). - + %%-------------------------------------------------------------------- binaries_to_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), @@ -831,9 +795,9 @@ simple_crypto_tar_big(Config) -> chk_tar([{"b1",Bin}, F1, "big.txt"], Config, [{crypto,{Cinit,Cdec}}]). stuff(Bin) -> << <> || <> <= Bin >>. - + unstuff(Bin) -> << <> || <> <= Bin >>. - + %%-------------------------------------------------------------------- read_tar(Config) -> ChPid2 = ?config(channel_pid2, Config), @@ -1002,9 +966,6 @@ prep(Config) -> ok = file:write_file_info(TestFile, FileInfo#file_info{mode = Mode}). -extra_opts(Config) -> - proplists:get_value(extra_opts, Config, []). - chk_tar(Items, Config) -> chk_tar(Items, Config, []). @@ -1041,7 +1002,7 @@ analyze_report([E={NameE,BinE}|Es], [A={NameA,BinA}|As]) -> NameE < NameA -> [["Component ",NameE," is missing.\n\n"] | analyze_report(Es,[A|As])]; - + NameE > NameA -> [["Component ",NameA," is not expected.\n\n"] | analyze_report([E|Es],As)]; @@ -1054,7 +1015,7 @@ analyze_report([], [{NameA,_BinA}|As]) -> [["Component ",NameA," not expected.\n\n"] | analyze_report([],As)]; analyze_report([], []) -> "". - + tar_size(TarFileName, Config) -> {ChPid,_} = ?config(sftp,Config), {ok,Data} = ssh_sftp:read_file(ChPid, TarFileName), @@ -1088,4 +1049,4 @@ fn(Name, Config) -> fmt_host({A,B,C,D}) -> lists:concat([A,".",B,".",C,".",D]); fmt_host(S) -> S. - + diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 988ea47bd8..6d568125bb 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -27,6 +27,8 @@ -include_lib("public_key/include/public_key.hrl"). -include_lib("common_test/include/ct.hrl"). +-include_lib("ssh/src/ssh_transport.hrl"). + -define(TIMEOUT, 50000). @@ -65,6 +67,55 @@ daemon(Host, Port, Options) -> end. +std_daemon(Config, ExtraOpts) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + std_daemon1(Config, + ExtraOpts ++ + [{user_dir, UserDir}, + {user_passwords, [{"usr1","pwd1"}]}]). + +std_daemon1(Config, ExtraOpts) -> + SystemDir = ?config(data_dir, Config), + {_Server, _Host, _Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {failfun, fun ssh_test_lib:failfun/2} + | ExtraOpts]). + +std_connect(Config, Host, Port, ExtraOpts) -> + UserDir = ?config(priv_dir, Config), + _ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user, "usr1"}, + {password, "pwd1"}, + {user_interaction, false} + | ExtraOpts]). + +std_simple_sftp(Host, Port, Config) -> + UserDir = ?config(priv_dir, Config), + DataFile = filename:join(UserDir, "test.data"), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, []), + {ok, ChannelRef} = ssh_sftp:start_channel(ConnectionRef), + Data = crypto:rand_bytes(proplists:get_value(std_simple_sftp_size,Config,10)), + ok = ssh_sftp:write_file(ChannelRef, DataFile, Data), + {ok,ReadData} = file:read_file(DataFile), + ok = ssh:close(ConnectionRef), + Data == ReadData. + +std_simple_exec(Host, Port, Config) -> + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, []), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, "23+21-2.", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"42\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ok; + Other -> + ct:fail(Other) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId). + start_shell(Port, IOServer, UserDir) -> start_shell(Port, IOServer, UserDir, []). @@ -372,3 +423,133 @@ openssh_sanity_check(Config) -> ssh:stop(), {skip, Str} end. + +%%-------------------------------------------------------------------- +%% Check if we have a "newer" ssh client that supports these test cases + +ssh_client_supports_Q() -> + ErlPort = open_port({spawn, "ssh -Q cipher"}, [exit_status, stderr_to_stdout]), + 0 == check_ssh_client_support2(ErlPort). + +check_ssh_client_support2(P) -> + receive + {P, {data, _A}} -> + check_ssh_client_support2(P); + {P, {exit_status, E}} -> + E + after 5000 -> + + ct:log("Openssh command timed out ~n"), + -1 + end. + +default_algorithms(Host, Port) -> + KexInitPattern = + #ssh_msg_kexinit{ + kex_algorithms = '$kex_algorithms', + server_host_key_algorithms = '$server_host_key_algorithms', + encryption_algorithms_client_to_server = '$encryption_algorithms_client_to_server', + encryption_algorithms_server_to_client = '$encryption_algorithms_server_to_client', + mac_algorithms_client_to_server = '$mac_algorithms_client_to_server', + mac_algorithms_server_to_client = '$mac_algorithms_server_to_client', + compression_algorithms_client_to_server = '$compression_algorithms_client_to_server', + compression_algorithms_server_to_client = '$compression_algorithms_server_to_client', + _ = '_' + }, + + try ssh_trpt_test_lib:exec( + [{connect,Host,Port, [{silently_accept_hosts, true}, + {user_interaction, false}]}, + {send,hello}, + receive_hello, + {send, ssh_msg_kexinit}, + {match, KexInitPattern, receive_msg}, + close_socket]) + of + {ok,E} -> + [Kex, PubKey, EncC2S, EncS2C, MacC2S, MacS2C, CompC2S, CompS2C] = + ssh_trpt_test_lib:instantiate(['$kex_algorithms', + '$server_host_key_algorithms', + '$encryption_algorithms_client_to_server', + '$encryption_algorithms_server_to_client', + '$mac_algorithms_client_to_server', + '$mac_algorithms_server_to_client', + '$compression_algorithms_client_to_server', + '$compression_algorithms_server_to_client' + ], E), + [{kex, to_atoms(Kex)}, + {public_key, to_atoms(PubKey)}, + {cipher, [{client2server, to_atoms(EncC2S)}, + {server2client, to_atoms(EncS2C)}]}, + {mac, [{client2server, to_atoms(MacC2S)}, + {server2client, to_atoms(MacS2C)}]}, + {compression, [{client2server, to_atoms(CompC2S)}, + {server2client, to_atoms(CompS2C)}]}]; + _ -> + [] + catch + _:_ -> + [] + end. + + +default_algorithms(sshd) -> + default_algorithms("localhost", 22); +default_algorithms(sshc) -> + case os:find_executable("ssh") of + false -> + []; + _ -> + Cipher = sshc(cipher), + Mac = sshc(mac), + [{kex, sshc(kex)}, + {public_key, sshc(key)}, + {cipher, [{client2server, Cipher}, + {server2client, Cipher}]}, + {mac, [{client2server, Mac}, + {server2client, Mac}]} + ] + end. + +sshc(Tag) -> + to_atoms( + string:tokens(os:cmd(lists:concat(["ssh -Q ",Tag])), "\n") + ). + +ssh_type() -> + case os:find_executable("ssh") of + false -> not_found; + _ -> + case os:cmd("ssh -V") of + "OpenSSH" ++ _ -> + openSSH; + Str -> + ct:log("ssh client ~p is unknown",[Str]), + unknown + end + end. + +algo_intersection([], _) -> []; +algo_intersection(_, []) -> []; +algo_intersection(L1=[A1|_], L2=[A2|_]) when is_atom(A1), is_atom(A2) -> + true = lists:all(fun erlang:is_atom/1, L1++L2), + lists:foldr(fun(A,Acc) -> + case lists:member(A,L2) of + true -> [A|Acc]; + false -> Acc + end + end, [], L1); +algo_intersection([{K,V1}|T1], L2) -> + case lists:keysearch(K,1,L2) of + {value, {K,V2}} -> + [{K,algo_intersection(V1,V2)} | algo_intersection(T1,L2)]; + false -> + algo_intersection(T1,L2) + end; +algo_intersection(_, _) -> + []. + + +to_atoms(L) -> lists:map(fun erlang:list_to_atom/1, L). + + diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 663168b169..104c1f9107 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -85,6 +85,11 @@ init_per_group(erlang_server, Config) -> UserDir = ?config(priv_dir, Config), ssh_test_lib:setup_dsa_known_host(DataDir, UserDir), Config; +init_per_group(erlang_client, Config) -> + CommonAlgs = ssh_test_lib:algo_intersection( + ssh:default_algorithms(), + ssh_test_lib:default_algorithms("localhost", 22)), + [{common_algs,CommonAlgs} | Config]; init_per_group(_, Config) -> Config. @@ -201,43 +206,49 @@ erlang_client_openssh_server_kexs() -> [{doc, "Test that we can connect with different KEXs."}]. erlang_client_openssh_server_kexs(Config) when is_list(Config) -> - Success = - lists:foldl( - fun(Kex, Acc) -> - ct:log("============= ~p ============= ~p",[Kex,Acc]), - ConnectionRef = - ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user_interaction, false}, - {preferred_algorithms, - [{kex,[Kex]}]}]), - - {ok, ChannelId} = - ssh_connection:session_channel(ConnectionRef, infinity), - success = - ssh_connection:exec(ConnectionRef, ChannelId, - "echo testing", infinity), - - ExpectedData = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, - case ssh_test_lib:receive_exec_result(ExpectedData) of - expected -> - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), - Acc; - {unexpected_msg,{ssh_cm, ConnectionRef, - {exit_status, ChannelId, 0}} = ExitStatus} -> - ct:log("0: Collected data ~p", [ExitStatus]), - ssh_test_lib:receive_exec_result(ExpectedData, ConnectionRef, ChannelId), - Acc; - Other -> - ct:log("~p failed: ~p",[Kex,Other]), - [Kex|Acc] - end - end, [], ssh_transport:supported_algorithms(kex)), - case Success of - [] -> - ok; - BadKex -> - ct:log("Bad kex algos: ~p",[BadKex]), - {fail, "Kex failed for one or more algos"} + KexAlgos = try proplists:get_value(kex, ?config(common_algs,Config)) + catch _:_ -> [] + end, + comment(KexAlgos), + case KexAlgos of + [] -> {skip, "No common kex algorithms"}; + _ -> + Success = + lists:foldl( + fun(Kex, Acc) -> + ConnectionRef = + ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}, + {preferred_algorithms, + [{kex,[Kex]}]}]), + + {ok, ChannelId} = + ssh_connection:session_channel(ConnectionRef, infinity), + success = + ssh_connection:exec(ConnectionRef, ChannelId, + "echo testing", infinity), + + ExpectedData = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, + case ssh_test_lib:receive_exec_result(ExpectedData) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + Acc; + {unexpected_msg,{ssh_cm, ConnectionRef, + {exit_status, ChannelId, 0}} = ExitStatus} -> + ct:log("0: Collected data ~p", [ExitStatus]), + ssh_test_lib:receive_exec_result(ExpectedData, ConnectionRef, ChannelId), + Acc; + Other -> + ct:log("~p failed: ~p",[Kex,Other]), + false + end + end, true, KexAlgos), + case Success of + true -> + ok; + false -> + {fail, "Kex failed for one or more algos"} + end end. %%-------------------------------------------------------------------- @@ -283,45 +294,37 @@ erlang_server_openssh_client_cipher_suites(Config) when is_list(Config) -> {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {failfun, fun ssh_test_lib:failfun/2}]), - ct:sleep(500), - Supports = crypto:supports(), - Ciphers = proplists:get_value(ciphers, Supports), - Tests = [ - {"3des-cbc", lists:member(des3_cbc, Ciphers)}, - {"aes128-cbc", lists:member(aes_cbc128, Ciphers)}, - {"aes128-ctr", lists:member(aes_ctr, Ciphers)}, - {"aes256-cbc", false} - ], - lists:foreach(fun({Cipher, Expect}) -> - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++ - " -c " ++ Cipher ++ " 1+1.", - - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - case Expect of - true -> - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive answer") - end; - false -> - receive - {SshPort,{data, <<"no matching cipher found", _/binary>>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive no matching cipher message") - end - end - end, Tests), - - ssh:stop_daemon(Pid). + OpenSshCiphers = + ssh_test_lib:to_atoms( + string:tokens(os:cmd("ssh -Q cipher"), "\n")), + ErlCiphers = + proplists:get_value(client2server, + proplists:get_value(cipher, ssh:default_algorithms())), + CommonCiphers = + ssh_test_lib:algo_intersection(ErlCiphers, OpenSshCiphers), + + comment(CommonCiphers), + + lists:foreach( + fun(Cipher) -> + Cmd = lists:concat(["ssh -p ",Port, + " -o UserKnownHostsFile=",KnownHosts," ",Host," ", + " -c ",Cipher," 1+1."]), + ct:log("Cmd: ~p~n", [Cmd]), + + SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), + + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + ct:fail("~p Did not receive answer",[Cipher]) + end + end, CommonCiphers), + + ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- erlang_server_openssh_client_macs() -> @@ -333,45 +336,40 @@ erlang_server_openssh_client_macs(Config) when is_list(Config) -> KnownHosts = filename:join(PrivDir, "known_hosts"), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), + {failfun, fun ssh_test_lib:failfun/2}]), ct:sleep(500), - Supports = crypto:supports(), - Hashs = proplists:get_value(hashs, Supports), - MACs = [{"hmac-sha1", lists:member(sha, Hashs)}, - {"hmac-sha2-256", lists:member(sha256, Hashs)}, - {"hmac-md5-96", false}, - {"hmac-ripemd160", false}], - lists:foreach(fun({MAC, Expect}) -> - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++ - " -o MACs=" ++ MAC ++ " 1+1.", - - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - case Expect of - true -> - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive answer") - end; - false -> - receive - {SshPort,{data, <<"no matching mac found", _/binary>>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive no matching mac message") - end - end - end, MACs), + OpenSshMacs = + ssh_test_lib:to_atoms( + string:tokens(os:cmd("ssh -Q mac"), "\n")), + ErlMacs = + proplists:get_value(client2server, + proplists:get_value(mac, ssh:default_algorithms())), + CommonMacs = + ssh_test_lib:algo_intersection(ErlMacs, OpenSshMacs), + + comment(CommonMacs), + + lists:foreach( + fun(MAC) -> + Cmd = lists:concat(["ssh -p ",Port, + " -o UserKnownHostsFile=",KnownHosts," ",Host," ", + " -o MACs=",MAC," 1+1."]), + ct:log("Cmd: ~p~n", [Cmd]), + + SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), + + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + ct:fail("~p Did not receive answer",[MAC]) + end + end, CommonMacs), - ssh:stop_daemon(Pid). + ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- erlang_server_openssh_client_kexs() -> @@ -389,54 +387,34 @@ erlang_server_openssh_client_kexs(Config) when is_list(Config) -> ]), ct:sleep(500), - ErlKexs = lists:map(fun erlang:atom_to_list/1, - ssh_transport:supported_algorithms(kex)), - OpenSshKexs = string:tokens(os:cmd("ssh -Q kex"), "\n"), - - Kexs = [{OpenSshKex,lists:member(OpenSshKex,ErlKexs)} - || OpenSshKex <- OpenSshKexs], - - Success = - lists:foldl( - fun({Kex, Expect}, Acc) -> - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++ - " -o KexAlgorithms=" ++ Kex ++ " 1+1.", - - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - case Expect of - true -> - receive - {SshPort,{data, <<"2\n">>}} -> - Acc - after ?TIMEOUT -> - ct:log("Did not receive answer for ~p",[Kex]), - [Kex|Acc] - end; - false -> - receive - {SshPort,{data, <<"Unable to negotiate a key exchange method", _/binary>>}} -> - Acc - after ?TIMEOUT -> - ct:log("Did not receive no matching kex message for ~p",[Kex]), - [Kex|Acc] - end - end - end, [], Kexs), + OpenSshKexs = + ssh_test_lib:to_atoms( + string:tokens(os:cmd("ssh -Q kex"), "\n")), + ErlKexs = + proplists:get_value(kex, ssh:default_algorithms()), + CommonKexs = + ssh_test_lib:algo_intersection(ErlKexs, OpenSshKexs), + + comment(CommonKexs), + + lists:foreach( + fun(Kex) -> + Cmd = lists:concat(["ssh -p ",Port, + " -o UserKnownHostsFile=",KnownHosts," ",Host," ", + " -o KexAlgorithms=",Kex," 1+1."]), + ct:log("Cmd: ~p~n", [Cmd]), + + SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), + + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + ct:log("~p Did not receive answer",[Kex]) + end + end, CommonKexs), - ssh:stop_daemon(Pid), - - case Success of - [] -> - ok; - BadKex -> - ct:log("Bad kex algos: ~p",[BadKex]), - {fail, "Kex failed for one or more algos"} - end. - + ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- erlang_server_openssh_client_exec_compressed() -> @@ -697,27 +675,18 @@ extra_logout() -> ok end. -%%-------------------------------------------------------------------- %%-------------------------------------------------------------------- %% Check if we have a "newer" ssh client that supports these test cases -%%-------------------------------------------------------------------- check_ssh_client_support(Config) -> - Port = open_port({spawn, "ssh -Q cipher"}, [exit_status, stderr_to_stdout]), - case check_ssh_client_support2(Port) of - 0 -> % exit status from command (0 == ok) + case ssh_test_lib:ssh_client_supports_Q() of + true -> ssh:start(), Config; _ -> {skip, "test case not supported by ssh client"} end. -check_ssh_client_support2(P) -> - receive - {P, {data, _A}} -> - check_ssh_client_support2(P); - {P, {exit_status, E}} -> - E - after 5000 -> - ct:log("Openssh command timed out ~n"), - -1 - end. +comment(AtomList) -> + ct:comment( + string:join(lists:map(fun erlang:atom_to_list/1, AtomList), + ", ")). diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 66df890f5c..caf9bac3b6 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -23,6 +23,7 @@ %%-compile(export_all). -export([exec/1, exec/2, + instantiate/2, format_msg/1, server_host_port/1 ] -- cgit v1.2.3 From 95de23a194ccb1603132d3a3baafa66385320559 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 17 Aug 2015 22:25:29 +0200 Subject: ssh: dh_gex defautl values increased. Groups added --- lib/ssh/src/ssh_transport.erl | 12 ++++-------- lib/ssh/src/ssh_transport.hrl | 38 +++++++++++++++++++++++++++---------- lib/ssh/test/ssh_protocol_SUITE.erl | 8 +++++--- 3 files changed, 37 insertions(+), 21 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 1914b223bc..2b6f0a3cdc 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1340,14 +1340,10 @@ peer_name({Host, _}) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -dh_group('diffie-hellman-group1-sha1') -> ?dh_group1; -dh_group('diffie-hellman-group14-sha1') -> ?dh_group14. - -dh_gex_default_groups() -> - [{1024, ?dh_group1 }, - {2048, ?dh_group14}, - {3072, ?dh_group15}, - {4096, ?dh_group16}]. +dh_group('diffie-hellman-group1-sha1') -> element(2, ?dh_group1); +dh_group('diffie-hellman-group14-sha1') -> element(2, ?dh_group14). + +dh_gex_default_groups() -> ?dh_default_groups. dh_gex_group(Min, N, Max, undefined) -> diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 0bc6b7953b..d962b1111f 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -32,10 +32,9 @@ -define(MAX_NUM_ALGORITHMS, 100). --define(DEFAULT_DH_GROUP_MIN, 512). --define(DEFAULT_DH_GROUP_NBITS, 1024). --define(DEFAULT_DH_GROUP_MAX, 4096). - +-define(DEFAULT_DH_GROUP_MIN, 1024). +-define(DEFAULT_DH_GROUP_NBITS, 6144). +-define(DEFAULT_DH_GROUP_MAX, 8192). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% @@ -114,6 +113,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% diffie-hellman-group1-sha1 | diffie-hellman-group14-sha1 + -define(SSH_MSG_KEXDH_INIT, 30). -define(SSH_MSG_KEXDH_REPLY, 31). @@ -230,20 +230,38 @@ %%% rfc 2489, ch 6.2 -define(dh_group1, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}). + {1024, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}}). %%% rfc 3526, ch3 -define(dh_group14, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}). + {2048, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}}). %%% rfc 3526, ch4 -define(dh_group15, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}). + {3072, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}}). %%% rfc 3526, ch5 -define(dh_group16, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}). - - + {4096, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}}). + +%%% rfc 3526, ch6 +-define(dh_group17, + {6144, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF}}). + +%%% rfc 3526, ch7 +-define(dh_group18, + {8192, + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF}}). + +-define(dh_default_groups, [?dh_group14, + ?dh_group15, + ?dh_group16, + ?dh_group17, + ?dh_group18] ). -endif. % -ifdef(ssh_transport). diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index cf2df5028a..d8e99799e2 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -343,13 +343,15 @@ gex_client_init_default_exact(Config) -> gex_client_init_option_groups(Config) -> - do_gex_client_init(Config, {2000, 2048, 4000}, {3,41}). + do_gex_client_init(Config, {2000, 2048, 4000}, + {'n/a',{3,41}}). gex_client_init_option_groups_file(Config) -> - do_gex_client_init(Config, {2000, 2048, 4000}, {5,61}). + do_gex_client_init(Config, {2000, 2048, 4000}, + {'n/a',{5,61}}). -do_gex_client_init(Config, {Min,N,Max}, {G,P}) -> +do_gex_client_init(Config, {Min,N,Max}, {_,{G,P}}) -> {ok,_} = ssh_trpt_test_lib:exec( [{set_options, [print_ops, print_seqnums, print_messages]}, -- cgit v1.2.3 From 6e3a0870ebd992ed410298e859066894134be9f6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 31 Aug 2015 16:56:02 +0200 Subject: erts,hipe,dialyzer: Fix hipe checkum of target runtime system Main problem: A faulty HIPE_LITERAL_CRC was not detected by the loader. Strangeness #1: Dialyzer should ask the hipe compiler about the target checksum, not an internal bif. Strangeness #2: The HIPE_SYSTEM_CRC checksum was based on the HIPE_LITERALS_CRC checksum. Solution: New HIPE_ERTS_CHECKSUM which is an bxor of the two (now independent) HIPE_LITERALS_CRC and HIPE_SYSTEM_CRC. HIPE_LITERALS_CRC represents values that are assumed to stay constant for different VM configurations of the same arch, and are therefor hard coded into the hipe compiler. HIPE_SYSTEM_CRC represents values that may differ between VM variants. By default the hipe compiler asks the running VM for this checksum, in order to create beam files for the same running VM. The hipe compiler can be configured (with "make XCOMP=yes ...") to create beam files for another VM variant, in which case HIPE_SYSTEM_CRC is also hard coded. ToDo: Treat all erts properties the same. Either ask the running VM or hard coded into hipe (if XCOMP=yes). This will simplify and reduce the risk of dangerous mismatches. One concern might be the added overhead from more frequent calls to hipe_bifs:get_rts_param. --- lib/dialyzer/src/dialyzer.app.src | 2 +- lib/dialyzer/src/dialyzer_cl.erl | 6 +++--- lib/hipe/arm/hipe_arm_assemble.erl | 2 +- lib/hipe/llvm/hipe_llvm_merge.erl | 2 +- lib/hipe/main/hipe.erl | 12 +++++++++++- lib/hipe/ppc/hipe_ppc_assemble.erl | 2 +- lib/hipe/sparc/hipe_sparc_assemble.erl | 2 +- lib/hipe/x86/hipe_x86_assemble.erl | 2 +- 8 files changed, 20 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src index 6718178fae..8ac6dc1367 100644 --- a/lib/dialyzer/src/dialyzer.app.src +++ b/lib/dialyzer/src/dialyzer.app.src @@ -47,5 +47,5 @@ {applications, [compiler, gs, hipe, kernel, stdlib, wx]}, {env, []}, {runtime_dependencies, ["wx-1.2","syntax_tools-1.6.14","stdlib-2.5", - "kernel-3.0","hipe-3.10.3","erts-7.0", + "kernel-3.0","hipe-3.13","erts-7.0", "compiler-5.0"]}]}. diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 55302d5869..4116866916 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -547,13 +547,13 @@ hc(Mod, Cache) -> hc_cache(Mod) -> CacheBase = cache_base_dir(), - %% Use HiPE architecture and version in directory name, to avoid - %% clashes between incompatible binaries. + %% Use HiPE architecture, version and erts checksum in directory name, + %% to avoid clashes between incompatible binaries. HipeArchVersion = lists:concat( [erlang:system_info(hipe_architecture), "-", hipe:version(), "-", - hipe_bifs:system_crc()]), + hipe:erts_checksum()]), CacheDir = filename:join(CacheBase, HipeArchVersion), OrigBeamFile = code:which(Mod), {ok, {Mod, <>}} = beam_lib:md5(OrigBeamFile), diff --git a/lib/hipe/arm/hipe_arm_assemble.erl b/lib/hipe/arm/hipe_arm_assemble.erl index 7859e2d4a8..5f98c6593e 100644 --- a/lib/hipe/arm/hipe_arm_assemble.erl +++ b/lib/hipe/arm/hipe_arm_assemble.erl @@ -48,7 +48,7 @@ assemble(CompiledCode, Closures, Exports, Options) -> DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap), SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports), SlimRefs = hipe_pack_constants:slim_refs(AccRefs), - Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC}, + Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM}, ConstAlign, ConstSize, SC, DataRelocs, % nee LM, LabelMap diff --git a/lib/hipe/llvm/hipe_llvm_merge.erl b/lib/hipe/llvm/hipe_llvm_merge.erl index 3ababfc21a..6e891ac3b0 100644 --- a/lib/hipe/llvm/hipe_llvm_merge.erl +++ b/lib/hipe/llvm/hipe_llvm_merge.erl @@ -27,7 +27,7 @@ finalize(CompiledCode, Closures, Exports) -> DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap), SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap, Closures, Exports), SlimRefs = hipe_pack_constants:slim_refs(AccRefs), - term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC}, + term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM}, ConstAlign, ConstSize, SC, % ConstMap DataRelocs, % LabelMap diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index ce4f49ffa7..1a4bbf179f 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -208,7 +208,8 @@ help_options/0, help_option/1, help_debug_options/0, - version/0]). + version/0, + erts_checksum/0]). -ifndef(DEBUG). -define(DEBUG,true). @@ -216,6 +217,7 @@ -include("hipe.hrl"). -include("../../compiler/src/beam_disasm.hrl"). +-include("../rtl/hipe_literals.hrl"). %%------------------------------------------------------------------- %% Basic type declaration for exported functions of the 'hipe' module @@ -1032,6 +1034,12 @@ post(Res, Icode, Options) -> version() -> ?VERSION_STRING(). +%% @doc Returns checksum identifying the target runtime system. +-spec erts_checksum() -> integer(). + +erts_checksum() -> + ?HIPE_ERTS_CHECKSUM. + %% -------------------------------------------------------------------- %% D O C U M E N T A T I O N - H E L P %% -------------------------------------------------------------------- @@ -1062,6 +1070,8 @@ help() -> " Prints a description of debug options.\n" ++ " version() ->\n" ++ " Returns the HiPE version as a string'.\n" ++ + " erts_checksum() ->\n" ++ + " Returns a checksum identifying the target runtime system.\n" ++ "\n" ++ " For HiPE developers only:\n" ++ " Use `help_hiper()' for information about HiPE's low-level interface\n", diff --git a/lib/hipe/ppc/hipe_ppc_assemble.erl b/lib/hipe/ppc/hipe_ppc_assemble.erl index 4d419978ef..00f28d60e4 100644 --- a/lib/hipe/ppc/hipe_ppc_assemble.erl +++ b/lib/hipe/ppc/hipe_ppc_assemble.erl @@ -50,7 +50,7 @@ assemble(CompiledCode, Closures, Exports, Options) -> DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap), SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports), SlimRefs = hipe_pack_constants:slim_refs(AccRefs), - Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC}, + Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM}, ConstAlign, ConstSize, SC, DataRelocs, % nee LM, LabelMap diff --git a/lib/hipe/sparc/hipe_sparc_assemble.erl b/lib/hipe/sparc/hipe_sparc_assemble.erl index 5424a6c965..0e27c78416 100644 --- a/lib/hipe/sparc/hipe_sparc_assemble.erl +++ b/lib/hipe/sparc/hipe_sparc_assemble.erl @@ -49,7 +49,7 @@ assemble(CompiledCode, Closures, Exports, Options) -> DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap), SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports), SlimRefs = hipe_pack_constants:slim_refs(AccRefs), - Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC}, + Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM}, ConstAlign, ConstSize, SC, DataRelocs, % nee LM, LabelMap diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl index 4ffa3d35ba..695ce16887 100644 --- a/lib/hipe/x86/hipe_x86_assemble.erl +++ b/lib/hipe/x86/hipe_x86_assemble.erl @@ -83,7 +83,7 @@ assemble(CompiledCode, Closures, Exports, Options) -> DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap), SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports), SlimRefs = hipe_pack_constants:slim_refs(AccRefs), - Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC}, + Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM}, ConstAlign, ConstSize, SC, DataRelocs, % nee LM, LabelMap -- cgit v1.2.3 From fc9f2bb3e2ef36d123451650e141ae5038cc00fc Mon Sep 17 00:00:00 2001 From: tmanevik Date: Thu, 4 Jun 2015 14:35:27 +0200 Subject: inets: Remove documentation of legacy API --- lib/inets/doc/src/Makefile | 1 - lib/inets/doc/src/httpd_conf.xml | 163 --------------------------------------- lib/inets/doc/src/ref_man.xml | 1 - 3 files changed, 165 deletions(-) delete mode 100644 lib/inets/doc/src/httpd_conf.xml (limited to 'lib') diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile index a0a3472c4a..cb71fbeb9c 100644 --- a/lib/inets/doc/src/Makefile +++ b/lib/inets/doc/src/Makefile @@ -52,7 +52,6 @@ XML_REF3_FILES = \ http_uri.xml\ httpc.xml\ httpd.xml \ - httpd_conf.xml \ httpd_custom_api.xml \ httpd_socket.xml \ httpd_util.xml \ diff --git a/lib/inets/doc/src/httpd_conf.xml b/lib/inets/doc/src/httpd_conf.xml deleted file mode 100644 index 54a5885eb4..0000000000 --- a/lib/inets/doc/src/httpd_conf.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - - -
- - 19972013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - httpd_conf - Joakim Grebenö - - 1997-10-14 - 2.2 - httpd_conf.sgml -
- httpd_conf - Configuration utility functions to be used by the Erlang - Web server API programmer. - -

This module provides the Erlang Webserver API programmer with - utility functions for adding run-time configuration directives.

- - -
- - - - check_enum(EnumString, ValidEnumStrings) -> Result - Check if string is a valid enumeration. - - EnumString = string() - ValidEnumStrings = [string()] - Result = {ok,atom()} | {error,not_valid} - - - -

check_enum/2 checks if EnumString is a valid - enumeration of ValidEnumStrings in which case it is - returned as an atom.

- - -
-
- - - clean(String) -> Stripped - Remove leading and/or trailing white spaces. - - String = Stripped = string() - - - -

clean/1 removes leading and/or trailing white spaces - from String.

- - -
-
- - - custom_clean(String,Before,After) -> Stripped - Remove leading and/or trailing white spaces and custom characters. - - Before = After = regexp() - String = Stripped = string() - - - -

custom_clean/3 removes leading and/or trailing white - spaces and custom characters from String. Before - and After are regular expressions, as defined in - regexp(3), describing the custom characters.

- - -
-
- - - is_directory(FilePath) -> Result - Check if a file path is a directory. - - FilePath = string() - Result = {ok,Directory} | {error,Reason} - Directory = string() - Reason = string() | enoent | eacces | enotdir | FileInfo - FileInfo = File info record - - - -

is_directory/1 checks if FilePath is a - directory in which case it is returned. Please read - file(3) for a description of enoent, - eacces and enotdir. The definition of - the file info record can be found by including file.hrl - from the kernel application, see file(3).

- - -
-
- - - is_file(FilePath) -> Result - Check if a file path is a regular file. - - FilePath = string() - Result = {ok,File} | {error,Reason} - File = string() - Reason = string() | enoent | eacces | enotdir | FileInfo - FileInfo = File info record - - - -

is_file/1 checks if FilePath is a regular - file in which case it is returned. Read file(3) for a - description of enoent, eacces and - enotdir. The definition of the file info record can be - found by including file.hrl from the kernel application, - see file(3).

- - -
-
- - - make_integer(String) -> Result - Return an integer representation of a string. - - String = string() - Result = {ok,integer()} | {error,nomatch} - - - -

make_integer/1 returns an integer representation of - String.

-
-
-
- -
- - SEE ALSO -

httpd(3)

-
- -
- - diff --git a/lib/inets/doc/src/ref_man.xml b/lib/inets/doc/src/ref_man.xml index bcebcc0fd4..ab6b399a74 100644 --- a/lib/inets/doc/src/ref_man.xml +++ b/lib/inets/doc/src/ref_man.xml @@ -39,7 +39,6 @@ - -- cgit v1.2.3 From ed9ad11c9e1a1681cae44c2c2b48bf70ea68ae43 Mon Sep 17 00:00:00 2001 From: tmanevik Date: Thu, 4 Jun 2015 15:55:54 +0200 Subject: inets: sorted functions alphabetically --- lib/inets/doc/src/http_uri.xml | 59 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml index 4b59c0c7a2..c71bfbd686 100644 --- a/lib/inets/doc/src/http_uri.xml +++ b/lib/inets/doc/src/http_uri.xml @@ -72,17 +72,32 @@ fragment() = string() - scheme_defaults() -> SchemeDefaults - A list of scheme and their default ports + decode(HexEncodedURI) -> URI + + Decode a hex encoded URI - SchemeDefaults = [{scheme(), default_scheme_port_number()}] - default_scheme_port_number() = pos_integer() + HexEncodedURI = string() - A possibly hex encoded uri + URI = uri() + -

This function provides a list of the scheme and their default - port numbers currently supported (by default) by this utility.

+

Decode a possibly hex encoded URI.

- +
+
+ + encode(URI) -> HexEncodedURI + + Hex encode an URI + + URI = uri() + HexEncodedURI = string() - Hex encoded uri + + + +

Hex encode an URI.

+ +
@@ -124,35 +139,21 @@ fragment() = string() - encode(URI) -> HexEncodedURI - - Hex encode an URI + scheme_defaults() -> SchemeDefaults + A list of scheme and their default ports - URI = uri() - HexEncodedURI = string() - Hex encoded uri + SchemeDefaults = [{scheme(), default_scheme_port_number()}] + default_scheme_port_number() = pos_integer() - -

Hex encode an URI.

+

This function provides a list of the scheme and their default + port numbers currently supported (by default) by this utility.

- +
- - decode(HexEncodedURI) -> URI - - Decode a hex encoded URI - - HexEncodedURI = string() - A possibly hex encoded uri - URI = uri() - - - -

Decode a possibly hex encoded URI.

- -
-
+
-- cgit v1.2.3 From c54168c72bb42f8ffb0e341fd56cd81a89b53430 Mon Sep 17 00:00:00 2001 From: tmanevik Date: Fri, 3 Jul 2015 09:34:23 +0200 Subject: Inets User Guide Editorial Changes --- lib/inets/doc/src/ftp_client.xml | 53 +-- lib/inets/doc/src/http_client.xml | 96 ++-- lib/inets/doc/src/http_server.xml | 851 ++++++++++++++++++----------------- lib/inets/doc/src/inets_services.xml | 59 +-- lib/inets/doc/src/introduction.xml | 57 +++ lib/inets/doc/src/part.xml | 14 +- 6 files changed, 581 insertions(+), 549 deletions(-) create mode 100644 lib/inets/doc/src/introduction.xml (limited to 'lib') diff --git a/lib/inets/doc/src/ftp_client.xml b/lib/inets/doc/src/ftp_client.xml index 2f5b8abb5f..84fa064551 100644 --- a/lib/inets/doc/src/ftp_client.xml +++ b/lib/inets/doc/src/ftp_client.xml @@ -34,38 +34,27 @@
- Introduction + Getting Started -

Ftp clients are consider to be rather temporary and are - for that reason only started and stopped during - runtime and can not be started at application startup. - Due to the design of FTP client API, letting some - functions return intermediate results, only the process - that started the ftp client will be able to access it in - order to preserve sane semantics. (This could be solved - by changing the API and using the concept of a controlling - process more in line with other OTP applications, but - that is perhaps something for the future.) - If the process that started the ftp session - dies the ftp client process will terminate.

+

FTP clients are considered to be rather temporary. Thus, + they are only started and stopped during runtime and cannot + be started at application startup. + The FTP client API is designed to allow some functions to + return intermediate results. This implies that only the process + that started the FTP client can access it with + preserved sane semantics. (This can be solved + by changing the API, using the concept of a controlling + process as with other OTP applications, but + that is something for future releases of Inets.) + If the process that started the FTP session + dies, the FTP client process terminates.

-

The client supports ipv6 as long as the underlying mechanisms - also do so.

+

The client supports IPv6 as long as the underlying mechanisms + also do so.

-
- -
- Using the FTP Client API -

The following is a simple example of an ftp session, where +

The following is a simple example of an FTP session, where the user guest with password password logs on to - the remote host erlang.org, and where the file - appl.erl is transferred from the remote to the local - host. When the session is opened, the current directory at - the remote host is /home/guest, and /home/fred - at the local host. Before transferring the file, the current - local directory is changed to /home/eproj/examples, and - the remote directory is set to - /home/guest/appl/examples.

+ the remote host erlang.org:

inets:start(). ok @@ -86,6 +75,14 @@ 9> inets:stop(ftpc, Pid). ok ]]> +

The file + appl.erl is transferred from the remote to the local + host. When the session is opened, the current directory at + the remote host is /home/guest, and /home/fred + at the local host. Before transferring the file, the current + local directory is changed to /home/eproj/examples, and + the remote directory is set to + /home/guest/appl/examples.

diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml index 5c42f72cec..f4d7b751ac 100644 --- a/lib/inets/doc/src/http_client.xml +++ b/lib/inets/doc/src/http_client.xml @@ -34,103 +34,91 @@
- Introduction + Configuration -

The HTTP client default profile will be started when the inets +

The HTTP client default profile is started when the Inets application is started and is then available to all processes on - that erlang node. Other profiles may also be started at + that Erlang node. Other profiles can also be started at application startup, or profiles can be started and stopped - dynamically in runtime. Each client profile will spawn a new - process to handle each request unless there is a possibility to use - a persistent connection with or without pipelining. - The client will add a host header and an empty + dynamically in runtime. Each client profile spawns a new + process to handle each request, unless a persistent connection + can be used with or without pipelining. + The client adds a host header and an empty te header if there are no such headers present in the request.

-

The client supports ipv6 as long as the underlying mechanisms also do +

The client supports IPv6 as long as the underlying mechanisms also do so.

-
-
- Configuration -

What to put in the erlang node application configuration file - in order to start a profile at application startup.

+

The following is to be put in the Erlang node application configuration file + to start a profile at application startup:

-      [{inets, [{services, [{httpc, PropertyList}]}]}]
-    
-

For valid properties see + [{inets, [{services, [{httpc, PropertyList}]}]}] +

For valid properties, see httpc(3).

- Using the HTTP Client API + Getting Started +

Start Inets:

1 > inets:start(). - ok - -

The following calls uses the default client profile. - Use the proxy "www-proxy.mycompany.com:8000", - but not for requests to localhost. This will apply to all subsequent - requests

+ ok +

The following calls use the default client profile. + Use the proxy "www-proxy.mycompany.com:8000", + except from requests to localhost. This applies to all the + following requests.

+

Example:

2 > httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000}, ["localhost"]}}]). - ok - -

An ordinary synchronous request.

+ ok +

The following is an ordinary synchronous request:

3 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - httpc:request(get, {"http://www.erlang.org", []}, [], []). - -

With all default values, as above, a get request can also be written - like this.

+ httpc:request(get, {"http://www.erlang.org", []}, [], []). +

With all the default values presented, a get request can also be written + as follows:

4 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - httpc:request("http://www.erlang.org"). - -

An ordinary asynchronous request. The result will be sent - to the calling process in the form {http, {ReqestId, Result}}

+ httpc:request("http://www.erlang.org"). +

The following is an ordinary asynchronous request:

5 > {ok, RequestId} = - httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]). - -

In this case the calling process is the shell, so we receive the - result.

+ httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]). +

The result is sent to the calling process as + {http, {ReqestId, Result}}.

+

In this case, the calling process is the shell, so the following + result is received:

6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end. - ok - -

Send a request with a specified connection header.

+ ok +

This sends a request with a specified connection header:

7 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} = httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]}, - [], []). - + [], []). -

Start a HTTP client profile.

+

Start an HTTP client profile:

{ok, Pid} = inets:start(httpc, [{profile, foo}]). {ok, <0.45.0>} ]]> -

The new profile has no proxy settings so the connection will - be refused

+

The new profile has no proxy settings, so the connection is refused:

9 > httpc:request("http://www.erlang.org", foo). - {error, econnrefused} - + {error, econnrefused} -

Stop a HTTP client profile.

+

Stop the HTTP client profile:

10 > inets:stop(httpc, foo). - ok - + ok -

Alternatively:

+

Alternative way to stop the HTTP client profile:

10 > inets:stop(httpc, Pid). - ok - + ok
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml index 51ed826c7c..efa5f7a8f5 100644 --- a/lib/inets/doc/src/http_server.xml +++ b/lib/inets/doc/src/http_server.xml @@ -22,7 +22,7 @@ - HTTP server + HTTP server Ingela Anderton Andin @@ -36,62 +36,65 @@
- Introduction - + Configuration +

The HTTP server, also referred to as httpd, handles HTTP requests - as described in RFC 2616 with a few exceptions such as gateway - and proxy functionality. The server supports ipv6 as long as the - underlying mechanisms also do so.

- -

The server implements numerous features such as SSL (Secure Sockets - Layer), ESI (Erlang Scripting Interface), CGI (Common Gateway - Interface), User Authentication(using Mnesia, dets or plain text - database), Common Logfile Format (with or without disk_log(3) - support), URL Aliasing, Action Mappings, and Directory Listings

- -

The configuration of the server is provided as an erlang - property list, and for backwards compatibility also a configuration + as described in + RFC 2616 + with a few exceptions, such as gateway + and proxy functionality. The server supports IPv6 as long as the + underlying mechanisms also do so.

+ +

The server implements numerous features, such as:

+ + Secure Sockets Layer (SSL) + Erlang Scripting Interface (ESI) + Common Gateway Interface (CGI) + User Authentication (using Mnesia, + Dets or plain text database) + Common Logfile Format (with or without disk_log(3) support) + URL Aliasing + Action Mappings + Directory Listings + + +

The configuration of the server is provided as an Erlang + property list. For backwards compatibility, a configuration file using apache-style configuration directives is supported.

-

As of inets version 5.0 the HTTP server is an easy to - start/stop and customize web server that provides the most basic - web server functionality. Depending on your needs there - are also other erlang based web servers that may be of interest - such as Yaws, http://yaws.hyber.org, that for instance has its own - markup support to generate html, and supports certain buzzword - technologies such as SOAP.

+

As of Inets 5.0 the HTTP server is an easy to + start/stop and customize web server providing the most basic + web server functionality. Depending on your needs, there + are also other Erlang-based web servers that can be of interest + such as Yaws, which, + for example, has its own + markup support to generate HTML and supports certain buzzword + technologies, such as SOAP.

-

Allmost all server functionality has been implemented using an - especially crafted server API which is described in the Erlang Web - Server API. This API can be used to advantage by all who wish +

Almost all server functionality has been implemented using an + especially crafted server API, which is described in the Erlang Web + Server API. This API can be used to enhance the core server functionality, for example with custom logging and authentication.

- -
- -
- Configuration - -

What to put in the erlang node application configuration file - in order to start a http server at application startup.

+

The following is to be put in the Erlang node application configuration + file to start an HTTP server at application startup:

[{inets, [{services, [{httpd, [{proplist_file, "/var/tmp/server_root/conf/8888_props.conf"}]}, {httpd, [{proplist_file, - "/var/tmp/server_root/conf/8080_props.conf"}]}]}]}]. - - -

The server is configured using an erlang property list. - For the available properties see - httpd(3) - For backwards compatibility also apache-like config files - are supported. + "/var/tmp/server_root/conf/8080_props.conf"}]}]}]}]. + +

The server is configured using an Erlang property list. + For the available properties, see + httpd(3). + For backwards compatibility, apache-like configuration files + are also supported.

-

All possible config properties are as follows

+

The available configuration properties are as follows:

httpd_service() -> {httpd, httpd()} httpd() -> [httpd_config()] @@ -103,40 +106,43 @@ debug_options() -> {all_functions, modules()} | {exported_functions, modules()} | {disable, modules()} - modules() -> [atom()] - -

{proplist_file, file()} File containing an erlang property + modules() -> [atom()] +

Here:

+ + {file, file()} +

If you use an old apace-like configuration file.

+ {proplist_file, file()} +

File containing an Erlang property list, followed by a full stop, describing the HTTP server - configuration.

-

{file, file()} If you use an old apace-like configuration file.

-

{debug, debug()} - Can enable trace on all - functions or only exported functions on chosen modules.

-

{accept_timeout, integer()} sets the wanted timeout value for - the server to set up a request connection.

- - + configuration.

+ {debug, debug()} +

Can enable trace on all functions or only exported functions + on chosen modules.

+ {accept_timeout, integer()} +

Sets the wanted time-out value for + the server to set up a request connection.

+
- Using the HTTP Server API + Getting Started + +

Start Inets:

1 > inets:start(). - ok - -

Start a HTTP server with minimal - required configuration. Note that if you - specify port 0 an arbitrary available port will be - used and you can use the info function to find out - which port number that was picked. -

+ ok +

Start an HTTP server with minimal required configuration. + If you specify port 0, an arbitrary available port is + used, and you can use function info to find which port + number that was picked:

2 > {ok, Pid} = inets:start(httpd, [{port, 0}, {server_name,"httpd_test"}, {server_root,"/tmp"}, {document_root,"/tmp/htdocs"}, {bind_address, "localhost"}]). - {ok, 0.79.0} - + {ok, 0.79.0} +

Call info:

3 > httpd:info(Pid). [{mime_types,[{"html","text/html"},{"htm","text/html"}]}, @@ -144,325 +150,312 @@ {bind_address, {127,0,0,1}}, {server_root,"/tmp"}, {port,59408}, - {document_root,"/tmp/htdocs"}] - + {document_root,"/tmp/htdocs"}] -

Reload the configuration without restarting the server. - Note port and bind_address can not be changed. Clients - trying to access the server during the reload will - get a service temporary unavailable answer. +

Reload the configuration without restarting the server: +

4 > httpd:reload_config([{port, 59408}, {server_name,"httpd_test"}, {server_root,"/tmp/www_test"}, {document_root,"/tmp/www_test/htdocs"}, {bind_address, "localhost"}], non_disturbing). - ok. - + ok. + +

port and bind_address cannot be changed. + Clients trying to access the server during the reload + get a service temporary unavailable answer.

5 > httpd:info(Pid, [server_root, document_root]). - [{server_root,"/tmp/www_test"},{document_root,"/tmp/www_test/htdocs"}] - + [{server_root,"/tmp/www_test"},{document_root,"/tmp/www_test/htdocs"}] - 6 > ok = inets:stop(httpd, Pid). - + 6 > ok = inets:stop(httpd, Pid). -

Alternative:

+

Alternative:

- 6 > ok = inets:stop(httpd, {{127,0,0,1}, 59408}). - + 6 > ok = inets:stop(httpd, {{127,0,0,1}, 59408}). -

Note that bind_address has to be - the ip address reported by the info function and can - not be the hostname that is allowed when inputting bind_address.

- - +

Notice that bind_address must be the IP address reported + by function info and cannot be the hostname that is allowed + when putting in bind_address.

Htaccess - User Configurable Authentication. -

If users of the web server needs to manage authentication of - web pages that are local to their user and do not have - server administrative privileges. They can use the - per-directory runtime configurable user-authentication scheme - that Inets calls htaccess. It works the following way:

+ +

Web server users without server administrative privileges + that need to manage authentication of web pages that are local + to their user can use the per-directory runtime configurable + user-authentication scheme htaccess. + It works as follows:

Each directory in the path to the requested asset is - searched for an access-file (default .htaccess), that restricts - the web servers rights to respond to a request. If an access-file - is found the rules in that file is applied to the - request. - The rules in an access-file applies both to files in the same - directories and in subdirectories. If there exists more than one - access-file in the path to an asset, the rules in the - access-file nearest the requested asset will be applied. - To change the rules that restricts the use of - an asset. The user only needs to have write access - to the directory where the asset exists. - All the access-files in the path to a requested asset is read - once per request, this means that the load on the server will - increase when this scheme is used. - If a directory is - limited both by auth directives in the HTTP server configuration - file and by the htaccess files. The user must be allowed to get - access the file by both methods for the request to succeed. + searched for an access file (default is .htaccess), which + restricts the web servers rights to respond to a request. + If an access file is found, the rules in that file is applied to the + request. + The rules in an access file apply to files in the same + directory and in subdirectories. If there exists more than one + access file in the path to an asset, the rules in the + access file nearest the requested asset is applied. + To change the rules that restrict the use of + an asset, the user only needs write access + to the directory where the asset is. + All access files in the path to a requested asset are read + once per request. This means that the load on the server + increases when htaccess is used. + If a directory is limited both by authentication directives + in the HTTP server configuration file and by the htaccess + files, the user must be allowed to get access to the file by both + methods for the request to succeed.
Access Files Directives -

In every directory under the DocumentRoot or under an - Alias a user can place an access-file. An access-file - is a plain text file that specify the restrictions that - shall be considered before the web server answer to a - request. If there are more than one access-file in the path - to the requested asset, the directives in the access-file in - the directory nearest the asset will be used.

- +

In every directory under DocumentRoot or under an + Alias a user can place an access file. An access file + is a plain text file that specifies the restrictions to + consider before the web server answers to a + request. If there are more than one access file in the path + to the requested asset, the directives in the access file in + the directory nearest the asset is used.

+ + "allow" -

DIRECTIVE: "allow"

-

Syntax:Allow from subnet subnet|from all

-Default:from all

-

-

Same as the directive allow for the server config file.

+

Syntax: Allow from subnet subnet | from all

+

Default: from all

+

Same as directive allow for the server configuration file.

- -

DIRECTIVE: "AllowOverRide"

-

Syntax:AllowOverRide all | none | - Directives

-Default:- None -

-AllowOverRide Specify which parameters that not - access-files in subdirectories are allowed to alter the value - for. If the parameter is set to none no more - access-files will be parsed. + "AllowOverRide" + +

Syntax: AllowOverRide all | none | Directives

+

Default: none

+

AllowOverRide specifies the parameters that + access files in subdirectories are not allowed to alter the value + for. If the parameter is set to none, no further + access files is parsed.

-

If only one access-file exists setting this parameter to - none can lessen the burden on the server since the server - will stop looking for access-files.

+

If only one access file exists, setting this parameter to + none can ease the burden on the server as the server + then stops looking for access files.

+ "AuthGroupfile" -

DIRECTIVE: "AuthGroupfile"

-

Syntax:AuthGroupFile Filename

-Default:- None -

-

-

AuthGroupFile indicates which file that contains the list - of groups. Filename must contain the absolute path to the - file. The format of the file is one group per row and +

Syntax: AuthGroupFile Filename

+

Default: none

+

AuthGroupFile indicates which file that contains the list + of groups. The filename must contain the absolute path to the + file. The format of the file is one group per row and every row contains the name of the group and the members - of the group separated by a space, for example:

+ of the group, separated by a space, for example:

-GroupName: Member1 Member2 .... MemberN
-            
+GroupName: Member1 Member2 .... MemberN
+ "AuthName" -

DIRECTIVE: "AuthName"

-

Syntax:AuthName auth-domain

-Default:- None -

-

-

Same as the directive AuthName for the server config file.

+

Syntax: AuthName auth-domain

+

Default: none

+

Same as directive AuthName for the server + configuration file.

+ "AuthType" -

DIRECTIVE: "AuthType"

-

Syntax:AuthType Basic

-Default:Basic

-

-

AuthType Specify which authentication scheme that shall - be used. Today only Basic Authenticating using UUEncoding of - the password and user ID is implemented.

+

Syntax: AuthType Basic

+

Default: Basic

+

AuthType specifies which authentication scheme to + be used. Only Basic Authenticating using UUEncoding of + the password and user ID is implemented.

+ "AuthUserFile" -

DIRECTIVE: "AuthUserFile"

-

Syntax:AuthUserFile Filename

-Default:- None -

-

-

AuthUserFile indicate which file that contains the list - of users. Filename must contain the absolute path to the - file. The users name and password are not encrypted so do not +

Syntax: AuthUserFile Filename

+

Default:none

+

AuthUserFile indicates which file that contains the list + of users. The filename must contain the absolute path to the + file. The username and password are not encrypted so do not place the file with users in a directory that is accessible - via the web server. The format of the file is one user per row - and every row contains User Name and Password separated by a - colon, for example:

+ through the web server. The format of the file is one user per row. + Every row contains UserName and Password separated + by a colon, for example:

 UserName:Password
-UserName:Password
-            
+UserName:Password
+ "deny" -

DIRECTIVE: "deny"

-

Syntax:deny from subnet subnet|from all

-Context: Limit

-

Same as the directive deny for the server config file.

+

Syntax: deny from subnet subnet | from all

+

Context: Limit

+

Same as directive deny for the server configuration file.

- -

DIRECTIVE: "Limit"

-

-

Syntax: RequestMethods>

-Default: - None -

-

-

]]> and </Limit> are used to enclose - a group of directives which applies only to requests using - the specified methods. If no request method is specified + "Limit" + +

Syntax: RequestMethods>

+

Default: none

+

]]> and </Limit> are used to enclose + a group of directives applying only to requests using + the specified methods. If no request method is specified, all request methods are verified against the restrictions.

+

Example:

 <Limit POST GET HEAD>
   order allow deny
   require group group1
   allow from 123.145.244.5
-</Limit>
-            
+</Limit>
- -

DIRECTIVE: "order"

-Syntax:order allow deny | deny allow

-Default: allow deny

-

-

order, defines if the deny or allow control shall - be preformed first.

-

If the order is set to allow deny, then first the users - network address is controlled to be in the allow subset. If - the users network address is not in the allowed subset he will - be denied to get the asset. If the network-address is in the - allowed subset then a second control will be preformed, that - the users network address is not in the subset of network - addresses that shall be denied as specified by the deny - parameter.

-

If the order is set to deny allow then only users from networks - specified to be in the allowed subset will succeed to request + "order" + +

Syntax: order allow deny | deny allow

+

Default: allow deny

+

order defines if the deny or allow control is to + be performed first.

+

If the order is set to allow deny, the users + network address is first controlled to be in the allow subset. + If the user network address is not in the allowed subset, the user + is denied to get the asset. If the network address is in the + allowed subset, a second control is performed. That is, + the user network address is not in the subset of network + addresses to be denied as specified by parameter deny.

+

If the order is set to deny allow, only users from networks + specified to be in the allowed subset succeeds to request assets in the limited area.

- -

DIRECTIVE: "require"

-

Syntax:require - group group1 group2...|user user1 user2...

-Default:- None -

-Context: Limit

-

-

See the require directive in the documentation of mod_auth(3) - for more information.

+ "require" + +

Syntax: require + group group1 group2... | user user1 user2...

+

Default: none

+

Context: Limit

+

For more information, see directive require in + mod_auth(3).

-
+
- -
Dynamic Web Pages -

The Inets HTTP server provides two ways of creating dynamic web - pages, each with its own advantages and disadvantages.

-

First there are CGI-scripts that can be written in any programming - language. CGI-scripts are standardized and supported by most - web servers. The drawback with CGI-scripts is that they are resource - intensive because of their design. CGI requires the server to fork a - new OS process for each executable it needs to start.

-

Second there are ESI-functions that provide a tight and efficient - interface to the execution of Erlang functions, this interface - on the other hand is Inets specific.

- + +

Inets HTTP server provides two ways of creating dynamic web + pages, each with its own advantages and disadvantages:

+ + CGI scripts +

Common Gateway Interface (CGI) scripts can be written + in any programming language. CGI scripts are standardized and + supported by most web servers. The drawback with CGI scripts is that + they are resource-intensive because of their design. CGI requires the + server to fork a new OS process for each executable it needs to start. +

+ ESI-functions +

Erlang Server Interface (ESI) functions provide a tight and efficient + interface to the execution of Erlang functions. This interface, + on the other hand, is Inets specific.

+
+
- The Common Gateway Interface (CGI) Version 1.1, RFC 3875. -

The mod_cgi module makes it possible to execute CGI scripts - in the server. A file that matches the definition of a - ScriptAlias config directive is treated as a CGI script. A CGI + CGI Version 1.1, RFC 3875 +

The module mod_cgi enables execution of CGI scripts + on the server. A file matching the definition of a + ScriptAlias config directive is treated as a CGI script. A CGI script is executed by the server and its output is returned to - the client.

-

The CGI Script response comprises a message-header and a - message-body, separated by a blank line. The message-header - contains one or more header fields. The body may be - empty. Example:

+ the client.

+

The CGI script response comprises a message header and a + message body, separated by a blank line. The message header + contains one or more header fields. The body can be + empty.

+

Example:

"Content-Type:text/plain\nAccept-Ranges:none\n\nsome very - plain text" + plain text" -

The server will interpret the cgi-headers and most of them - will be transformed into HTTP headers and sent back to the - client together with the body.

-

Support for CGI-1.1 is implemented in accordance with the RFC - 3875.

+

The server interprets the message headers and most of them + are transformed into HTTP headers and sent back to the + client together with the message-body.

+

Support for CGI-1.1 is implemented in accordance with + RFC 3875.

- Erlang Server Interface (ESI) -

The erlang server interface is implemented by the - module mod_esi.

+ ESI +

The Erlang server interface is implemented by + module mod_esi.

- ERL Scheme + ERL Scheme

The erl scheme is designed to mimic plain CGI, but without - the extra overhead. An URL which calls an Erlang erl function + the extra overhead. An URL that calls an Erlang erl function has the following syntax (regular expression):

-http://your.server.org/***/Module[:/]Function(?QueryString|/PathInfo) - -

*** above depends on how the ErlScriptAlias config - directive has been used

-

The module (Module) referred to must be found in the code - path, and it must define a function (Function) with an arity - of two or three. It is preferable to implement a funtion - with arity three as it permits you to send chunks of the - webpage beeing generated to the client during the generation +http://your.server.org/***/Module[:/]Function(?QueryString|/PathInfo) +

*** depends on how the ErlScriptAlias config + directive has been used.

+

The module Module referred to must be found in the code + path, and it must define a function Function with an arity + of two or three. It is preferable to implement a function + with arity three, as it permits to send chunks of the + web page to the client during the generation phase instead of first generating the whole web page and then sending it to the client. The option to implement a function with arity two is only kept for backwards compatibility reasons. - See mod_esi(3) for - implementation details of the esi callback function.

+ For implementation details of the ESI callback function, + see mod_esi(3).

- EVAL Scheme + EVAL Scheme

The eval scheme is straight-forward and does not mimic the - behavior of plain CGI. An URL which calls an Erlang eval + behavior of plain CGI. An URL that calls an Erlang eval function has the following syntax:

-http://your.server.org/***/Mod:Func(Arg1,...,ArgN) - -

*** above depends on how the ErlScriptAlias config - directive has been used

-

The module (Mod) referred to must be found in the code - path, and data returned by the function (Func) is passed +http://your.server.org/***/Mod:Func(Arg1,...,ArgN) +

*** depends on how the ErlScriptAlias config + directive has been used.

+

The module Mod referred to must be found in the code + path and data returned by the function Func is passed back to the client. Data returned from the - function must furthermore take the form as specified in - the CGI specification. See mod_esi(3) for implementation details of the esi - callback function.

+ function must take the form as specified in + the CGI specification. For implementation details of the ESI + callback function, + see mod_esi(3).

The eval scheme can seriously threaten the - integrity of the Erlang node housing a Web server, for - example:

+ integrity of the Erlang node housing a web server, for + example:

-http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[]))) - -

which effectively will close down the Erlang node, - therefor, use the erl scheme instead, until this - security breach has been fixed.

-

Today there are no good way of solving this problem - and therefore Eval Scheme may be removed in future - release of Inets.

+http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[]))) +

This effectively closes down the Erlang node. + Therefore, use the erl scheme instead, until this + security breach is fixed.

+

Today there are no good ways of solving this problem + and therefore the eval scheme can be removed in future + release of Inets.

- -
- Logging -

There are three types of logs supported. Transfer logs, - security logs and error logs. The de-facto standard Common + Logging + +

Three types of logs are supported: transfer logs, + security logs, and error logs. The de-facto standard Common Logfile Format is used for the transfer and security logging. There are numerous statistics programs available to analyze Common Logfile Format. The Common Logfile Format looks as follows:

remotehost rfc931 authuser [date] "request" status bytes

+

Here:

remotehost - Remote hostname + Remote hostname. rfc931 - The client's remote username (RFC 931). + The client remote username (RFC 931). authuser - The username with which the user authenticated himself. + The username used for authentication. [date] Date and time of the request (RFC 1123). "request" @@ -473,7 +466,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[ The content-length of the document transferred.

Internal server errors are recorded in the error log file. The - format of this file is a more ad hoc format than the logs using + format of this file is a more unplanned format than the logs using Common Logfile Format, but conforms to the following syntax:

[date] access to path failed for @@ -481,73 +474,79 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[

- The Erlang Web Server API -

The process of handling a HTTP request involves several steps + Erlang Web Server API +

The process of handling an HTTP request involves several steps, such as:

- Seting up connections, sending and receiving data. - URI to filename translation - Authenication/access checks. - Retriving/generating the response. - Logging + Setting up connections, sending and receiving data. + URI to filename translation. + Authentication/access checks. + Retrieving/generating the response. + Logging. -

To provide customization and extensibility of the HTTP servers - request handling most of these steps are handled by one or more - modules that may be replaced or removed at runtime, and of course - new ones can be added. For each request all modules will be - traversed in the order specified by the modules directive in the - server configuration file. Some parts mainly the communication - related steps are considered server core functionality and are - not implemented using the Erlang Web Server API. A description of - functionality implemented by the Erlang Webserver API is described - in the section Inets Webserver Modules.

+

To provide customization and extensibility of the request + handling of the HTTP servers, most of these steps are handled by + one or more modules. These modules can be replaced or removed at + runtime and new ones can be added. For each request, all modules are + traversed in the order specified by the module directive in the + server configuration file. Some parts, mainly the communication- + related steps, are considered server core functionality and are + not implemented using the Erlang web server API. A description of + functionality implemented by the Erlang webserver API is described + in Section + Inets Web Server Modules.

+

A module can use data generated by previous modules in the - Erlang Webserver API module sequence or generate data to be used - by consecutive Erlang Web Server API modules. This is made - possible due to an internal list of key-value tuples, also referred to - as interaction data.

+ Erlang webserver API module sequence or generate data to be used + by consecutive Erlang Web Server API modules. This is + possible owing to an internal list of key-value tuples, referred to + as interaction data.

Interaction data enforces module dependencies and - should be avoided if possible. This means the order - of modules in the Modules property is significant.

+ is to be avoided if possible. This means that the order + of modules in the modules property is significant.

API Description -

Each module implements server functionality - using the Erlang Web Server API should implement the following +

Each module that implements server functionality + using the Erlang web server API is to implement the following call back functions:

- do/1 (mandatory) - the function called when - a request should be handled. - load/2 - store/2 - remove/1 + do/1 (mandatory) - the function called when + a request is to be handled + load/2 + store/2 + remove/1

The latter functions are needed only when new config - directives are to be introduced. For details see - httpd(3)

+ directives are to be introduced. For details, see + httpd(3).

- Inets Web Server Modules

The convention is that - all modules implementing some webserver functionality has the - name mod_*. When configuring the web server an appropriate - selection of these modules should be present in the Module - directive. Please note that there are some interaction dependencies - to take into account so the order of the modules can not be - totally random.

+ Inets Web Server Modules + +

The convention is that + all modules implementing some web server functionality has the + name mod_*. When configuring the web server, an appropriate + selection of these modules is to be present in the module + directive. Notice that there are some interaction dependencies + to take into account, so the order of the modules cannot be + random.

- mod_action - Filetype/Method-Based Script Execution. -

Runs CGI scripts whenever a file of a - certain type or HTTP method (See RFC 1945) is requested. + mod_action - Filetype/Method-Based Script Execution +

This module runs CGI scripts whenever a file of a + certain type or HTTP method (see + RFC 1945RFC 1945) + is requested.

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data, if possible:

@@ -559,48 +558,51 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
mod_alias - URL Aliasing -

This module makes it possible to map different parts of the - host file system into the document tree e.i. creates aliases and +

The mod_alias + module makes it possible to map different parts of the + host file system into the document tree, that is, creates aliases and redirections.

Exports the following Erlang Web Server API interaction data, if possible:

{real_name, PathData} - PathData is the argument used for API function mod_alias:path/3. + PathData is the argument used for API function + mod_alias:path/3.
- mod_auth - User Authentication -

This module provides for basic user authentication using - textual files, dets databases as well as mnesia databases.

+ mod_auth - User Authentication +

The mod_auth(3) + module provides for basic user authentication using + textual files, Dets databases as well as Mnesia databases.

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data:

{remote_user, User} - The user name with which the user has authenticated himself. + The username used for authentication.
- Mnesia as Authentication Database + Mnesia As Authentication Database -

If Mnesia is used as storage method, Mnesia must be - started prio to the HTTP server. The first time Mnesia is - started the schema and the tables must be created before - Mnesia is started. A naive example of a module with two - functions that creates and start mnesia is provided - here. The function shall be used the first - time. first_start/0 creates the schema and the tables. The - second function start/0 shall be used in consecutive - startups. start/0 Starts Mnesia and wait for the tables to +

If Mnesia is used as storage method, Mnesia must be + started before the HTTP server. The first time Mnesia is + started, the schema and the tables must be created before + Mnesia is started. A simple example of a module with two + functions that creates and start Mnesia is provided + here. Function first_start/0 is to be used the first + time. It creates the schema and the tables. + start/0 is to be used in consecutive startups. + start/0 starts Mnesia and waits for the tables to be initiated. This function must only be used when the - schema and the tables already is created.

+ schema and the tables are already created.

-module(mnesia_test). @@ -624,28 +626,28 @@ first_start() -> start() -> mnesia:start(), - mnesia:wait_for_tables([httpd_user, httpd_group], 60000). - + mnesia:wait_for_tables([httpd_user, httpd_group], 60000). -

To create the Mnesia tables we use two records defined in - mod_auth.hrl so the file must be included. The first - function first_start/0 creates a schema that specify on - which nodes the database shall reside. Then it starts Mnesia - and creates the tables. The first argument is the name of - the tables, the second argument is a list of options how the - table will be created, see Mnesia documentation for more - information. Since the current implementation of the - mod_auth_mnesia saves one row for each user the type must be - bag. When the schema and the tables is created the second - function start/0 shall be used to start Mensia. It starts - Mnesia and wait for the tables to be loaded. Mnesia use the - directory specified as mnesia_dir at startup if specified, - otherwise Mnesia use the current directory. For security - reasons, make sure that the Mnesia tables are stored outside - the document tree of the HTTP server. If it is placed in the - directory which it protects, clients will be able to - download the tables. Only the dets and mnesia storage - methods allow writing of dynamic user data to disk. plain is +

To create the Mnesia tables, we use two records defined in + mod_auth.hrl, so that file must be included. first_start/0 + creates a schema that specifies on which nodes the database is to reside. + Then it starts Mnesia and creates the tables. The first argument + is the name of the tables, the second argument is a list of options of + how to create the table, see + mnesia, documentation for + more information. As the implementation of the mod_auth_mnesia + saves one row for each user, the type must be bag. + When the schema and the tables are created, function + mnesia:start/0 + is used to start Mnesia and + waits for the tables to be loaded. Mnesia uses the + directory specified as mnesia_dir at startup if specified, + otherwise Mnesia uses the current directory. For security + reasons, ensure that the Mnesia tables are stored outside + the document tree of the HTTP server. If they are placed in the + directory which it protects, clients can download the tables. + Only the Dets and Mnesia storage + methods allow writing of dynamic user data to disk. plain is a read only method.

@@ -653,19 +655,19 @@ start() ->
mod_cgi - CGI Scripts -

This module handles invoking of CGI scripts

+

This module handles invoking of CGI scripts.

mod_dir - Directories

This module generates an HTML directory listing (Apache-style) if a client sends a request for a directory - instead of a file. This module needs to be removed from the + instead of a file. This module must be removed from the Modules config directive if directory listings is unwanted.

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data:

@@ -677,27 +679,27 @@ start() ->
- mod_disk_log - Logging Using disk_log. + mod_disk_log - Logging Using Disk_Log.

Standard logging using the "Common Logfile Format" and - disk_log(3).

+ kernel:disk_log(3).

Uses the following Erlang Web Server API interaction data:

- remote_user - from mod_auth + remote_user - from mod_auth
mod_esi - Erlang Server Interface -

This module implements - the Erlang Server Interface (ESI) that provides a tight and - efficient interface to the execution of Erlang functions.

-

Uses the following Erlang Web Server API interaction data: +

The mod_esi(3) + module implements the Erlang Server Interface (ESI) providing a + tight and efficient interface to the execution of Erlang functions.

+

Uses the following Erlang web server API interaction data:

- remote_user - from mod_auth + remote_user - from mod_auth -

Exports the following Erlang Web Server API interaction data: +

Exports the following Erlang web server API interaction data:

{mime_type, MimeType} @@ -709,11 +711,11 @@ start() ->
mod_get - Regular GET Requests

This module is responsible for handling GET requests to regular - files. GET requests for parts of files is handled by mod_range.

-

Uses the following Erlang Web Server API interaction data: + files. GET requests for parts of files is handled by mod_range.

+

Uses the following Erlang web server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias
@@ -725,7 +727,7 @@ start() ->

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias
@@ -736,13 +738,13 @@ start() ->

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data:

{remote_user_name, User} - The user name with which the user has authenticated himself. + The username used for authentication.
@@ -750,84 +752,83 @@ start() -> mod_log - Logging Using Text Files.

Standard logging using the "Common Logfile Format" and text files.

-

Uses the following Erlang Webserver API interaction data: +

Uses the following Erlang Web Server API interaction data:

- remote_user - from mod_auth + remote_user - from mod_auth
mod_range - Requests with Range Headers -

This module response to requests for one or many ranges of a - file. This is especially useful when downloading large files, - since a broken download may be resumed.

-

Note that request for multiple parts of a document will report a +

This module responses to requests for one or many ranges of a + file. This is especially useful when downloading large files, + as a broken download can be resumed.

+

Notice that request for multiple parts of a document report a size of zero to the log file.

-

Uses the following Erlang Webserver API interaction data: +

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias
mod_response_control - Requests with If* Headers -

This module controls that the conditions in the requests is - fulfilled. For example a request may specify that the answer - only is of interest if the content is unchanged since last - retrieval. Or if the content is changed the range-request shall - be converted to a request for the whole file instead.

If - a client sends more then one of the header fields that restricts - the servers right to respond, the standard does not specify how - this shall be handled. httpd will control each field in the - following order and if one of the fields not match the current - state the request will be rejected with a proper response. -

+

This module controls that the conditions in the requests are + fulfilled. For example, a request can specify that the answer + only is of interest if the content is unchanged since the last + retrieval. If the content is changed, the range request is to + be converted to a request for the whole file instead.

+

If a client sends more than one of the header fields that + restricts the servers right to respond, the standard does not + specify how this is to be handled. + httpd(3) controls each + field in the following order and if one of the fields does not + match the current state, the request is rejected with a proper + response:

+

If-modified

+

If-Unmodified

+

If-Match

+

If-Nomatch

- 1.If-modified

- - 2.If-Unmodified

- - 3.If-Match

- - 4.If-Nomatch

-

-

Uses the following Erlang Webserver API interaction data: +

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias -

Exports the following Erlang Webserver API interaction data: +

Exports the following Erlang Web Server API interaction data:

{if_range, send_file} - The conditions for the range request was not fulfilled. + The conditions for the range request are not fulfilled. The response must not be treated as a range request, instead it - must be treated as a ordinary get request. + must be treated as an ordinary get request.
mod_security - Security Filter -

This module serves as a filter for authenticated requests - handled in mod_auth. It provides possibility to restrict users - from access for a specified amount of time if they fail to +

The mod_security + module serves as a filter for authenticated requests + handled in mod_auth(3). + It provides a possibility to restrict users from + access for a specified amount of time if they fail to authenticate several times. It logs failed authentication as - well as blocking of users, and it also calls a configurable - call-back module when the events occur.

+ well as blocking of users, and it calls a configurable + callback module when the events occur.

There is also an - API to manually block, unblock and list blocked users or users, - who have been authenticated within a configurable amount of - time.

+ API to block or unblock users manually. This API can also list + blocked users or users who have been authenticated within a + configurable amount of time.

mod_trace - TRACE Request -

mod_trace is responsible for handling of TRACE requests. +

mod_trace is responsible for handling of TRACE requests. Trace is a new request method in HTTP/1.1. The intended use of trace requests is for testing. The body of the trace response is - the request message that the responding Web server or proxy + the request message that the responding web server or proxy received.

diff --git a/lib/inets/doc/src/inets_services.xml b/lib/inets/doc/src/inets_services.xml index f78485cb64..d100216ebb 100644 --- a/lib/inets/doc/src/inets_services.xml +++ b/lib/inets/doc/src/inets_services.xml @@ -22,7 +22,7 @@ - Introduction + Inets Ingela Anderton Andin @@ -34,45 +34,26 @@
- Purpose -

Inets is a container for Internet clients and - servers. Currently, an client and server, a - TFPT client and server, and a FTP client has been incorporated - into Inets. The HTTP server and client is HTTP 1.1 compliant as - defined in 2616.

-
- -
- Prerequisites -

It is assumed that the reader is familiar with the Erlang - programming language, concepts of OTP and has a basic - understanding of the HTTP, TFTP and FTP protocols.

-
- -
- The Service Concept -

Each client and server in inets is viewed as service. Services - may be configured to be started at application startup or - started dynamically in runtime. If you want to run inets as an - distributed application that should handle application failover - and takeover, services should be configured to be started at - application startup. When starting the inets application - the inets top supervisor will start a number of subsupervisors - and worker processes for handling the different services - provided. When starting services dynamically new children will - be added to the supervision tree, unless the service is started - with the stand alone option, in which case the service is linked - to the calling process and all OTP application features such as - soft upgrade are lost.

-

Services that should be configured for startup at application - startup time should be put into the erlang node configuration file - on the form:

+ Service Concept +

Each client and server in Inets is viewed as a service. + Services can be configured to be started at application startup or + dynamically in runtime. To run Inets as a distributed + application that handles application failover and takeover, + configure the services to be started at application startup. + When starting the Inets application, the Inets + top supervisor starts a number of subsupervisors and worker + processes for handling the provided services. + When starting services dynamically, new children are added to the + supervision tree, unless the service is started with the standalone + option. In this case the service is linked to the calling process + and all OTP application features, such as soft upgrade, are lost.

+

Services to be configured for startup at application startup are to + be put into the Erlang node configuration file + on the following form:

-      [{inets, [{services, ListofConfiguredServices}]}].
-    
-

For details of exactly what to put in the list of configured - services see the documentation for the services that should be - configured.

+ [{inets, [{services, ListofConfiguredServices}]}]. +

For details of what to put in the list of configured services, + see the documentation for the services to be configured.

diff --git a/lib/inets/doc/src/introduction.xml b/lib/inets/doc/src/introduction.xml new file mode 100644 index 0000000000..ef3e109df5 --- /dev/null +++ b/lib/inets/doc/src/introduction.xml @@ -0,0 +1,57 @@ + + + + +
+ + 19972013 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Introduction + Ingela Anderton Andin + + + + + 2004-09-28 + A + inets_services.xml +
+ +
+ Purpose +

Inets is a container for Internet clients and servers + including the following:

+ + An FTP client + A TFTP client and server + An client and server + +

The HTTP client and server are HTTP 1.1 compliant as + defined in + RFC 2616.

+
+ +
+ Prerequisites +

It is assumed that the reader is familiar with the Erlang + programming language, concepts of OTP, and has a basic + understanding of the FTP, TFTP, and HTTP protocols.

+
+
+ + diff --git a/lib/inets/doc/src/part.xml b/lib/inets/doc/src/part.xml index 1640ff507c..3b817eecf2 100644 --- a/lib/inets/doc/src/part.xml +++ b/lib/inets/doc/src/part.xml @@ -30,10 +30,18 @@ part.sgml -

The Inets Application provides a set of Internet - related services. Currently supported are a HTTP client, a HTTP - server a FTP client and a TFTP client and server.

+

The Inets application provides a set of + Internet-related services as follows:

+ + An FTP client + A TFTP client and server + An client and server + +

The HTTP client and server are HTTP 1.1 compliant as + defined in + RFC 2616.

+ -- cgit v1.2.3 From a2a1883e04aaa923b385cbbc496395ed5bf1dc17 Mon Sep 17 00:00:00 2001 From: tmanevik Date: Mon, 6 Jul 2015 21:21:27 +0200 Subject: Inets Reference Manual Editorial changes --- lib/inets/doc/src/ftp.xml | 467 +++++++++--------- lib/inets/doc/src/http_uri.xml | 96 ++-- lib/inets/doc/src/httpc.xml | 658 +++++++++++++------------ lib/inets/doc/src/httpd.xml | 986 +++++++++++++++++++------------------ lib/inets/doc/src/httpd_socket.xml | 24 +- lib/inets/doc/src/httpd_util.xml | 177 ++++--- lib/inets/doc/src/inets.xml | 93 ++-- lib/inets/doc/src/mod_alias.xml | 58 ++- lib/inets/doc/src/mod_auth.xml | 260 +++++----- lib/inets/doc/src/mod_esi.xml | 73 +-- lib/inets/doc/src/mod_security.xml | 106 ++-- lib/inets/doc/src/ref_man.xml | 6 +- lib/inets/doc/src/tftp.xml | 325 ++++++------ 13 files changed, 1688 insertions(+), 1641 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/ftp.xml b/lib/inets/doc/src/ftp.xml index f3d4a5c45d..2e6176d011 100644 --- a/lib/inets/doc/src/ftp.xml +++ b/lib/inets/doc/src/ftp.xml @@ -30,95 +30,94 @@ ftp.xml ftp - A File Transfer Protocol client + A File Transfer Protocol client. -

The ftp module implements a client for file transfer - according to a subset of the File Transfer Protocol (see 959).

+

This module implements a client for file transfer + according to a subset of the File Transfer Protocol (FTP), see + RFC 959.

-

Starting from inets version 4.4.1 the ftp - client will always try to use passive ftp mode and only resort - to active ftp mode if this fails. There is a start option - mode where this default behavior - may be changed.

+

As from Inets 4.4.1, the FTP + client always tries to use passive FTP mode and only resort + to active FTP mode if this fails. This default behavior can be + changed by start option mode.

-

There are two ways to start an ftp client. One is using the - Inets service framework - and the other is to start it directy as a standalone process - using the open function.

+

An FTP client can be started in two ways. One is using the + Inets service framework, + the other is to start it directly as a standalone process + using function open.

-

For a simple example of an ftp session see - Inets User's Guide.

+

For a simple example of an FTP session, see + Inets User's Guide.

In addition to the ordinary functions for receiving and sending - files (see recv/2, recv/3, send/2 and + files (see recv/2, recv/3, send/2, and send/3) there are functions for receiving remote files as - binaries (see recv_bin/2) and for sending binaries to to be + binaries (see recv_bin/2) and for sending binaries to be stored as remote files (see send_bin/3).

-

There is also a set of functions for sending and receiving - contiguous parts of a file to be stored in a remote file (for send - see send_chunk_start/2, send_chunk/2 and - send_chunk_end/1 and for receive see +

A set of functions is provvided for sending and receiving + contiguous parts of a file to be stored in a remote file. For send, + see send_chunk_start/2, send_chunk/2, and + send_chunk_end/1. For receive, see recv_chunk_start/2 and recv_chunk/).

-

The particular return values of the functions below depend very +

The return values of the following functions depend much on the implementation of the FTP server at the remote - host. In particular the results from ls and nlist + host. In particular, the results from ls and nlist varies. Often real errors are not reported as errors by ls, - even if for instance a file or directory does not + even if, for example, a file or directory does not exist. nlist is usually more strict, but some implementations have the peculiar behaviour of responding with an - error, if the request is a listing of the contents of directory - which exists but is empty.

+ error if the request is a listing of the contents of a directory + that exists but is empty.

- FTP CLIENT SERVICE START/STOP + FTP CLIENT SERVICE START/STOP

The FTP client can be started and stopped dynamically in runtime by - calling the Inets application API + calling the Inets application API inets:start(ftpc, ServiceConfig), or inets:start(ftpc, ServiceConfig, How), and inets:stop(ftpc, Pid). - See inets(3) for more info.

-

Below follows a description of - the available configuration options.

+ For details, see inets(3).

+ +

The available configuration options are as follows:

{host, Host} -

Host = string() | ip_address()

+

Host = string() | ip_address()

{port, Port} -

Port = integer() > 0

-

Default is 21.

+

Port = integer() > 0

+

Default is 21.

{mode, Mode} -

Mode = active | passive

-

Default is passive.

+

Mode = active | passive

+

Default is passive.

{verbose, Verbose}

Verbose = boolean()

-

This determines if the FTP communication should be - verbose or not.

-

Default is false.

+

Determines if the FTP communication is to be + verbose or not.

+

Default is false.

{debug, Debug} @@ -126,93 +125,90 @@

Debug = trace | debug | disable

Debugging using the dbg toolkit.

-

Default is disable.

+

Default is disable.

{ipfamily, IpFamily}

IpFamily = inet | inet6 | inet6fb4

-

With inet6fb4 the client behaves as before - (it tries to use IPv6 and only if that does not work, it - uses IPv4).

-

Default is inet (IPv4).

+

With inet6fb4 the client behaves as before, that is, + tries to use IPv6, and only if that does not work it + uses IPv4).

+

Default is inet (IPv4).

{timeout, Timeout} -

Timeout = non_neg_integer()

-

Connection timeout.

-

Default is 60000 (milliseconds).

+

Timeout = non_neg_integer()

+

Connection time-out.

+

Default is 60000 (milliseconds).

{dtimeout, DTimeout}

DTimeout = non_neg_integer() | infinity

-

Data Connect timeout. - The time the client will wait for the server to connect to the - data socket.

-

Default is infinity.

+

Data connect time-out. + The time the client waits for the server to connect to the + data socket.

+

Default is infinity.

{progress, Progress}

Progress = ignore | {CBModule, CBFunction, InitProgress}

-

CBModule = atom(), CBFunction = atom()

-

InitProgress = term()

-

Default is ignore.

+

CBModule = atom(), CBFunction = atom()

+

InitProgress = term()

+

Default is ignore.

-

The progress option is intended to be used by applications that - want to create some type of progress report such as a progress bar in - a GUI. The default value for the progress option is ignore - e.i. the option is not used. When the progress option is - specified the following will happen when ftp:send/[3,4] or - ftp:recv/[3,4] are called.

+

Option progress is intended to be used by applications that + want to create some type of progress report, such as a progress bar in + a GUI. Default for the progress option is ignore, + that is, the option is not used. When the progress option is + specified, the following happens when ftp:send/[3,4] or + ftp:recv/[3,4] are called:

-

Before a file is transfered the following call will - be made to indicate the start of the file transfer and how big +

Before a file is transferred, the following call is + made to indicate the start of the file transfer and how large the file is. The return value of the callback function - should be a new value for the UserProgressTerm that will - bu used as input next time the callback function is + is to be a new value for the UserProgressTerm that will + be used as input the next time the callback function is called.

-

CBModule:CBFunction(InitProgress, File, {file_size, FileSize})

-

-

Every time a chunk of bytes is transfered the - following call will be made:

-

+

Every time a chunk of bytes is transferred the + following call is made:

- CBModule:CBFunction(UserProgressTerm, File, {transfer_size, TransferSize})

-

+ CBModule:CBFunction(UserProgressTerm, File, {transfer_size, TransferSize}) +

-

At the end of the file the following call will be - made to indicate the end of the transfer.

-

+

At the end of the file the following call is + made to indicate the end of the transfer:

- CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0})

-

+ CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0}) +

-

The callback function should be defined as

+

The callback function is to be defined as follows:

- CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm

+ CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm +

CBModule = CBFunction = atom() @@ -227,50 +223,51 @@

- Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown}

+ Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown} +

-

Alas for remote files it is not possible for ftp to determine the +

For remote files, ftp cannot determine the file size in a platform independent way. In this case the size - will be unknown and it is left to the application to find - out the size.

+ becomes unknown and it is left to the application to + determine the size.

The callback is made by a middleman process, hence the - file transfer will not be affected by the code in the progress - callback function. If the callback should crash this will be - detected by the ftp connection process that will print an - info-report and then go one as if the progress option was set - to ignore.

+ file transfer is not affected by the code in the progress + callback function. If the callback crashes, this is + detected by the FTP connection process, which then prints an + info-report and goes on as if the progress option was set + to ignore.

The file transfer type is set to the default of the FTP server - when the session is opened. This is usually ASCCI-mode. + when the session is opened. This is usually ASCCI mode.

-

The current local working directory (cf. lpwd/1) is set to - the value reported by file:get_cwd/1. the wanted +

The current local working directory (compare lpwd/1) is set + to the value reported by file:get_cwd/1, the wanted local directory.

The return value Pid is used as a reference to the - newly created ftp client in all other functions, and they should - be called by the process that created the connection. The ftp + newly created FTP client in all other functions, and they are to + be called by the process that created the connection. The FTP client process monitors the process that created it and - will terminate if that process terminates.

+ terminates if that process terminates.

- COMMON DATA TYPES -

Here follows type definitions that are used by more than one - function in the FTP client API.

-

pid() - identifier of an ftp connection.

-

string() = list of ASCII characters.

-

shortage_reason() = etnospc | epnospc

-

restriction_reason() = epath | efnamena | elogin | enotbinary - - note not all restrictions may always relevant to all functions -

-

common_reason() = econn | eclosed | term() - some kind of - explanation of what went wrong.

+ DATA TYPES +

The following type definitions are used by more than one + function in the FTP client API:

+

pid() = identifier of an FTP connection

+

string() = list of ASCII characters

+

shortage_reason() = etnospc | epnospc

+

restriction_reason() = epath | efnamena | elogin | enotbinary + - all restrictions are not always relevant to all functions +

+

common_reason() = econn | eclosed | term() + - some explanation of what went wrong

@@ -278,15 +275,14 @@ account(Pid, Account) -> ok | {error, Reason} - Specify which account to use. + Specifies which account to use. Pid = pid() Account = string() Reason = eacct | common_reason() -

If an account is needed for an operation set the account - with this operation.

+

Sets the account for an operation, if needed.

@@ -297,7 +293,8 @@ append(Pid, LocalFile) -> append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason} - Transfer file to remote server, and append it to Remotefile. + Transfers a file to remote server, and appends it to + Remotefile. Pid = pid() LocalFile = RemoteFile = string() @@ -306,9 +303,9 @@

Transfers the file LocalFile to the remote server. If RemoteFile is specified, the name of the remote file that the - file will be appended to is set to RemoteFile; otherwise - the name is set to LocalFile If the file does not exists the - file will be created.

+ file is appended to is set to RemoteFile, otherwise + to LocalFile. If the file does not exists, + it is created.

@@ -316,17 +313,17 @@ append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason} - Transfer a binary into a remote file. + Transfers a binary into a remote file. Pid = pid() Bin = binary()() RemoteFile = string() - Reason = restriction_reason()| shortage_reason() | common_reason() + Reason = restriction_reason()| shortage_reason() | common_reason() -

Transfers the binary Bin to the remote server and append - it to the file RemoteFile. If the file does not exists it - will be created.

+

Transfers the binary Bin to the remote server and appends + it to the file RemoteFile. If the file does not exist, it + is created.

@@ -334,18 +331,18 @@ append_chunk(Pid, Bin) -> ok | {error, Reason} - append a chunk to the remote file. + Appends a chunk to the remote file. Pid = pid() Bin = binary() Reason = echunk | restriction_reason() | common_reason() -

Transfer the chunk Bin to the remote server, which - append it into the file specified in the call to - append_chunk_start/2.

-

Note that for some errors, e.g. file system full, it is - necessary to to call append_chunk_end to get the +

Transfers the chunk Bin to the remote server, which + appends it to the file specified in the call to + append_chunk_start/2.

+

For some errors, for example, file system full, it is + necessary to call append_chunk_end to get the proper reason.

@@ -354,16 +351,16 @@ append_chunk_start(Pid, File) -> ok | {error, Reason} - Start transfer of file chunks for appending to File. + Starts transfer of file chunks for appending to File. Pid = pid() File = string() Reason = restriction_reason() | common_reason() -

Start the transfer of chunks for appending to the file - File at the remote server. If the file does not exists - it will be created.

+

Starts the transfer of chunks for appending to the file + File at the remote server. If the file does not exist, + it is created.

@@ -371,7 +368,7 @@ append_chunk_end(Pid) -> ok | {error, Reason} - Stop transfer of chunks for appending. + Stops transfer of chunks for appending. Pid = pid() Reason = echunk | restriction_reason() | shortage_reason() @@ -379,7 +376,7 @@

Stops transfer of chunks for appending to the remote server. The file at the remote server, specified in the call to - append_chunk_start/2 is closed by the server.

+ append_chunk_start/2, is closed by the server.

@@ -387,7 +384,7 @@ cd(Pid, Dir) -> ok | {error, Reason} - Change remote working directory. + Changes remote working directory. Pid = pid() Dir = string() @@ -403,13 +400,13 @@ close(Pid) -> ok - End the ftp session. + Ends the FTP session. Pid = pid() -

Ends an ftp session, created using the - open function.

+

Ends an FTP session, created using function + open.

@@ -417,7 +414,7 @@ delete(Pid, File) -> ok | {error, Reason} - Delete a file at the remote server.. + Deletes a file at the remote server. Pid = pid() File = string() @@ -432,7 +429,7 @@ formaterror(Tag) -> string() - Return error diagnostics. + Returns error diagnostics. Tag = {error, atom()} | atom() @@ -446,14 +443,14 @@ lcd(Pid, Dir) -> ok | {error, Reason} - Change local working directory. + Changes local working directory. Pid = pid() Dir = string() Reason = restriction_reason() -

Changes the working directory to Dir for the local client.

+

Changes the working directory to Dir for the local client.

@@ -461,7 +458,7 @@ lpwd(Pid) -> {ok, Dir} - Get local current working directory. + Gets local current working directory. Pid = pid() @@ -485,13 +482,13 @@ Reason = restriction_reason() | common_reason()
-

Returns a list of files in long format.

-

Pathname can be a directory, a group of files or - even a file. The Pathname string can contain wildcard(s).

-

ls/1 implies the user's current remote directory.

-

The format of Listing is operating system dependent - (on UNIX it is typically produced from the output of the - ls -l shell command).

+

Returns a list of files in long format.

+

Pathname can be a directory, a group of files, or + a file. The Pathname string can contain wildcards.

+

ls/1 implies the current remote directory of the user.

+

The format of Listing depends on the operating system. + On UNIX, it is typically produced from the output of the + ls -l shell command.

@@ -499,7 +496,7 @@ mkdir(Pid, Dir) -> ok | {error, Reason} - Create remote directory. + Creates a remote directory. Pid = pid() Dir = string() @@ -525,15 +522,15 @@ Reason = restriction_reason() | common_reason() -

Returns a list of files in short format.

-

Pathname can be a directory, a group of files or - even a file. The Pathname string can contain wildcard(s).

-

nlist/1 implies the user's current remote directory.

+

Returns a list of files in short format.

+

Pathname can be a directory, a group of files, or + a file. The Pathname string can contain wildcards.

+

nlist/1 implies the current remote directory of the user.

The format of Listing is a stream of - file names, where each name is separated by <CRLF> or - <NL>. Contrary to the ls function, the purpose of - nlist is to make it possible for a program to - automatically process file name information.

+ filenames where each filename is separated by <CRLF> or + <NL>. Contrary to function ls, the purpose of + nlist is to enable a program to + process filename information automatically.

@@ -542,23 +539,23 @@ open(Host) -> {ok, Pid} | {error, Reason} open(Host, Opts) -> {ok, Pid} | {error, Reason} - Start an standalone ftp client. + Starts a standalone FTP client. Host = string() | ip_address() Opts = options() options() = [option()] option() = start_option() | open_option() start_option() = {verbose, verbose()} | {debug, debug()} - verbose() = boolean() (defaults to false) - debug() = disable | debug | trace (defaults to disable) + verbose() = boolean() (default is false) + debug() = disable | debug | trace (default is disable) open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()} - ipfamily() = inet | inet6 | inet6fb4 (defaults to inet) - port() = integer() > 0 (defaults to 21) - mode() = active | passive (defaults to passive) + ipfamily() = inet | inet6 | inet6fb4 (default is inet) + port() = integer() > 0 (default is 21) + mode() = active | passive (default is passive) tls_options() = [ssl:ssloption()] - timeout() = integer() > 0 (defaults to 60000 milliseconds) - dtimeout() = integer() > 0 | infinity (defaults to infinity) - pogress() = ignore | {module(), function(), initial_data()} (defaults to ignore) + timeout() = integer() > 0 (default is 60000 milliseconds) + dtimeout() = integer() > 0 | infinity (default is infinity) + pogress() = ignore | {module(), function(), initial_data()} (default is ignore) module() = atom() function() = atom() initial_data() = term() @@ -566,16 +563,20 @@ -

This function is used to start a standalone ftp client process - (without the inets service framework) and - open a session with the FTP server at Host.

+

Starts a standalone FTP client process + (without the Inets service framework) and + opens a session with the FTP server at Host.

-

If the option {tls, tls_options()} is present, the ftp session will be transported over tls (ftps, see -RFC 4217). The list tls_options() may be empty. The function ssl:connect/3 is used for securing both the control connection and the data sessions. +

If option {tls, tls_options()} is present, the FTP session + is transported over tls (ftps, see + RFC 4217). + The list tls_options() can be empty. The function + ssl:connect/3 + is used for securing both the control connection and the data sessions.

-

A session opened in this way, is closed using the - close function.

+

A session opened in this way is closed using function + close.

@@ -583,22 +584,10 @@ pwd(Pid) -> {ok, Dir} | {error, Reason} - Get remote current working directory. - - Pid = pid() - Reason = restriction_reason() | common_reason() - - -

Returns the current working directory at the remote server.

-
-
- - - pwd(Pid) -> {ok, Dir} | {error, Reason} - Get remote current working directory. + Gets the remote current working directory. Pid = pid() - Reason = restriction_reason() | common_reason() + Reason = restriction_reason() | common_reason()

Returns the current working directory at the remote server.

@@ -612,7 +601,7 @@ recv(Pid, RemoteFile) -> recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason} - Transfer file from remote server. + Transfers a file from remote server. Pid = pid() RemoteFile = LocalFile = string() @@ -620,14 +609,14 @@ file_write_error_reason() = see file:write/2 -

Transfer the file RemoteFile from the remote server - to the the file system of the local client. If +

Transfers the file RemoteFile from the remote server + to the file system of the local client. If LocalFile is specified, the local file will be - LocalFile; otherwise it will be + LocalFile, otherwise RemoteFile.

-

If the file write fails - (e.g. enospc), then the command is aborted and {error, file_write_error_reason()} is returned. The file is - however not removed.

+

If the file write fails (for example, enospc), the command is + aborted and {error, file_write_error_reason()} is returned. + However, the file is not removed.

@@ -635,7 +624,7 @@ recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason} - Transfer file from remote server as a binary. + Transfers a file from remote server as a binary. Pid = pid() Bin = binary() @@ -652,14 +641,14 @@ recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason} - Start chunk-reading of the remote file. + Starts chunk-reading of the remote file. Pid = pid() RemoteFile = string() Reason = restriction_reason() | common_reason() -

Start transfer of the file RemoteFile from the +

Starts transfer of the file RemoteFile from the remote server.

@@ -668,20 +657,20 @@ recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason} - Receive a chunk of the remote file. + Receives a chunk of the remote file. Pid = pid() Bin = binary() Reason = restriction_reason() | common_reason() -

Receive a chunk of the remote file (RemoteFile of - recv_chunk_start). The return values has the following +

Receives a chunk of the remote file (RemoteFile of + recv_chunk_start). The return values have the following meaning:

- ok the transfer is complete. - {ok, Bin} just another chunk of the file. - {error, Reason} transfer failed. + ok = the transfer is complete. + {ok, Bin} = just another chunk of the file. + {error, Reason} = transfer failed. @@ -690,7 +679,7 @@ rename(Pid, Old, New) -> ok | {error, Reason} - Rename a file at the remote server.. + Renames a file at the remote server. Pid = pid() CurrFile = NewFile = string() @@ -705,7 +694,7 @@ rmdir(Pid, Dir) -> ok | {error, Reason} - Remove a remote directory. + Removes a remote directory. Pid = pid() Dir = string() @@ -723,7 +712,7 @@ send(Pid, LocalFile) -> send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason} - Transfer file to remote server. + Transfers a file to the remote server. Pid = pid() LocalFile = RemoteFile = string() @@ -732,7 +721,7 @@

Transfers the file LocalFile to the remote server. If RemoteFile is specified, the name of the remote file is set - to RemoteFile; otherwise the name is set to LocalFile.

+ to RemoteFile, otherwise to LocalFile.

@@ -740,7 +729,7 @@ send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason} - Transfer a binary into a remote file. + Transfers a binary into a remote file. Pid = pid() Bin = binary()() @@ -757,17 +746,17 @@ send_chunk(Pid, Bin) -> ok | {error, Reason} - Write a chunk to the remote file. + Writes a chunk to the remote file. Pid = pid() Bin = binary() Reason = echunk | restriction_reason() | common_reason() -

Transfer the chunk Bin to the remote server, which +

Transfers the chunk Bin to the remote server, which writes it into the file specified in the call to - send_chunk_start/2.

-

Note that for some errors, e.g. file system full, it is + send_chunk_start/2.

+

For some errors, for example, file system full, it is necessary to to call send_chunk_end to get the proper reason.

@@ -777,14 +766,14 @@ send_chunk_start(Pid, File) -> ok | {error, Reason} - Start transfer of file chunks. + Starts transfer of file chunks. Pid = pid() File = string() Reason = restriction_reason() | common_reason() -

Start transfer of chunks into the file File at the +

Starts transfer of chunks into the file File at the remote server.

@@ -793,7 +782,7 @@ send_chunk_end(Pid) -> ok | {error, Reason} - Stop transfer of chunks. + Stops transfer of chunks. Pid = pid() Reason = restriction_reason() | common_reason() | shortage_reason() @@ -809,7 +798,7 @@ type(Pid, Type) -> ok | {error, Reason} - Set transfer type to asciior binary. + Sets transfer type to asciior binary. Pid = pid() Type = ascii | binary @@ -817,8 +806,8 @@

Sets the file transfer type to ascii or binary. When - an ftp session is opened, the default transfer type of the - server is used, most often ascii, which is the default + an FTP session is opened, the default transfer type of the + server is used, most often ascii, which is default according to RFC 959.

@@ -857,21 +846,22 @@ quote(Pid, Command) -> [FTPLine] - Sends an arbitrary FTP command. + Sends an arbitrary FTP command. Pid = pid() Command = string() - FTPLine = string() - Note the telnet end of line characters, from the ftp protocol definition, CRLF e.g. "\\r\\n" has been removed. - - -

Sends an arbitrary FTP command and returns verbatimly a list - of the lines sent back by the FTP server. This functions is - intended to give an application accesses to FTP commands - that are server specific or that may not be provided by - this FTP client.

+ FTPLine = string( +
+

The telnet end of line characters, from the FTP + protocol definition, CRLF, for example, "\\r\\n" has been removed.

+

Sends an arbitrary FTP command and returns verbatim a list + of the lines sent back by the FTP server. This function is + intended to give application accesses to FTP commands + that are server-specific or that cannot be provided by + this FTP client.

-

FTP commands that require a data connection can not be - successfully issued with this function.

+

FTP commands requiring a data connection cannot be + successfully issued with this function.

@@ -885,30 +875,31 @@ echunk -

Synchronisation error during chunk sending. -

-

A call has been made to send_chunk/2 or - send_chunk_end/1, before a call to - send_chunk_start/2; or a call has been made to another - transfer function during chunk sending, i.e. before a call - to send_chunk_end/1.

+

Synchronization error during chunk sending according to one + of the following: +

+ >A call is made to send_chunk/2 or send_chunk_end/1 + before a call to send_chunk_start/2. + A call has been made to another transfer function during chunk + sending, that is, before a call to send_chunk_end/1. +
eclosed -

The session has been closed.

+

The session is closed.

econn -

Connection to remote server prematurely closed.

+

Connection to the remote server is prematurely closed.

ehost -

Host not found, FTP server not found, or connection rejected +

Host is not found, FTP server is not found, or connection is rejected by FTP server.

elogin -

User not logged in.

+

User is not logged in.

enotbinary @@ -925,7 +916,7 @@ euser -

User name or password not valid.

+

Invalid username or password.

etnospc @@ -938,7 +929,7 @@ efnamena -

File name not allowed [553].

+

Filename not allowed [553].

diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml index c71bfbd686..47c40da96a 100644 --- a/lib/inets/doc/src/http_uri.xml +++ b/lib/inets/doc/src/http_uri.xml @@ -35,38 +35,45 @@

This module provides utility functions for working with URIs, - according to RFC 3986.

- + according to + RFC 3986.

- COMMON DATA TYPES + DATA TYPES

Type definitions that are used more than once in this module:

- +

boolean() = true | false

+

string() = list of ASCII characters

- URI DATA TYPES + URI DATA TYPES

Type definitions that are related to URI:

-

For more information about URI, see RFC 3986.

- - - + + + uri() = string() +

Syntax according to the URI definition in RFC 3986, + for example, "http://www.erlang.org/"

+ user_info() = string() +

+ scheme() = atom() +

Example: http, https

+ host() = string() +

+ port() = pos_integer() +

+ path() = string() +

Represents a file path or directory path

+ query() = string() +

+ fragment() = string() +

+
+ +

For more information about URI, see + RFC 3986.

@@ -74,28 +81,28 @@ fragment() = string() decode(HexEncodedURI) -> URI - Decode a hex encoded URI + Decodes a hexadecimal encoded URI. - HexEncodedURI = string() - A possibly hex encoded uri + HexEncodedURI = string() - A possibly hexadecimal encoded URI URI = uri() -

Decode a possibly hex encoded URI.

+

Decodes a possibly hexadecimal encoded URI.

encode(URI) -> HexEncodedURI - Hex encode an URI + Encodes a hexadecimal encoded URI. URI = uri() - HexEncodedURI = string() - Hex encoded uri + HexEncodedURI = string() - Hexadecimal encoded URI -

Hex encode an URI.

+

Encodes a hexadecimal encoded URI.

@@ -104,10 +111,10 @@ fragment() = string() parse(URI) -> {ok, Result} | {error, Reason} parse(URI, Options) -> {ok, Result} | {error, Reason} - Parse an URI + Parses a URI. - URI = uri() - Options = [Option] + URI = uri() + Options = [Option] Option = {ipv6_host_with_brackets, boolean()} | {scheme_defaults, scheme_defaults()} | {fragment, boolean()}] @@ -119,20 +126,20 @@ fragment() = string() Path = path() Query = query() Fragment = fragment() - Reason = term() + Reason = term() -

This function is used to parse an URI. If no scheme defaults - are provided, the value of +

Parses a URI. If no scheme defaults + are provided, the value of the scheme_defaults - function will be used.

+ function is used.

-

Note that when parsing an URI with an unknown scheme (that is, - a scheme not found in the scheme defaults) a port number must be - provided or else the parsing will fail.

+

When parsing a URI with an unknown scheme (that is, + a scheme not found in the scheme defaults), a port number must be + provided, otherwise the parsing fails.

-

If the fragment option is true, the URI fragment will be returned as - part of the parsing result, otherwise it is completely ignored.

+

If the fragment option is true, the URI fragment is returned as + part of the parsing result, otherwise it is ignored.

@@ -140,14 +147,14 @@ fragment() = string() scheme_defaults() -> SchemeDefaults - A list of scheme and their default ports + A list of the scheme and their default ports. SchemeDefaults = [{scheme(), default_scheme_port_number()}] default_scheme_port_number() = pos_integer() -

This function provides a list of the scheme and their default - port numbers currently supported (by default) by this utility.

+

Provides a list of the scheme and their default + port numbers supported (by default) by this utility.

@@ -160,7 +167,8 @@ fragment() = string() hexlist_to_integer(HexString) -> Number @@ -165,8 +121,6 @@

hexlist_to_integer converts the hexadecimal value of HexString to an integer.

- -
@@ -178,11 +132,8 @@ HexString = string() -

integer_to_hexlist/1 returns a string representing Number in a hexadecimal form.

- -
@@ -205,8 +156,6 @@ returned. lookup/2 returns undefined and lookup/3 returns Undefined if no Value is found.

- -
@@ -221,14 +170,11 @@ Undefined = term() -

lookup_mime returns the MIME type associated with a specific file suffix as specified in the file mime.types (located in the config directory).

- -
@@ -244,7 +190,6 @@ Undefined = term() -

lookup_mime_default returns the MIME type associated with a specific file suffix as specified in the mime.types file (located in the @@ -252,8 +197,6 @@ config directory). If no appropriate association is found, the value of DefaultType is returned.

- -
@@ -267,7 +210,6 @@ Message = string() -

message/3 returns an informative HTTP 1.1 status string in HTML. Each StatusCode requires a specific PhraseArgs: @@ -290,8 +232,6 @@

string(): A string describing why the service was unavailable.

- - @@ -303,12 +243,9 @@ Month = string() -

month/1 converts the month NthMonth as an integer (1-12) to an abbreviated string, that is:

1 = "Jan", 2 = "Feb", ..., 12 = "Dec".

- -
@@ -324,8 +261,6 @@

multi_lookup extracts all {Key,Value} tuples from an ETSTable and returns all Values associated with Key in a list.

- - @@ -341,7 +276,6 @@ HTTP 1.1 StatusCode, for example, 200 is "OK" and 201 is "Created". For more information, see RFC 2616.

- @@ -354,12 +288,9 @@ RFC1123Date = string() -

rfc1123_date/0 returns the current date in RFC 1123 format. rfc_date/1 converts the date in the Erlang format to the RFC 1123 date format.

- -
@@ -373,14 +304,11 @@ N = integer -

split/3 splits String in N chunks using RegExp. split/3 is equivalent to regexp:split/2 with the exception that N defines the maximum number of fields in FieldList.

- -
@@ -394,13 +322,10 @@ Path = QueryString = PathInfo = string() -

split_script_path/1 is equivalent to split_path/1 with one exception. If the longest possible path is not a regular, accessible, and executable file, then not_a_script is returned.

- -
@@ -412,7 +337,6 @@ RequestLine = Path = QueryStringOrPathInfo = string() -

split_path/1 splits RequestLine in a file reference (Path), and a QueryString or a PathInfo string as specified in @@ -428,8 +352,6 @@ Path, isolated with a /, is regarded as PathInfo. The resulting Path is decoded using decode_hex/1 before delivery.

- -
@@ -441,12 +363,9 @@ String = Stripped = string() -

strip/1 removes any leading or trailing linear white space from the string. Linear white space is to be read as horizontal tab or space.

- -
@@ -457,7 +376,6 @@ FileName = Suffix = string() -

suffix/1 is equivalent to filename:extension/1 with the exception that Suffix is returned without a leading dot (.).

@@ -466,7 +384,6 @@
- SEE ALSO

httpd(3)

diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml index 2bb5427465..5d071c9a48 100644 --- a/lib/inets/doc/src/inets.xml +++ b/lib/inets/doc/src/inets.xml @@ -119,17 +119,6 @@
- - stop() -> ok - Stops the Inets application. - -

Stops the Inets application. See also - application(3).

- - -
-
- start(Service, ServiceConfig) -> {ok, Pid} | {error, Reason} start(Service, ServiceConfig, How) -> {ok, Pid} | {error, Reason} @@ -166,6 +155,17 @@ + + stop() -> ok + Stops the Inets application. + +

Stops the Inets application. See also + application(3).

+ + +
+
+ stop(Service, Reference) -> ok | {error, Reason} Stops a started service of the Inets application or takes diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml index 8bef025be8..2da2be37ed 100644 --- a/lib/inets/doc/src/mod_auth.xml +++ b/lib/inets/doc/src/mod_auth.xml @@ -34,11 +34,36 @@

This module provides for basic user authentication using textual files, Dets databases, or Mnesia databases.

- -
+ + add_group_member(GroupName, UserName, Options) -> true | {error, Reason} + add_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason} + add_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason} + Adds a user to a group. + + GroupName = string() + UserName = string() + Options = [Option] + Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} + Port = integer() + Address = {A,B,C,D} | string() | undefined + Dir = string() + AuthPassword = string() + Reason = term() + + +

add_group_member/3, add_group_member/4, and + add_group_member/5 each + adds a user to a group. If the group does not exist, it + is created and the user is added to the group. Upon successful + operation, this function returns true. + When add_group_members/3 + is called, options Port and Dir are mandatory.

+
+
+ add_user(UserName, Options) -> true| {error, Reason} add_user(UserName, Password, UserData, Port, Dir) -> true | {error, Reason} @@ -57,53 +82,45 @@ Reason = term() - -

add_user/2, add_user/5, and add_user/6 each adds a user to the user database. If the operation is successful, this function returns true. If an error occurs, {error,Reason} is returned. When add_user/2 is called, options Password, UserData, Port, and Dir are mandatory.

- -
- - delete_user(UserName,Options) -> true | {error, Reason} - delete_user(UserName, Port, Dir) -> true | {error, Reason} - delete_user(UserName, Address, Port, Dir) -> true | {error, Reason} - Deletes a user from the user database. + + delete_group(GroupName, Options) -> true | {error,Reason} <name>delete_group(GroupName, Port, Dir) -> true | {error, Reason} + delete_group(GroupName, Address, Port, Dir) -> true | {error, Reason} + Deletes a group. - UserName = string() Options = [Option] Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} Port = integer() Address = {A,B,C,D} | string() | undefined Dir = string() + GroupName = string() AuthPassword = string() Reason = term() - -

delete_user/2, delete_user/3, and delete_user/4 - each deletes a user from the user database. - If the operation is successful, this function returns true. - If an error occurs, {error,Reason} is returned. - When delete_user/2 is called, options Port and Dir - are mandatory.

- - +

delete_group/2, delete_group/3, and delete_group/4 + each deletes the group specified and returns true. + If there is an error, {error, Reason} is returned. + When delete_group/2 is called, option + Port and Dir are mandatory.

- - get_user(UserName,Options) -> {ok, #httpd_user} |{error, Reason} - get_user(UserName, Port, Dir) -> {ok, #httpd_user} | {error, Reason} - get_user(UserName, Address, Port, Dir) -> {ok, #httpd_user} | {error, Reason} - Returns a user from the user database. + + delete_group_member(GroupName, UserName, Options) -> true | {error, Reason} + delete_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason} + delete_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason} + Removes a user from a group. + GroupName = string() UserName = string() Options = [Option] Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} @@ -114,51 +131,46 @@ Reason = term() - -

get_user/2, get_user/3, and get_user/4 each - returns an httpd_user record containing the userdata for a - specific user. If the user cannot be found, {error, Reason} - is returned. When get_user/2 is called, options Port and Dir - are mandatory.

- - +

delete_group_member/3, delete_group_member/4, and + delete_group_member/5 each deletes a user from a group. + If the group or the user does not exist, + this function returns an error, otherwise true. + When delete_group_member/3 is called, the options Port + and Dir are mandatory.

- + - list_users(Options) -> {ok, Users} | {error, Reason} - list_users(Port, Dir) -> {ok, Users} | {error, Reason} - list_users(Address, Port, Dir) -> {ok, Users} | {error, Reason} - Lists users in the user database. + delete_user(UserName,Options) -> true | {error, Reason} + delete_user(UserName, Port, Dir) -> true | {error, Reason} + delete_user(UserName, Address, Port, Dir) -> true | {error, Reason} + Deletes a user from the user database. + UserName = string() Options = [Option] Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} Port = integer() Address = {A,B,C,D} | string() | undefined Dir = string() - Users = list() AuthPassword = string() - Reason = atom() + Reason = term() - -

list_users/1, list_users/2, and list_users/3 - each returns a list - of users in the user database for a specific Port/Dir. - When list_users/1 is called, options Port and Dir +

delete_user/2, delete_user/3, and delete_user/4 + each deletes a user from the user database. + If the operation is successful, this function returns true. + If an error occurs, {error,Reason} is returned. + When delete_user/2 is called, options Port and Dir are mandatory.

- -
- add_group_member(GroupName, UserName, Options) -> true | {error, Reason} - add_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason} - add_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason} - Adds a user to a group. + get_user(UserName,Options) -> {ok, #httpd_user} |{error, Reason} + get_user(UserName, Port, Dir) -> {ok, #httpd_user} | {error, Reason} + get_user(UserName, Address, Port, Dir) -> {ok, #httpd_user} | {error, Reason} + Returns a user from the user database. - GroupName = string() UserName = string() Options = [Option] Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} @@ -169,48 +181,38 @@ Reason = term() - -

add_group_member/3, add_group_member/4, and - add_group_member/5 each - adds a user to a group. If the group does not exist, it - is created and the user is added to the group. Upon successful - operation, this function returns true. - When add_group_members/3 - is called, options Port and Dir are mandatory.

- - +

get_user/2, get_user/3, and get_user/4 each + returns an httpd_user record containing the userdata for a + specific user. If the user cannot be found, {error, Reason} + is returned. When get_user/2 is called, options Port and Dir + are mandatory.

- - delete_group_member(GroupName, UserName, Options) -> true | {error, Reason} - delete_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason} - delete_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason} - Removes a user from a group. + + list_groups(Options) -> {ok, Groups} | {error, Reason} + list_groups(Port, Dir) -> {ok, Groups} | {error, Reason} + list_groups(Address, Port, Dir) -> {ok, Groups} | {error, Reason} + Lists all the groups. - GroupName = string() - UserName = string() Options = [Option] Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} Port = integer() Address = {A,B,C,D} | string() | undefined Dir = string() + Groups = list() AuthPassword = string() Reason = term() - -

delete_group_member/3, delete_group_member/4, and - delete_group_member/5 each deletes a user from a group. - If the group or the user does not exist, - this function returns an error, otherwise true. - When delete_group_member/3 is called, the options Port +

list_groups/1, list_groups/2, and list_groups/3 + each lists all the groups available. + If there is an error, {error, Reason} is returned. + When list_groups/1 is called, options Port and Dir are mandatory.

- -
- + list_group_members(GroupName, Options) -> {ok, Users} | {error, Reason} list_group_members(GroupName, Port, Dir) -> {ok, Users} | {error, Reason} @@ -228,71 +230,39 @@ Reason = term() -

list_group_members/2, list_group_members/3, and list_group_members/4 each lists the members of a specified group. If the group does not exist or there is an error, {error, Reason} is returned. When list_group_members/2 is called, options Port and Dir are mandatory.

- - -
-
- - - list_groups(Options) -> {ok, Groups} | {error, Reason} - list_groups(Port, Dir) -> {ok, Groups} | {error, Reason} - list_groups(Address, Port, Dir) -> {ok, Groups} | {error, Reason} - Lists all the groups. - - Options = [Option] - Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} - Port = integer() - Address = {A,B,C,D} | string() | undefined - Dir = string() - Groups = list() - AuthPassword = string() - Reason = term() - - - -

list_groups/1, list_groups/2, and list_groups/3 - each lists all the groups available. - If there is an error, {error, Reason} is returned. - When list_groups/1 is called, options Port - and Dir are mandatory.

- -
- - delete_group(GroupName, Options) -> true | {error,Reason} <name>delete_group(GroupName, Port, Dir) -> true | {error, Reason} - delete_group(GroupName, Address, Port, Dir) -> true | {error, Reason} - Deletes a group. + + list_users(Options) -> {ok, Users} | {error, Reason} + list_users(Port, Dir) -> {ok, Users} | {error, Reason} + list_users(Address, Port, Dir) -> {ok, Users} | {error, Reason} + Lists users in the user database. Options = [Option] Option = {port,Port} | {addr,Address} | {dir,Directory} | {authPassword,AuthPassword} Port = integer() Address = {A,B,C,D} | string() | undefined Dir = string() - GroupName = string() + Users = list() AuthPassword = string() - Reason = term() + Reason = atom() - -

delete_group/2, delete_group/3, and delete_group/4 - each deletes the group specified and returns true. - If there is an error, {error, Reason} is returned. - When delete_group/2 is called, option - Port and Dir are mandatory.

- - +

list_users/1, list_users/2, and list_users/3 + each returns a list + of users in the user database for a specific Port/Dir. + When list_users/1 is called, options Port and Dir + are mandatory.

- + update_password(Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason} update_password(Address,Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason} @@ -307,7 +277,6 @@ Reason = term() -

update_password/5 and update_password/6 each updates AuthAccessPassword for the specified directory. If NewPassword is equal to "NoPassword", no password is required to @@ -319,7 +288,6 @@

- SEE ALSO

httpd(3), mod_alias(3)

diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml index 7aae98e1cf..9dc32b971b 100644 --- a/lib/inets/doc/src/mod_security.xml +++ b/lib/inets/doc/src/mod_security.xml @@ -35,6 +35,26 @@

Security Audit and Trailing Functionality

+ + + block_user(User, Port, Dir, Seconds) -> true | {error, Reason} + block_user(User, Address, Port, Dir, Seconds) -> true | {error, Reason} + Blocks a user from access to a directory for a certain amount of time. + + User = string() + Port = integer() + Address = {A,B,C,D} | string() | undefined + Dir = string() + Seconds = integer() | infinity + Reason = no_such_directory + + +

block_user/4 and block_user/5 each blocks the user + User from directory Dir for a specified + amount of time.

+
+
+ list_auth_users(Port) -> Users | [] list_auth_users(Address, Port) -> Users | [] @@ -50,7 +70,6 @@ Users = list() = [string()] -

list_auth_users/1, list_auth_users/2, and list_auth_users/3 each returns a list of users that are currently authenticated. Authentications are stored for @@ -71,31 +90,12 @@ Users = list() = [string()] -

list_blocked_users/1, list_blocked_users/2, and list_blocked_users/3 each returns a list of users that are currently blocked from access.

- - block_user(User, Port, Dir, Seconds) -> true | {error, Reason} - block_user(User, Address, Port, Dir, Seconds) -> true | {error, Reason} - Blocks a user from access to a directory for a certain amount of time. - - User = string() - Port = integer() - Address = {A,B,C,D} | string() | undefined - Dir = string() - Seconds = integer() | infinity - Reason = no_such_directory - - - -

block_user/4 and block_user/5 each blocks the user - User from directory Dir for a specified - amount of time.

-
-
+ unblock_user(User, Port) -> true | {error, Reason} unblock_user(User, Address, Port) -> true | {error, Reason} @@ -110,7 +110,6 @@ Reason = term() -

unblock_user/2, unblock_user/3, and unblock_user/4 each removes the user User from the list of blocked users for Port (and Dir).

@@ -123,16 +122,15 @@ SecurityCallbackModule

The SecurityCallbackModule is a user-written module that can receive events from the mod_security Erlang web server API module. - This module only exports the functions - event/4,5, + This module only exports the functions event/[4,5] which are described here.

- event(What, Port, Dir, Data) -> ignored - event(What, Address, Port, Dir, Data) -> ignored + Module:event(What, Port, Dir, Data) -> ignored + Module:event(What, Address, Port, Dir, Data) -> ignored Called whenever an event occurs in mod_security. What = atom() diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml index 78f77f5b91..00d9d53376 100644 --- a/lib/inets/doc/src/tftp.xml +++ b/lib/inets/doc/src/tftp.xml @@ -221,88 +221,57 @@
+ - start(Options) -> {ok, Pid} | {error, Reason} - Starts a daemon process. + change_config(daemons, Options) -> [{Pid, Result}] + Changes configuration for all daemons. + Options = [option()] Pid = pid() + Result = ok | {error, Reason} Reason = term() -

Starts a daemon process listening for UDP packets on a - port. When it receives a request for read or write, it spawns - a temporary server process handling the actual transfer - of the (virtual) file.

+

Changes configuration for all TFTP daemon processes.

- +
- read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason} - Reads a (virtual) file from a TFTP server. + change_config(servers, Options) -> [{Pid, Result}] + Changes configuration for all servers. + - RemoteFilename = string() - LocalFilename = binary | string() Options = [option()] - LastCallbackState = term() + Pid = pid() + Result = ok | {error, Reason} Reason = term() -

Reads a (virtual) file RemoteFilename from a TFTP - server.

-

If LocalFilename is the atom binary, - tftp_binary is used as callback module. It concatenates - all transferred blocks and returns them as one single binary - in LastCallbackState.

-

If LocalFilename is a string and there are no - registered callback modules, tftp_file is used as - callback module. It writes each transferred block to the file - named LocalFilename and returns the number of - transferred bytes in LastCallbackState.

-

If LocalFilename is a string and there are registered - callback modules, LocalFilename is tested against - the regexps of these and the callback module corresponding to - the first match is used, or an error tuple is returned if no - matching regexp is found.

-
+

Changes configuration for all TFTP server processes.

- + +
- write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason} - Writes a (virtual) file to a TFTP server. + change_config(Pid, Options) -> Result + Changes configuration for a TFTP daemon, server, + or client process. - RemoteFilename = string() - LocalFilename = binary() | string() + Pid = pid() Options = [option()] - LastCallbackState = term() + Result = ok | {error, Reason} Reason = term() -

Writes a (virtual) file RemoteFilename to a TFTP - server.

-

If LocalFilename is a binary, tftp_binary is - used as callback module. The binary is transferred block by - block and the number of transferred bytes is returned in - LastCallbackState.

-

If LocalFilename is a string and there are no - registered callback modules, tftp_file is used as - callback module. It reads the file named LocalFilename - block by block and returns the number of transferred bytes - in LastCallbackState.

-

If LocalFilename is a string and there are registered - callback modules, LocalFilename is tested against - the regexps of these and the callback module corresponding to - the first match is used, or an error tuple is returned if no - matching regexp is found.

- +

Changes configuration for a TFTP daemon, server, or client process.

- + info(daemons) -> [{Pid, Options}] Returns information about all daemons. @@ -342,72 +311,89 @@

Returns information about a TFTP daemon, server, or client process.

- -
- - - change_config(daemons, Options) -> [{Pid, Result}] - Changes configuration for all daemons. - + + + read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason} + Reads a (virtual) file from a TFTP server. + RemoteFilename = string() + LocalFilename = binary | string() Options = [option()] - Pid = pid() - Result = ok | {error, Reason} + LastCallbackState = term() Reason = term() -

Changes configuration for all TFTP daemon processes.

- - +

Reads a (virtual) file RemoteFilename from a TFTP + server.

+

If LocalFilename is the atom binary, + tftp_binary is used as callback module. It concatenates + all transferred blocks and returns them as one single binary + in LastCallbackState.

+

If LocalFilename is a string and there are no + registered callback modules, tftp_file is used as + callback module. It writes each transferred block to the file + named LocalFilename and returns the number of + transferred bytes in LastCallbackState.

+

If LocalFilename is a string and there are registered + callback modules, LocalFilename is tested against + the regexps of these and the callback module corresponding to + the first match is used, or an error tuple is returned if no + matching regexp is found.

+ +
- + - change_config(servers, Options) -> [{Pid, Result}] - Changes configuration for all servers. - + start(Options) -> {ok, Pid} | {error, Reason} + Starts a daemon process. Options = [option()] Pid = pid() - Result = ok | {error, Reason} Reason = term() -

Changes configuration for all TFTP server processes.

+

Starts a daemon process listening for UDP packets on a + port. When it receives a request for read or write, it spawns + a temporary server process handling the actual transfer + of the (virtual) file.

- +
- change_config(Pid, Options) -> Result - Changes configuration for a TFTP daemon, server, - or client process. + write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason} + Writes a (virtual) file to a TFTP server. - Pid = pid() + RemoteFilename = string() + LocalFilename = binary() | string() Options = [option()] - Result = ok | {error, Reason} - Reason = term() - - -

Changes configuration for a TFTP daemon, server, or client process.

- - -
-
- - - start() -> ok | {error, Reason} - Starts the Inets application. - + LastCallbackState = term() Reason = term() -

Starts the Inets application.

+

Writes a (virtual) file RemoteFilename to a TFTP + server.

+

If LocalFilename is a binary, tftp_binary is + used as callback module. The binary is transferred block by + block and the number of transferred bytes is returned in + LastCallbackState.

+

If LocalFilename is a string and there are no + registered callback modules, tftp_file is used as + callback module. It reads the file named LocalFilename + block by block and returns the number of transferred bytes + in LastCallbackState.

+

If LocalFilename is a string and there are registered + callback modules, LocalFilename is tested against + the regexps of these and the callback module corresponding to + the first match is used, or an error tuple is returned if no + matching regexp is found.

+
@@ -467,43 +453,32 @@
- - prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}} - Prepares to open a file on the client side. + + Module:abort(Code, Text, State) -> ok + Aborts the file transfer. - Peer = {PeerType, PeerHost, PeerPort} - PeerType = inet | inet6 - PeerHost = ip_address() - PeerPort = integer() - Access = read | write - Filename = string() - Mode = string() - SuggestedOptions = AcceptedOptions = [{Key, Value}] -  Key = Value = string() - InitialState = [] | [{root_dir, string()}] - NewState = term() Code = undef | enoent | eacces | enospc   | badop | eexist | baduser | badopt   | int() Text = string() + State = term() -

Prepares to open a file on the client side.

-

No new options can be added, but those present in - SuggestedOptions can be omitted or replaced with new - values in AcceptedOptions.

-

This is followed by a call to open/4 before any - read/write access is performed. AcceptedOptions is - sent to the server, which replies with the options that it - accepts. These are then forwarded to open/4 as - SuggestedOptions.

- - +

Invoked when the file transfer is aborted.

+

The callback function is expected to clean + up its used resources after the aborted file + transfer, such as closing open file + descriptors and so on. The function is not + invoked if any of the other callback + functions returns an error, as it is + expected that they already have cleaned up + the necessary resources. However, it is + invoked if the functions fail (crash).

- - - open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}} + + + Module:open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}} Opens a file for read or write access. Peer = {PeerType, PeerHost, PeerPort} @@ -536,9 +511,44 @@ + + + Module:prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}} + Prepares to open a file on the client side. + + Peer = {PeerType, PeerHost, PeerPort} + PeerType = inet | inet6 + PeerHost = ip_address() + PeerPort = integer() + Access = read | write + Filename = string() + Mode = string() + SuggestedOptions = AcceptedOptions = [{Key, Value}] +  Key = Value = string() + InitialState = [] | [{root_dir, string()}] + NewState = term() + Code = undef | enoent | eacces | enospc +   | badop | eexist | baduser | badopt +   | int() + Text = string() + + +

Prepares to open a file on the client side.

+

No new options can be added, but those present in + SuggestedOptions can be omitted or replaced with new + values in AcceptedOptions.

+

This is followed by a call to open/4 before any + read/write access is performed. AcceptedOptions is + sent to the server, which replies with the options that it + accepts. These are then forwarded to open/4 as + SuggestedOptions.

+ + +
+
- read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}} + Module:read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}} Reads a chunk from the file. State = NewState = term() @@ -565,7 +575,7 @@ - write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}} + Module:write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}} Writes a chunk to the file. Bin = binary() @@ -590,30 +600,6 @@ - - - abort(Code, Text, State) -> ok - Aborts the file transfer. - - Code = undef | enoent | eacces | enospc -   | badop | eexist | baduser | badopt -   | int() - Text = string() - State = term() - - -

Invoked when the file transfer is aborted.

-

The callback function is expected to clean - up its used resources after the aborted file - transfer, such as closing open file - descriptors and so on. The function is not - invoked if any of the other callback - functions returns an error, as it is - expected that they already have cleaned up - the necessary resources. However, it is - invoked if the functions fail (crash).

-
-
@@ -628,7 +614,7 @@ - error_msg(Format, Data) -> ok | exit(Reason) + Logger:error_msg(Format, Data) -> ok | exit(Reason) Logs an error message. Format = string() @@ -644,32 +630,32 @@ - warning_msg(Format, Data) -> ok | exit(Reason) - Logs a warning message. + Logger:info_msg(Format, Data) -> ok | exit(Reason) + Logs an info message. Format = string() Data = [term()] Reason = term() -

Logs a warning message. - See error_logger:warning_msg/2 for details.

- - +

Logs an info message. + See error_logger:info_msg/2 for details.

- + - info_msg(Format, Data) -> ok | exit(Reason) - Logs an info message. + Logger:warning_msg(Format, Data) -> ok | exit(Reason) + Logs a warning message. Format = string() Data = [term()] Reason = term() -

Logs an info message. - See error_logger:info_msg/2 for details.

+

Logs a warning message. + See error_logger:warning_msg/2 for details.

+ +
-- cgit v1.2.3 From 8e216b94beeed02e67f08d3bf9307c7c48e3b977 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 2 Sep 2015 12:11:50 +0200 Subject: inets: httpc - Clarify/correct documentation Remove legacy inet6fb4 option from documentation even if the code will still accept it. --- lib/inets/doc/src/httpc.xml | 64 ++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 9a24226e78..31e44f405c 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -49,12 +49,12 @@ be started. When https links need to go through a proxy, the CONNECT method extension to HTTP-1.1 is used to establish a tunnel and then the connection is upgraded to TLS. - However, "TLS upgrade" according to RFC 2817 is not + However, "TLS upgrade" according to RFC 2817is not supported.

Pipelining is only used if the pipeline time-out is set, otherwise persistent connections without - pipelining are used. For example, the client always waits for + pipelining are used. That is, the client always waits for the previous response before sending the next request.

Some examples are provided in the RequestId = request_id() - A unique identifier as returned by request/4 Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used.

Cancels an asynchronous HTTP request. Notice that this does not guarantee @@ -188,7 +188,7 @@

Option ipv6_host_with_bracket deals with how to parse IPv6 addresses. For details, see argument Options of - request/4,5.

+ request/[4,5].

@@ -199,7 +199,7 @@ OptionItems = all | [option_item()] option_item() = proxy | - https_proxy + https_proxy | max_sessions | keep_alive_timeout | max_keep_alive_length | @@ -211,8 +211,8 @@ port | socket_opts | verbose - Profile = profile() | pid( - When started stand_alone. + Profile = profile() | pid() + When started stand_alone only the pid can used. Values = [{option_item(), term()}] Reason = term() @@ -227,7 +227,7 @@ Produces a list of miscellaneous information. Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used.

Produces a list of miscellaneous information. @@ -243,7 +243,7 @@ Resets the cookie database. Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used.

Resets (clears) the cookie database for the specified @@ -262,7 +262,7 @@ {status_code(), Body} | request_id() Body = string() | binary() Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used. Reason = term() @@ -311,7 +311,7 @@ {status_code(), Body} | request_id() Body = string() | binary() Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used. Reason = {connect_failed, term()} | {send_failed, term()} | term() @@ -343,8 +343,8 @@ -

This is the default SSL configuration option.

-

Defaults to [].

+

This is the SSL/TLS connectin configuration option.

+

Defaults to []. See ssl:connect/[2, 3,4] for availble options.

@@ -353,8 +353,8 @@ from the new URI and returns that as the result, instead of a 30X-result code.

For some 30X-result codes, automatic redirect - is not allowed. In these cases the 30X-result is always to - be returned.

+ is not allowed. In these cases the 30X-result is always + returned.

Default is true.

@@ -453,12 +453,14 @@ requests.

Overrides any value set by function set_options.

-

The validity of the options is not - checked in any way.

-

Notice that this can change the socket behavior - (see inet:setopts/2) - for an already existing one, and therefore an already connected - request handler.

+

The validity of the options is not checked by + the HTTP client they are assumed to be correct and passed + on to ssl application and inet driver, which may reject + them if they are not correct. Note that the current + implementation assumes the requests to the same host, port + combination will use the same socket options. +

+

By default the socket options set by function set_options/[1,2] are used when establishing a connection.

@@ -502,7 +504,7 @@ {RequestId, stream, BinBodyPart} {RequestId, stream_end, Headers} -

Default is the pid() of the process calling the request +

Default is the pid of the process calling the request function (self()).

@@ -582,12 +584,8 @@ If option verify is used, function store_cookies/2 has to be called for the cookies to be saved. Default is disabled. - IpFamily = inet | inet6 | inet6fb4 - When set to inet6fb4, both IPv4 and IPv6 can be used. - First inet6 is tried and if that does not work it falls - back to inet. - The option is to provide a workaround for buggy IPv6 stacks to ensure that - IPv4 always works. Default is inet. + IpFamily = inet | inet6 + Default is inet. IpAddress = ip_address() If the host has several network interfaces, this option specifies which one to use. @@ -610,7 +608,7 @@ different levels of Erlang trace on the client. It is a debug feature. Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used.

Sets options to be used for subsequent requests.

@@ -642,7 +640,7 @@ SetCookieHeaders = headers() - where field = "set-cookie" Url = url() Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used.

Saves the cookies defined in SetCookieHeaders @@ -655,7 +653,7 @@ stream_next(Pid) -> ok Triggers the next message to be streamed, that is, - the same behavior as active ones for sockets. + the same behavior as active one for sockets. Pid = pid() @@ -676,7 +674,7 @@ Dumps the entire cookie database. Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used. cookies() = [cookie_stores()] cookie_stores() = {cookies, cookies()} | {session_cookies, cookies()} cookies() = [cookie()] @@ -695,7 +693,7 @@ Produces a slightly processed dump of the sessions database. Profile = profile() | pid() - When started stand_alone. + When started stand_alone only the pid can be used. session_info() = {GoodSessions, BadSessions, NonSessions} GoodSessions = session() BadSessions = tuple() -- cgit v1.2.3 From 4c9428db3de49f36bc9802c6026147d9b2e401bc Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 2 Sep 2015 14:32:33 +0200 Subject: inets: httpd - Add links and small corrections --- lib/inets/doc/src/http_server.xml | 29 +++++++++++++++-------------- lib/inets/doc/src/httpd.xml | 31 +++++++++++++++---------------- 2 files changed, 30 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml index efa5f7a8f5..ee9496d9ba 100644 --- a/lib/inets/doc/src/http_server.xml +++ b/lib/inets/doc/src/http_server.xml @@ -184,7 +184,7 @@

- Htaccess - User Configurable Authentication. + Htaccess - User Configurable Authentication

Web server users without server administrative privileges that need to manage authentication of web pages that are local @@ -356,7 +356,8 @@ UserName:Password

- CGI Version 1.1, RFC 3875 + CGI Version 1.1, + <url href="http://www.ietf.org/rfc/rfc3875.txt">RFC 3875</url>

The module mod_cgi enables execution of CGI scripts on the server. A file matching the definition of a ScriptAlias config directive is treated as a CGI script. A CGI @@ -453,15 +454,15 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[ remotehost Remote hostname. rfc931 - The client remote username (RFC 931). + The client remote username (RFC 931). authuser The username used for authentication. [date] - Date and time of the request (RFC 1123). + Date and time of the request (RFC 1123). "request" - The request line exactly as it came from the client (RFC 1945). + The request line exactly as it came from the client (RFC 1945). status - The HTTP status code returned to the client (RFC 1945). + The HTTP status code returned to the client (RFC 1945). bytes The content-length of the document transferred. @@ -546,7 +547,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias.

Exports the following Erlang Web Server API interaction data, if possible:

@@ -579,7 +580,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data:

@@ -667,7 +668,7 @@ start() ->

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data:

@@ -715,7 +716,7 @@ start() ->

Uses the following Erlang web server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias
@@ -727,7 +728,7 @@ start() ->

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias
@@ -738,7 +739,7 @@ start() ->

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data:

@@ -769,7 +770,7 @@ start() ->

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias
@@ -795,7 +796,7 @@ start() ->

Uses the following Erlang Web Server API interaction data:

- real_name - from mod_alias + real_name - from mod_alias

Exports the following Erlang Web Server API interaction data:

diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml index b6d3c5d39b..4e3a875a7f 100644 --- a/lib/inets/doc/src/httpd.xml +++ b/lib/inets/doc/src/httpd.xml @@ -31,7 +31,7 @@ httpd An implementation of an HTTP - 1.1 compliant web server, as defined in RFC 2616. + 1.1 compliant web server, as defined in RFC 2616

This module provides the HTTP server start options, some administrative @@ -115,7 +115,7 @@ -

The properties proplist_file and file are mutually exclusive.

+

The properties proplist_file and file are mutually exclusive. Also newer properties may not be supported as Apache-like options, this is a legacy feature.

@@ -124,7 +124,7 @@ {port, integer()} -

The port that the HTTP server is to listen on. +

The port that the HTTP server listen to. If zero is specified as port, an arbitrary available port is picked and function httpd:info/2 can be used to determine which port was picked.

@@ -378,15 +378,15 @@ text/plain asc txt remotehost Remote. rfc931 - The remote username of the client (RFC 931). + The remote username of the client (RFC 931). authuser The username used for authentication. [date] - Date and time of the request (RFC 1123). + Date and time of the request (RFC 1123). "request" - The request line as it came from the client (RFC 1945). + The request line as it came from the client (RFC 1945). status - The HTTP status code returned to the client (RFC 1945). + The HTTP status code returned to the client (RFC 1945). bytes The content-length of the document transferred. @@ -564,7 +564,7 @@ text/plain asc txt

Method = string() and CgiScript = string(). script adds an action activating a CGI script whenever a file is requested using a certain HTTP method. The - method is either GET or POST, as defined in RFC 1945. It + method is either GET or POST, as defined in RFC 1945. It propagates the URL and file path of the requested document using the standard CGI PATH_INFO and PATH_TRANSLATED environment variables.

@@ -1065,7 +1065,7 @@ text/plain asc txt "http://ServerName:Part/cgi-bin/find.pl?person=jocke"

request_uri

The Request-URI as defined - in RFC 1945, for example, "/cgi-bin/find.pl?person=jocke".

+ in RFC 1945, for example, "/cgi-bin/find.pl?person=jocke".

http_version

The HTTP version of the @@ -1073,7 +1073,7 @@ text/plain asc txt request_line

The Request-Line as - defined in RFC 1945, for example, + defined inRFC 1945, for example, "GET /cgi-bin/find.pl?person=jocke HTTP/1.0".

parsed_header @@ -1089,7 +1089,7 @@ text/plain asc txt entity_body

The entity-Body as defined - in RFC 2616, for example, data sent from a CGI script using the + in RFC 2616, for example, data sent from a CGI script using the POST method.

connection @@ -1142,11 +1142,10 @@ text/plain asc txt RFC 2616 for the appropriate values.

Head is a key value list of HTTP header fields. The - server constructs an HTTP header from this data. See RFC - 2616 for the appropriate value for each header field. If the - client is an HTTP/1.0 client, the server filters the - list so that only HTTP/1.0 header fields are sent back - to the client.

+ server constructs an HTTP header from this data. See RFC 2616 for the appropriate value for each header field. If the + client is an HTTP/1.0 client, the server filters the + list so that only HTTP/1.0 header fields are sent back + to the client.

If Body is returned and equal to {Fun,Arg}, the web server tries apply/2 on Fun with Arg as argument. The web server expects that the fun either -- cgit v1.2.3 From a4f03b39acff16989cd3dc1cfedc58896a8f9fcd Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 2 Sep 2015 14:53:43 +0200 Subject: inets: ftp - Remove information about alternative solutions Currently there is no plans in modernizing/changing the API so there is no real value of pointing out alternative solutions. --- lib/inets/doc/src/ftp_client.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/ftp_client.xml b/lib/inets/doc/src/ftp_client.xml index 84fa064551..89e66db814 100644 --- a/lib/inets/doc/src/ftp_client.xml +++ b/lib/inets/doc/src/ftp_client.xml @@ -42,10 +42,7 @@ The FTP client API is designed to allow some functions to return intermediate results. This implies that only the process that started the FTP client can access it with - preserved sane semantics. (This can be solved - by changing the API, using the concept of a controlling - process as with other OTP applications, but - that is something for future releases of Inets.) + preserved sane semantics. If the process that started the FTP session dies, the FTP client process terminates.

-- cgit v1.2.3 From 6285460219d2e79d61294468b1c2915ad2d71456 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 2 Sep 2015 15:05:27 +0200 Subject: inets: Fix copy paste error --- lib/inets/doc/src/introduction.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/doc/src/introduction.xml b/lib/inets/doc/src/introduction.xml index ef3e109df5..491835f852 100644 --- a/lib/inets/doc/src/introduction.xml +++ b/lib/inets/doc/src/introduction.xml @@ -29,7 +29,7 @@ 2004-09-28 A - inets_services.xml + introduction.xml
-- cgit v1.2.3 From 628f8cff34f9784cfa34857bcd7133305acc3d27 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 7 Sep 2015 15:51:35 +0200 Subject: inets: Fix broken links --- lib/inets/doc/src/http_server.xml | 6 +++--- lib/inets/doc/src/httpd.xml | 10 +++++----- lib/inets/doc/src/httpd_custom_api.xml | 2 +- lib/inets/doc/src/mod_alias.xml | 4 ++-- lib/inets/doc/src/notes.xml | 36 ++++++++++++++-------------------- 5 files changed, 26 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml index ee9496d9ba..4b6d64fc8f 100644 --- a/lib/inets/doc/src/http_server.xml +++ b/lib/inets/doc/src/http_server.xml @@ -494,7 +494,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[ related steps, are considered server core functionality and are not implemented using the Erlang web server API. A description of functionality implemented by the Erlang webserver API is described - in Section + in Section Inets Web Server Modules.

A module can use data generated by previous modules in the @@ -635,11 +635,11 @@ start() -> Then it starts Mnesia and creates the tables. The first argument is the name of the tables, the second argument is a list of options of how to create the table, see - mnesia, documentation for + mnesia, documentation for more information. As the implementation of the mod_auth_mnesia saves one row for each user, the type must be bag. When the schema and the tables are created, function - mnesia:start/0 + mnesia:start/0 is used to start Mnesia and waits for the tables to be loaded. Mnesia uses the directory specified as mnesia_dir at startup if specified, diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml index 4e3a875a7f..2a4aea41c2 100644 --- a/lib/inets/doc/src/httpd.xml +++ b/lib/inets/doc/src/httpd.xml @@ -165,14 +165,14 @@ {profile, atom()} -

Used together with bind_address - and port to uniquely identify +

Used together with bind_address + and port to uniquely identify a HTTP server. This can be useful in a virtualized environment, where there can be more that one server that has the same bind_address and port. If this property is not explicitly set, it is assumed that the - bind_address and - portuniquely identifies the HTTP server. + bind_address and + portuniquely identifies the HTTP server.

@@ -227,7 +227,7 @@ {customize, atom()}

A callback module to customize the inets HTTP servers behaviour - see httpd_custom_api

+ see httpd_custom_api

diff --git a/lib/inets/doc/src/httpd_custom_api.xml b/lib/inets/doc/src/httpd_custom_api.xml index 5840641b37..23417900fa 100644 --- a/lib/inets/doc/src/httpd_custom_api.xml +++ b/lib/inets/doc/src/httpd_custom_api.xml @@ -29,7 +29,7 @@ Behaviour with optional callbacks to customize the inets HTTP server.

The module implementing this behaviour shall be supplied to to the servers - configuration with the option customize

+ configuration with the option customize

diff --git a/lib/inets/doc/src/mod_alias.xml b/lib/inets/doc/src/mod_alias.xml index a7b01efe06..87c950cc6b 100644 --- a/lib/inets/doc/src/mod_alias.xml +++ b/lib/inets/doc/src/mod_alias.xml @@ -106,7 +106,7 @@ FakeName is replaced with RealName in the match. The resulting path is split into two parts, ShortPath and AfterPath, as defined in - httpd_util:split_path/1. + httpd_util:split_path/1. Path is generated from ShortPath, that is, the result from default_index/2 with @@ -140,7 +140,7 @@ not_a_script is returned. If it is a script, the resulting script path is in two parts, ShortPath and AfterPath, as defined in - httpd_util:split_script_path/1. + httpd_util:split_script_path/1. config_db() is the server config file in ETS table format as described in Inets User's Guide.

diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index d1bfa28013..6a6b9c8b23 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -765,9 +765,9 @@

Better handling of errorI(s) during update of the session database.

Also added and updated some debugging functions - which_sessions/10,1 + which_sessions/[0,1] and - info/0.

+ info/0.

Own Id: OTP-10093

Aux Id: Seq 12062

@@ -861,7 +861,7 @@

[httpc] Add function for retrieving current options, - get_options/1,2.

+ get_options/[1,2].

Own Id: OTP-9979

@@ -1038,15 +1038,11 @@
Incompatibilities - -

[httpc] Deprecated interface module http has been removed. It has (long) been replaced by http client interface module - httpc.

+ httpc.

Own Id: OTP-9359

@@ -1234,15 +1230,13 @@
Inets 5.6
Improvements and New Features - +

[httpc] Add support for upload body streaming (PUT and POST).

For more info, see the definition of the Body argument of the - request/4,5 + request/[4,5] function.

Filipe David Manana

Own Id: OTP-9094

@@ -1255,7 +1249,7 @@

[httpd] - mod_esi:deliver/2 + mod_esi:deliver/2 made to accept binary data.

Bernard Duggan

Own Id: OTP-9123

@@ -1283,7 +1277,7 @@ for using file descriptors has been improved. It is now possible to add the file descriptor to the config (option fd) when calling the - inets:start(httpd, ...) + inets:start(httpd, ...) function.

Attila Rajmund Nohl

Own Id: OTP-9202

@@ -1297,7 +1291,7 @@

See the httpd socket_type communication property or the httpc - request/4,5 function + request/[4,5] function for more info.

Own Id: OTP-9230

*** POTENTIAL INCOMPATIBILITY ***

@@ -1497,7 +1491,7 @@

[httpc|httpd] - Now allow the use of the "new" ssl, by using the essl tag instead.

See the http_option option in the - request/4,5 or + request/[4,5] or the socket-type section of the Communication properties chapter for more info,

Own Id: OTP-7907

@@ -1729,8 +1723,8 @@

[httpc] - Allow users to pass socket options to the transport module when making requests.

See the socket_opts option in the - request/4 or - set_options/1,2 + request/4 or + set_options/[1,2] for more info,

Own Id: OTP-8352

@@ -1771,7 +1765,7 @@ deliver an async reply to more receivers then the calling process.

See the - receiver + receiver option for more info,

Own Id: OTP-8106

@@ -2040,7 +2034,7 @@ request, when the client connects to the server. Default value is that of the timeout option.

See the - request/4,5 + request/[4,5] function for more info.

Own Id: OTP-7298

@@ -2147,7 +2141,7 @@ the client connects to the server.

As a side-effect of this, the option ipv6 has been removed and replaced by the ipfamily option.

-

See http:set_options/1,2 +

See http:set_options/[1,2] for more info.

*** POTENTIAL INCOMPATIBILITY ***

Own Id: OTP-8004

-- cgit v1.2.3 From a66d9fb8813d32c7ded2253a7a5904f5b20b5ba8 Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Fri, 24 Jul 2015 14:02:48 +0300 Subject: inets: Forward connection errors with https proxy httpc should return meaningful error reason disregarding whether it is being used with http proxy or not --- lib/inets/src/http_client/httpc_handler.erl | 10 +++++++--- lib/inets/test/httpc_proxy_SUITE.erl | 20 +++++++++++++++++++- .../test/httpc_proxy_SUITE_data/server_proxy.sh | 2 ++ 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 205348524a..6e6cc38c06 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1817,13 +1817,13 @@ host_header(_, URI) -> tls_upgrade(#state{status = {ssl_tunnel, #request{settings = - #http_options{ssl = {_, TLSOptions} = SocketType}} = Request}, + #http_options{ssl = {_, TLSOptions} = SocketType}, + address = Address} = Request}, session = #session{socket = TCPSocket} = Session0, options = Options} = State) -> case ssl:connect(TCPSocket, TLSOptions) of {ok, TLSSocket} -> - Address = Request#request.address, ClientClose = httpc_request:is_client_closing(Request#request.headers), SessionType = httpc_manager:session_type(Options), Session = Session0#session{ @@ -1844,7 +1844,11 @@ tls_upgrade(#state{status = status = new }, {noreply, activate_request_timeout(NewState)}; - {error, _Reason} -> + {error, Reason} -> + Error = httpc_response:error(Request, {failed_connect, + [{to_address, Address}, + {tls, TLSOptions, Reason}]}), + maybe_send_answer(Request, Error, State), {stop, normal, State#state{request = Request}} end. diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl index 786de1bc42..6d7af4ea5d 100644 --- a/lib/inets/test/httpc_proxy_SUITE.erl +++ b/lib/inets/test/httpc_proxy_SUITE.erl @@ -58,7 +58,7 @@ groups() -> [http_emulate_lower_versions |local_proxy_cases()]}, {local_proxy_https,[], - local_proxy_cases()}]. + local_proxy_cases() ++ local_proxy_https_cases()}]. %% internal functions @@ -77,6 +77,9 @@ local_proxy_cases() -> http_stream, http_not_modified_otp_6821]. +local_proxy_https_cases() -> + [https_connect_error]. + %%-------------------------------------------------------------------- init_per_suite(Config0) -> @@ -431,6 +434,21 @@ header_value(Name, [{HeaderName,HeaderValue}|Headers]) -> header_value(Name, Headers) end. +%%-------------------------------------------------------------------- +https_connect_error(doc) -> + ["Error from CONNECT tunnel should be returned"]; +https_connect_error(Config) when is_list(Config) -> + {HttpServer,HttpPort} = ?config(http, Config), + Method = get, + %% using HTTPS scheme with HTTP port to trigger connection error + URL = "https://" ++ HttpServer ++ ":" ++ + integer_to_list(HttpPort) ++ "/index.html", + Opts = [], + HttpOpts = [], + Request = {URL,[]}, + {error,{failed_connect,[_,{tls,_,_}]}} = + httpc:request(Method, Request, HttpOpts, Opts). + %%-------------------------------------------------------------------- %% Internal Functions ------------------------------------------------ %%-------------------------------------------------------------------- diff --git a/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh index 9d1698c386..473024ae63 100755 --- a/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh +++ b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh @@ -169,6 +169,8 @@ MaxRequestsPerChild 0 ViaProxyName "tinyproxy" ConnectPort $APACHE_HTTPS_PORT +# to test connect error +ConnectPort $APACHE_HTTP_PORT EOF (tinyproxy -d -c tinyproxy.conf 1>/dev/null 2>&1 Date: Wed, 29 Jul 2015 20:03:26 +0900 Subject: Accept 'ECPrivateKey' as a ssl key option --- lib/ssl/src/ssl.erl | 1 + lib/ssl/test/ssl_ECC_SUITE.erl | 44 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 9f2af73204..120e8b59ed 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -804,6 +804,7 @@ validate_option(key, {KeyType, Value}) when is_binary(Value), KeyType == dsa; %% Backwards compatibility KeyType == 'RSAPrivateKey'; KeyType == 'DSAPrivateKey'; + KeyType == 'ECPrivateKey'; KeyType == 'PrivateKeyInfo' -> {KeyType, Value}; diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 85152fda22..3a9f21ea99 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -46,7 +46,7 @@ groups() -> {'tlsv1', [], all_versions_groups()}, {'erlang_server', [], key_cert_combinations()}, {'erlang_client', [], key_cert_combinations()}, - {'erlang', [], key_cert_combinations()} + {'erlang', [], key_cert_combinations() ++ misc()} ]. all_versions_groups ()-> @@ -65,6 +65,9 @@ key_cert_combinations() -> client_rsa_server_ecdsa ]. +misc()-> + [client_ecdsa_server_ecdsa_with_raw_key]. + %%-------------------------------------------------------------------- init_per_suite(Config0) -> end_per_suite(Config0), @@ -189,6 +192,32 @@ client_rsa_server_ecdsa(Config) when is_list(Config) -> SOpts = ?config(server_ecdsa_verify_opts, Config), basic_test(COpts, SOpts, Config). +client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) -> + COpts = ?config(client_ecdsa_opts, Config), + SOpts = ?config(server_ecdsa_verify_opts, Config), + ServerCert = proplists:get_value(certfile, SOpts), + ServerKeyFile = proplists:get_value(keyfile, SOpts), + {ok, PemBin} = file:read_file(ServerKeyFile), + PemEntries = public_key:pem_decode(PemBin), + {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries), + ServerKey = {'ECPrivateKey', Key}, + ServerCA = proplists:get_value(cacertfile, SOpts), + ClientCert = proplists:get_value(certfile, COpts), + ClientKey = proplists:get_value(keyfile, COpts), + ClientCA = proplists:get_value(cacertfile, COpts), + SType = ?config(server_type, Config), + CType = ?config(client_type, Config), + {Server, Port} = start_server_with_raw_key(SType, + ClientCA, ServerCA, + ServerCert, + ServerKey, + Config), + Client = start_client(CType, Port, ServerCA, ClientCA, + ClientCert, + ClientKey, Config), + check_result(Server, SType, Client, CType), + close(Server, Client). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- @@ -247,9 +276,7 @@ start_server(openssl, CA, OwnCa, Cert, Key, Config) -> OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), true = port_command(OpenSslPort, "Hello world"), {OpenSslPort, Port}; - start_server(erlang, CA, _, Cert, Key, Config) -> - {_, ServerNode, _} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, @@ -260,6 +287,17 @@ start_server(erlang, CA, _, Cert, Key, Config) -> [{verify, verify_peer}, {cacertfile, CA}, {certfile, Cert}, {keyfile, Key}]}]), {Server, ssl_test_lib:inet_port(Server)}. +start_server_with_raw_key(erlang, CA, _, Cert, Key, Config) -> + {_, ServerNode, _} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, + []}}, + {options, + [{verify, verify_peer}, {cacertfile, CA}, + {certfile, Cert}, {key, Key}]}]), + {Server, ssl_test_lib:inet_port(Server)}. check_result(Server, erlang, Client, erlang) -> ssl_test_lib:check_result(Server, ok, Client, ok); -- cgit v1.2.3 From d57f5e34e58a49298c2c2d6210392df6629a740b Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 2 Sep 2015 15:21:47 +0200 Subject: dialyzer: Correct the handling of parameters of opaque types Prior to this commit, the fact that parameters of opaque types are expanded differently depending on the current values of limits used during expansion, caused problems later when the types of parameters are used for determining if opaque types are comparable. --- lib/hipe/cerl/erl_types.erl | 82 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 56ec757dbf..cd2d2fe207 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -2712,7 +2712,87 @@ is_compat_args([], []) -> true; is_compat_args(_, _) -> false. is_compat_arg(A, A) -> true; -is_compat_arg(A1, A2) -> t_is_any(A1) orelse t_is_any(A2). +is_compat_arg(A1, A2) -> + is_specialization(A1, A2) orelse is_specialization(A2, A1). + +-spec is_specialization(erl_type(), erl_type()) -> boolean(). + +%% Returns true if the first argument is a specialization of the +%% second argument in the sense that every type is a specialization of +%% any(). For example, {_,_} is a specialization of any(), but not of +%% tuple(). Does not handle variables, but any() and unions (sort of). + +is_specialization(_, ?any) -> true; +is_specialization(?any, _) -> false; +is_specialization(?function(Domain1, Range1), ?function(Domain2, Range2)) -> + (is_specialization(Domain1, Domain2) andalso + is_specialization(Range1, Range2)); +is_specialization(?list(Contents1, Termination1, Size1), + ?list(Contents2, Termination2, Size2)) -> + (Size1 =:= Size2 andalso + is_specialization(Contents1, Contents2) andalso + is_specialization(Termination1, Termination2)); +is_specialization(?product(Types1), ?product(Types2)) -> + specialization_list(Types1, Types2); +is_specialization(?tuple(?any, ?any, ?any), ?tuple(_, _, _)) -> false; +is_specialization(?tuple(_, _, _), ?tuple(?any, ?any, ?any)) -> false; +is_specialization(?tuple(Elements1, Arity, _), + ?tuple(Elements2, Arity, _)) when Arity =/= ?any -> + specialization_list(Elements1, Elements2); +is_specialization(?tuple_set([{Arity, List}]), + ?tuple(Elements2, Arity, _)) when Arity =/= ?any -> + specialization_list(sup_tuple_elements(List), Elements2); +is_specialization(?tuple(Elements1, Arity, _), + ?tuple_set([{Arity, List}])) when Arity =/= ?any -> + specialization_list(Elements1, sup_tuple_elements(List)); +is_specialization(?tuple_set(List1), ?tuple_set(List2)) -> + try + specialization_list(lists:append([T || {_Arity, T} <- List1]), + lists:append([T || {_Arity, T} <- List2])) + catch _:_ -> false + end; +is_specialization(?union(List1)=T1, ?union(List2)=T2) -> + case specialization_union2(T1, T2) of + {yes, Type1, Type2} -> is_specialization(Type1, Type2); + no -> specialization_list(List1, List2) + end; +is_specialization(?union(List), T2) -> + case unify_union(List) of + {yes, Type} -> is_specialization(Type, T2); + no -> false + end; +is_specialization(T1, ?union(List)) -> + case unify_union(List) of + {yes, Type} -> is_specialization(T1, Type); + no -> false + end; +is_specialization(?opaque(_) = T1, T2) -> + is_specialization(t_opaque_structure(T1), T2); +is_specialization(T1, ?opaque(_) = T2) -> + is_specialization(T1, t_opaque_structure(T2)); +is_specialization(?var(_), _) -> exit(error); +is_specialization(_, ?var(_)) -> exit(error); +is_specialization(T, T) -> true; +is_specialization(?none, _) -> false; +is_specialization(_, ?none) -> false; +is_specialization(?unit, _) -> false; +is_specialization(_, ?unit) -> false; +is_specialization(#c{}, #c{}) -> false. + +specialization_list(L1, L2) -> + length(L1) =:= length(L2) andalso specialization_list1(L1, L2). + +specialization_list1([], []) -> true; +specialization_list1([T1|L1], [T2|L2]) -> + is_specialization(T1, T2) andalso specialization_list1(L1, L2). + +specialization_union2(?union(List1)=T1, ?union(List2)=T2) -> + case {unify_union(List1), unify_union(List2)} of + {{yes, Type1}, {yes, Type2}} -> {yes, Type1, Type2}; + {{yes, Type1}, no} -> {yes, Type1, T2}; + {no, {yes, Type2}} -> {yes, T1, Type2}; + {no, no} -> no + end. -spec t_inf_lists([erl_type()], [erl_type()]) -> [erl_type()]. -- cgit v1.2.3 From 25c6dc431d612a842fe504a661f01e81a5d452fa Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 9 Sep 2015 12:31:13 +0200 Subject: dialyzer: Add a testcase --- .../opaque_SUITE_data/src/proper/proper_common.hrl | 55 + .../opaque_SUITE_data/src/proper/proper_gen.erl | 624 +++++ .../src/proper/proper_internal.hrl | 92 + .../opaque_SUITE_data/src/proper/proper_types.erl | 1349 +++++++++++ .../src/proper/proper_typeserver.erl | 2401 ++++++++++++++++++++ 5 files changed, 4521 insertions(+) create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_common.hrl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_gen.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_internal.hrl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_types.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl (limited to 'lib') diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_common.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_common.hrl new file mode 100644 index 0000000000..c10626c5cc --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_common.hrl @@ -0,0 +1,55 @@ +%%% Copyright 2010-2013 Manolis Papadakis , +%%% Eirini Arvaniti +%%% and Kostis Sagonas +%%% +%%% This file is part of PropEr. +%%% +%%% PropEr 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 3 of the License, or +%%% (at your option) any later version. +%%% +%%% PropEr 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 PropEr. If not, see . + +%%% @copyright 2010-2013 Manolis Papadakis, Eirini Arvaniti and Kostis Sagonas +%%% @version {@version} +%%% @author Manolis Papadakis +%%% @doc Common parts of user and internal header files + + +%%------------------------------------------------------------------------------ +%% Test generation macros +%%------------------------------------------------------------------------------ + +-define(FORALL(X,RawType,Prop), proper:forall(RawType,fun(X) -> Prop end)). +-define(IMPLIES(Pre,Prop), proper:implies(Pre,?DELAY(Prop))). +-define(WHENFAIL(Action,Prop), proper:whenfail(?DELAY(Action),?DELAY(Prop))). +-define(TRAPEXIT(Prop), proper:trapexit(?DELAY(Prop))). +-define(TIMEOUT(Limit,Prop), proper:timeout(Limit,?DELAY(Prop))). +%% TODO: -define(ALWAYS(Tests,Prop), proper:always(Tests,?DELAY(Prop))). +%% TODO: -define(SOMETIMES(Tests,Prop), proper:sometimes(Tests,?DELAY(Prop))). + + +%%------------------------------------------------------------------------------ +%% Generator macros +%%------------------------------------------------------------------------------ + +-define(FORCE(X), (X)()). +-define(DELAY(X), fun() -> X end). +-define(LAZY(X), proper_types:lazy(?DELAY(X))). +-define(SIZED(SizeArg,Gen), proper_types:sized(fun(SizeArg) -> Gen end)). +-define(LET(X,RawType,Gen), proper_types:bind(RawType,fun(X) -> Gen end,false)). +-define(SHRINK(Gen,AltGens), + proper_types:shrinkwith(?DELAY(Gen),?DELAY(AltGens))). +-define(LETSHRINK(Xs,RawType,Gen), + proper_types:bind(RawType,fun(Xs) -> Gen end,true)). +-define(SUCHTHAT(X,RawType,Condition), + proper_types:add_constraint(RawType,fun(X) -> Condition end,true)). +-define(SUCHTHATMAYBE(X,RawType,Condition), + proper_types:add_constraint(RawType,fun(X) -> Condition end,false)). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_gen.erl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_gen.erl new file mode 100644 index 0000000000..bf627d1373 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_gen.erl @@ -0,0 +1,624 @@ +%%% Copyright 2010-2013 Manolis Papadakis , +%%% Eirini Arvaniti +%%% and Kostis Sagonas +%%% +%%% This file is part of PropEr. +%%% +%%% PropEr 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 3 of the License, or +%%% (at your option) any later version. +%%% +%%% PropEr 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 PropEr. If not, see . + +%%% @copyright 2010-2013 Manolis Papadakis, Eirini Arvaniti and Kostis Sagonas +%%% @version {@version} +%%% @author Manolis Papadakis + +%%% @doc Generator subsystem and generators for basic types. +%%% +%%% You can use these functions to try out the random +%%% instance generation and shrinking subsystems. +%%% +%%% CAUTION: These functions should never be used inside properties. They are +%%% meant for demonstration purposes only. + +-module(proper_gen). +-export([pick/1, pick/2, pick/3, sample/1, sample/3, sampleshrink/1, sampleshrink/2]). + +-export([safe_generate/1]). +-export([generate/1, normal_gen/1, alt_gens/1, clean_instance/1, + get_ret_type/1]). +-export([integer_gen/3, float_gen/3, atom_gen/1, atom_rev/1, binary_gen/1, + binary_rev/1, binary_len_gen/1, bitstring_gen/1, bitstring_rev/1, + bitstring_len_gen/1, list_gen/2, distlist_gen/3, vector_gen/2, + union_gen/1, weighted_union_gen/1, tuple_gen/1, loose_tuple_gen/2, + loose_tuple_rev/2, exactly_gen/1, fixed_list_gen/1, function_gen/2, + any_gen/1, native_type_gen/2, safe_weighted_union_gen/1, + safe_union_gen/1]). + +-export_type([instance/0, imm_instance/0, sized_generator/0, nosize_generator/0, + generator/0, reverse_gen/0, combine_fun/0, alt_gens/0]). + +-include("proper_internal.hrl"). + + +%%----------------------------------------------------------------------------- +%% Types +%%----------------------------------------------------------------------------- + +%% TODO: update imm_instance() when adding more types: be careful when reading +%% anything that returns it +%% @private_type +-type imm_instance() :: proper_types:raw_type() + | instance() + | {'$used', imm_instance(), imm_instance()} + | {'$to_part', imm_instance()}. +-type instance() :: term(). +%% A value produced by the random instance generator. +-type error_reason() :: 'arity_limit' | 'cant_generate' | {'typeserver',term()}. + +%% @private_type +-type sized_generator() :: fun((size()) -> imm_instance()). +%% @private_type +-type typed_sized_generator() :: {'typed', + fun((proper_types:type(),size()) -> + imm_instance())}. +%% @private_type +-type nosize_generator() :: fun(() -> imm_instance()). +%% @private_type +-type typed_nosize_generator() :: {'typed', + fun((proper_types:type()) -> + imm_instance())}. +%% @private_type +-type generator() :: sized_generator() + | typed_sized_generator() + | nosize_generator() + | typed_nosize_generator(). +%% @private_type +-type plain_reverse_gen() :: fun((instance()) -> imm_instance()). +%% @private_type +-type typed_reverse_gen() :: {'typed', + fun((proper_types:type(),instance()) -> + imm_instance())}. +%% @private_type +-type reverse_gen() :: plain_reverse_gen() | typed_reverse_gen(). +%% @private_type +-type combine_fun() :: fun((instance()) -> imm_instance()). +%% @private_type +-type alt_gens() :: fun(() -> [imm_instance()]). +%% @private_type +-type fun_seed() :: {non_neg_integer(),non_neg_integer()}. + + +%%----------------------------------------------------------------------------- +%% Instance generation functions +%%----------------------------------------------------------------------------- + +%% @private +-spec safe_generate(proper_types:raw_type()) -> + {'ok',imm_instance()} | {'error',error_reason()}. +safe_generate(RawType) -> + try generate(RawType) of + ImmInstance -> {ok, ImmInstance} + catch + throw:'$arity_limit' -> {error, arity_limit}; + throw:'$cant_generate' -> {error, cant_generate}; + throw:{'$typeserver',SubReason} -> {error, {typeserver,SubReason}} + end. + +%% @private +-spec generate(proper_types:raw_type()) -> imm_instance(). +generate(RawType) -> + Type = proper_types:cook_outer(RawType), + ok = add_parameters(Type), + Instance = generate(Type, get('$constraint_tries'), none), + ok = remove_parameters(Type), + Instance. + +-spec add_parameters(proper_types:type()) -> 'ok'. +add_parameters(Type) -> + case proper_types:find_prop(parameters, Type) of + {ok, Params} -> + OldParams = erlang:get('$parameters'), + case OldParams of + undefined -> + erlang:put('$parameters', Params); + _ -> + erlang:put('$parameters', Params ++ OldParams) + end, + ok; + _ -> + ok + end. + +-spec remove_parameters(proper_types:type()) -> 'ok'. +remove_parameters(Type) -> + case proper_types:find_prop(parameters, Type) of + {ok, Params} -> + AllParams = erlang:get('$parameters'), + case AllParams of + Params-> + erlang:erase('$parameters'); + _ -> + erlang:put('$parameters', AllParams -- Params) + end, + ok; + _ -> + ok + end. + +-spec generate(proper_types:type(), non_neg_integer(), + 'none' | {'ok',imm_instance()}) -> imm_instance(). +generate(_Type, 0, none) -> + throw('$cant_generate'); +generate(_Type, 0, {ok,Fallback}) -> + Fallback; +generate(Type, TriesLeft, Fallback) -> + ImmInstance = + case proper_types:get_prop(kind, Type) of + constructed -> + PartsType = proper_types:get_prop(parts_type, Type), + Combine = proper_types:get_prop(combine, Type), + ImmParts = generate(PartsType), + Parts = clean_instance(ImmParts), + ImmInstance1 = Combine(Parts), + %% TODO: We can just generate the internal type: if it's not + %% a type, it will turn into an exactly. + ImmInstance2 = + case proper_types:is_raw_type(ImmInstance1) of + true -> generate(ImmInstance1); + false -> ImmInstance1 + end, + {'$used',ImmParts,ImmInstance2}; + _ -> + ImmInstance1 = normal_gen(Type), + case proper_types:is_raw_type(ImmInstance1) of + true -> generate(ImmInstance1); + false -> ImmInstance1 + end + end, + case proper_types:satisfies_all(clean_instance(ImmInstance), Type) of + {_,true} -> ImmInstance; + {true,false} -> generate(Type, TriesLeft - 1, {ok,ImmInstance}); + {false,false} -> generate(Type, TriesLeft - 1, Fallback) + end. + +%% @equiv pick(Type, 10) +-spec pick(Type::proper_types:raw_type()) -> {'ok',instance()} | 'error'. +pick(RawType) -> + pick(RawType, 10). + +%% @equiv pick(Type, Size, now()) +-spec pick(Type::proper_types:raw_type(), size()) -> {'ok', instance()} | 'error'. +pick(RawType, Size) -> + pick(RawType, Size, now()). + +%% @doc Generates a random instance of `Type', of size `Size' with seed `Seed'. +-spec pick(Type::proper_types:raw_type(), size(), seed()) -> + {'ok',instance()} | 'error'. +pick(RawType, Size, Seed) -> + proper:global_state_init_size_seed(Size, Seed), + case clean_instance(safe_generate(RawType)) of + {ok,Instance} = Result -> + Msg = "WARNING: Some garbage has been left in the process registry " + "and the code server~n" + "to allow for the returned function(s) to run normally.~n" + "Please run proper:global_state_erase() when done.~n", + case contains_fun(Instance) of + true -> io:format(Msg, []); + false -> proper:global_state_erase() + end, + Result; + {error,Reason} -> + proper:report_error(Reason, fun io:format/2), + proper:global_state_erase(), + error + end. + +%% @equiv sample(Type, 10, 20) +-spec sample(Type::proper_types:raw_type()) -> 'ok'. +sample(RawType) -> + sample(RawType, 10, 20). + +%% @doc Generates and prints one random instance of `Type' for each size from +%% `StartSize' up to `EndSize'. +-spec sample(Type::proper_types:raw_type(), size(), size()) -> 'ok'. +sample(RawType, StartSize, EndSize) when StartSize =< EndSize -> + Tests = EndSize - StartSize + 1, + Prop = ?FORALL(X, RawType, begin io:format("~p~n",[X]), true end), + Opts = [quiet,{start_size,StartSize},{max_size,EndSize},{numtests,Tests}], + _ = proper:quickcheck(Prop, Opts), + ok. + +%% @equiv sampleshrink(Type, 10) +-spec sampleshrink(Type::proper_types:raw_type()) -> 'ok'. +sampleshrink(RawType) -> + sampleshrink(RawType, 10). + +%% @doc Generates a random instance of `Type', of size `Size', then shrinks it +%% as far as it goes. The value produced on each step of the shrinking process +%% is printed on the screen. +-spec sampleshrink(Type::proper_types:raw_type(), size()) -> 'ok'. +sampleshrink(RawType, Size) -> + proper:global_state_init_size(Size), + Type = proper_types:cook_outer(RawType), + case safe_generate(Type) of + {ok,ImmInstance} -> + Shrunk = keep_shrinking(ImmInstance, [], Type), + PrintInst = fun(I) -> io:format("~p~n",[clean_instance(I)]) end, + lists:foreach(PrintInst, Shrunk); + {error,Reason} -> + proper:report_error(Reason, fun io:format/2) + end, + proper:global_state_erase(), + ok. + +-spec keep_shrinking(imm_instance(), [imm_instance()], proper_types:type()) -> + [imm_instance(),...]. +keep_shrinking(ImmInstance, Acc, Type) -> + case proper_shrink:shrink(ImmInstance, Type, init) of + {[], _NewState} -> + lists:reverse([ImmInstance|Acc]); + {[Shrunk|_Rest], _NewState} -> + keep_shrinking(Shrunk, [ImmInstance|Acc], Type) + end. + +-spec contains_fun(term()) -> boolean(). +contains_fun(List) when is_list(List) -> + proper_arith:safe_any(fun contains_fun/1, List); +contains_fun(Tuple) when is_tuple(Tuple) -> + contains_fun(tuple_to_list(Tuple)); +contains_fun(Fun) when is_function(Fun) -> + true; +contains_fun(_Term) -> + false. + + +%%----------------------------------------------------------------------------- +%% Utility functions +%%----------------------------------------------------------------------------- + +%% @private +-spec normal_gen(proper_types:type()) -> imm_instance(). +normal_gen(Type) -> + case proper_types:get_prop(generator, Type) of + {typed, Gen} -> + if + is_function(Gen, 1) -> Gen(Type); + is_function(Gen, 2) -> Gen(Type, proper:get_size(Type)) + end; + Gen -> + if + is_function(Gen, 0) -> Gen(); + is_function(Gen, 1) -> Gen(proper:get_size(Type)) + end + end. + +%% @private +-spec alt_gens(proper_types:type()) -> [imm_instance()]. +alt_gens(Type) -> + case proper_types:find_prop(alt_gens, Type) of + {ok, AltGens} -> ?FORCE(AltGens); + error -> [] + end. + +%% @private +-spec clean_instance(imm_instance()) -> instance(). +clean_instance({'$used',_ImmParts,ImmInstance}) -> + clean_instance(ImmInstance); +clean_instance({'$to_part',ImmInstance}) -> + clean_instance(ImmInstance); +clean_instance(ImmInstance) -> + if + is_list(ImmInstance) -> + %% CAUTION: this must handle improper lists + proper_arith:safe_map(fun clean_instance/1, ImmInstance); + is_tuple(ImmInstance) -> + proper_arith:tuple_map(fun clean_instance/1, ImmInstance); + true -> + ImmInstance + end. + + +%%----------------------------------------------------------------------------- +%% Basic type generators +%%----------------------------------------------------------------------------- + +%% @private +-spec integer_gen(size(), proper_types:extint(), proper_types:extint()) -> + integer(). +integer_gen(Size, inf, inf) -> + proper_arith:rand_int(Size); +integer_gen(Size, inf, High) -> + High - proper_arith:rand_non_neg_int(Size); +integer_gen(Size, Low, inf) -> + Low + proper_arith:rand_non_neg_int(Size); +integer_gen(Size, Low, High) -> + proper_arith:smart_rand_int(Size, Low, High). + +%% @private +-spec float_gen(size(), proper_types:extnum(), proper_types:extnum()) -> + float(). +float_gen(Size, inf, inf) -> + proper_arith:rand_float(Size); +float_gen(Size, inf, High) -> + High - proper_arith:rand_non_neg_float(Size); +float_gen(Size, Low, inf) -> + Low + proper_arith:rand_non_neg_float(Size); +float_gen(_Size, Low, High) -> + proper_arith:rand_float(Low, High). + +%% @private +-spec atom_gen(size()) -> proper_types:type(). +%% We make sure we never clash with internal atoms by checking that the first +%% character is not '$'. +atom_gen(Size) -> + ?LET(Str, + ?SUCHTHAT(X, + proper_types:resize(Size, + proper_types:list(proper_types:byte())), + X =:= [] orelse hd(X) =/= $$), + list_to_atom(Str)). + +%% @private +-spec atom_rev(atom()) -> imm_instance(). +atom_rev(Atom) -> + {'$used', atom_to_list(Atom), Atom}. + +%% @private +-spec binary_gen(size()) -> proper_types:type(). +binary_gen(Size) -> + ?LET(Bytes, + proper_types:resize(Size, + proper_types:list(proper_types:byte())), + list_to_binary(Bytes)). + +%% @private +-spec binary_rev(binary()) -> imm_instance(). +binary_rev(Binary) -> + {'$used', binary_to_list(Binary), Binary}. + +%% @private +-spec binary_len_gen(length()) -> proper_types:type(). +binary_len_gen(Len) -> + ?LET(Bytes, + proper_types:vector(Len, proper_types:byte()), + list_to_binary(Bytes)). + +%% @private +-spec bitstring_gen(size()) -> proper_types:type(). +bitstring_gen(Size) -> + ?LET({BytesHead, NumBits, TailByte}, + {proper_types:resize(Size,proper_types:binary()), + proper_types:range(0,7), proper_types:range(0,127)}, + <>). + +%% @private +-spec bitstring_rev(bitstring()) -> imm_instance(). +bitstring_rev(BitString) -> + List = bitstring_to_list(BitString), + {BytesList, BitsTail} = lists:splitwith(fun erlang:is_integer/1, List), + {NumBits, TailByte} = case BitsTail of + [] -> {0, 0}; + [Bits] -> N = bit_size(Bits), + <> = Bits, + {N, Byte} + end, + {'$used', + {{'$used',BytesList,list_to_binary(BytesList)}, NumBits, TailByte}, + BitString}. + +%% @private +-spec bitstring_len_gen(length()) -> proper_types:type(). +bitstring_len_gen(Len) -> + BytesLen = Len div 8, + BitsLen = Len rem 8, + ?LET({BytesHead, NumBits, TailByte}, + {proper_types:binary(BytesLen), BitsLen, + proper_types:range(0, 1 bsl BitsLen - 1)}, + <>). + +%% @private +-spec list_gen(size(), proper_types:type()) -> [imm_instance()]. +list_gen(Size, ElemType) -> + Len = proper_arith:rand_int(0, Size), + vector_gen(Len, ElemType). + +%% @private +-spec distlist_gen(size(), sized_generator(), boolean()) -> [imm_instance()]. +distlist_gen(RawSize, Gen, NonEmpty) -> + Len = case NonEmpty of + true -> proper_arith:rand_int(1, erlang:max(1,RawSize)); + false -> proper_arith:rand_int(0, RawSize) + end, + Size = case Len of + 1 -> RawSize - 1; + _ -> RawSize + end, + %% TODO: this produces a lot of types: maybe a simple 'div' is sufficient? + Sizes = proper_arith:distribute(Size, Len), + InnerTypes = [Gen(S) || S <- Sizes], + fixed_list_gen(InnerTypes). + +%% @private +-spec vector_gen(length(), proper_types:type()) -> [imm_instance()]. +vector_gen(Len, ElemType) -> + vector_gen_tr(Len, ElemType, []). + +-spec vector_gen_tr(length(), proper_types:type(), [imm_instance()]) -> + [imm_instance()]. +vector_gen_tr(0, _ElemType, AccList) -> + AccList; +vector_gen_tr(Left, ElemType, AccList) -> + vector_gen_tr(Left - 1, ElemType, [generate(ElemType) | AccList]). + +%% @private +-spec union_gen([proper_types:type(),...]) -> imm_instance(). +union_gen(Choices) -> + {_Choice,Type} = proper_arith:rand_choose(Choices), + generate(Type). + +%% @private +-spec weighted_union_gen([{frequency(),proper_types:type()},...]) -> + imm_instance(). +weighted_union_gen(FreqChoices) -> + {_Choice,Type} = proper_arith:freq_choose(FreqChoices), + generate(Type). + +%% @private +-spec safe_union_gen([proper_types:type(),...]) -> imm_instance(). +safe_union_gen(Choices) -> + {Choice,Type} = proper_arith:rand_choose(Choices), + try generate(Type) + catch + error:_ -> + safe_union_gen(proper_arith:list_remove(Choice, Choices)) + end. + +%% @private +-spec safe_weighted_union_gen([{frequency(),proper_types:type()},...]) -> + imm_instance(). +safe_weighted_union_gen(FreqChoices) -> + {Choice,Type} = proper_arith:freq_choose(FreqChoices), + try generate(Type) + catch + error:_ -> + safe_weighted_union_gen(proper_arith:list_remove(Choice, + FreqChoices)) + end. + +%% @private +-spec tuple_gen([proper_types:type()]) -> tuple(). +tuple_gen(Fields) -> + list_to_tuple(fixed_list_gen(Fields)). + +%% @private +-spec loose_tuple_gen(size(), proper_types:type()) -> proper_types:type(). +loose_tuple_gen(Size, ElemType) -> + ?LET(L, + proper_types:resize(Size, proper_types:list(ElemType)), + list_to_tuple(L)). + +%% @private +-spec loose_tuple_rev(tuple(), proper_types:type()) -> imm_instance(). +loose_tuple_rev(Tuple, ElemType) -> + CleanList = tuple_to_list(Tuple), + List = case proper_types:find_prop(reverse_gen, ElemType) of + {ok,{typed, ReverseGen}} -> + [ReverseGen(ElemType,X) || X <- CleanList]; + {ok,ReverseGen} -> [ReverseGen(X) || X <- CleanList]; + error -> CleanList + end, + {'$used', List, Tuple}. + +%% @private +-spec exactly_gen(T) -> T. +exactly_gen(X) -> + X. + +%% @private +-spec fixed_list_gen([proper_types:type()]) -> imm_instance() + ; ({[proper_types:type()],proper_types:type()}) -> + maybe_improper_list(imm_instance(), imm_instance() | []). +fixed_list_gen({ProperHead,ImproperTail}) -> + [generate(F) || F <- ProperHead] ++ generate(ImproperTail); +fixed_list_gen(ProperFields) -> + [generate(F) || F <- ProperFields]. + +%% @private +-spec function_gen(arity(), proper_types:type()) -> function(). +function_gen(Arity, RetType) -> + FunSeed = {proper_arith:rand_int(0, ?SEED_RANGE - 1), + proper_arith:rand_int(0, ?SEED_RANGE - 1)}, + create_fun(Arity, RetType, FunSeed). + +%% @private +-spec any_gen(size()) -> imm_instance(). +any_gen(Size) -> + case get('$any_type') of + undefined -> real_any_gen(Size); + {type,AnyType} -> generate(proper_types:resize(Size, AnyType)) + end. + +-spec real_any_gen(size()) -> imm_instance(). +real_any_gen(0) -> + SimpleTypes = [proper_types:integer(), proper_types:float(), + proper_types:atom()], + union_gen(SimpleTypes); +real_any_gen(Size) -> + FreqChoices = [{?ANY_SIMPLE_PROB,simple}, {?ANY_BINARY_PROB,binary}, + {?ANY_EXPAND_PROB,expand}], + case proper_arith:freq_choose(FreqChoices) of + {_,simple} -> + real_any_gen(0); + {_,binary} -> + generate(proper_types:resize(Size, proper_types:bitstring())); + {_,expand} -> + %% TODO: statistics of produced terms? + NumElems = proper_arith:rand_int(0, Size - 1), + ElemSizes = proper_arith:distribute(Size - 1, NumElems), + ElemTypes = [?LAZY(real_any_gen(S)) || S <- ElemSizes], + case proper_arith:rand_int(1,2) of + 1 -> fixed_list_gen(ElemTypes); + 2 -> tuple_gen(ElemTypes) + end + end. + +%% @private +-spec native_type_gen(mod_name(), string()) -> proper_types:type(). +native_type_gen(Mod, TypeStr) -> + case proper_typeserver:translate_type({Mod,TypeStr}) of + {ok,Type} -> Type; + {error,Reason} -> throw({'$typeserver',Reason}) + end. + + +%%------------------------------------------------------------------------------ +%% Function-generation functions +%%------------------------------------------------------------------------------ + +-spec create_fun(arity(), proper_types:type(), fun_seed()) -> function(). +create_fun(Arity, RetType, FunSeed) -> + Handler = fun(Args) -> function_body(Args, RetType, FunSeed) end, + Err = fun() -> throw('$arity_limit') end, + case Arity of + 0 -> fun() -> Handler([]) end; + _ -> Err() + end. + +%% @private +-spec get_ret_type(function()) -> proper_types:type(). +get_ret_type(Fun) -> + {arity,Arity} = erlang:fun_info(Fun, arity), + put('$get_ret_type', true), + RetType = apply(Fun, lists:duplicate(Arity,dummy)), + erase('$get_ret_type'), + RetType. +-spec function_body([term()], proper_types:type(), fun_seed()) -> + proper_types:type() | instance(). +function_body(Args, RetType, {Seed1,Seed2}) -> + case get('$get_ret_type') of + true -> + RetType; + _ -> + SavedSeed = get(?SEED_NAME), + update_seed({Seed1,Seed2,erlang:phash2(Args,?SEED_RANGE)}), + Ret = clean_instance(generate(RetType)), + put(?SEED_NAME, SavedSeed), + proper_symb:internal_eval(Ret) + end. + +-ifdef(USE_SFMT). +update_seed(Seed) -> + sfmt:seed(Seed). +-else. +update_seed(Seed) -> + put(random_seed, Seed). +-endif. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_internal.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_internal.hrl new file mode 100644 index 0000000000..c790d7d4db --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_internal.hrl @@ -0,0 +1,92 @@ +%%% Copyright 2010-2013 Manolis Papadakis , +%%% Eirini Arvaniti +%%% and Kostis Sagonas +%%% +%%% This file is part of PropEr. +%%% +%%% PropEr 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 3 of the License, or +%%% (at your option) any later version. +%%% +%%% PropEr 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 PropEr. If not, see . + +%%% @copyright 2010-2013 Manolis Papadakis, Eirini Arvaniti and Kostis Sagonas +%%% @version {@version} +%%% @author Manolis Papadakis +%%% @doc Internal header file: This header is included in all PropEr source +%%% files. + +-include("proper_common.hrl"). + + +%%------------------------------------------------------------------------------ +%% Activate strip_types parse transform +%%------------------------------------------------------------------------------ + +-ifdef(NO_TYPES). +-compile({parse_transform, strip_types}). +-endif. + +%%------------------------------------------------------------------------------ +%% Random generator selection +%%------------------------------------------------------------------------------ + +-ifdef(USE_SFMT). +-define(RANDOM_MOD, sfmt). +-define(SEED_NAME, sfmt_seed). +-else. +-define(RANDOM_MOD, random). +-define(SEED_NAME, random_seed). +-endif. + +%%------------------------------------------------------------------------------ +%% Macros +%%------------------------------------------------------------------------------ + +-define(PROPERTY_PREFIX, "prop_"). + + +%%------------------------------------------------------------------------------ +%% Constants +%%------------------------------------------------------------------------------ + +-define(SEED_RANGE, 4294967296). +-define(MAX_ARITY, 20). +-define(MAX_TRIES_FACTOR, 5). +-define(ANY_SIMPLE_PROB, 3). +-define(ANY_BINARY_PROB, 1). +-define(ANY_EXPAND_PROB, 8). +-define(SMALL_RANGE_THRESHOLD, 16#FFFF). + + +%%------------------------------------------------------------------------------ +%% Common type aliases +%%------------------------------------------------------------------------------ + +%% TODO: Perhaps these should be moved inside modules. +-type mod_name() :: atom(). +-type fun_name() :: atom(). +-type size() :: non_neg_integer(). +-type length() :: non_neg_integer(). +-type position() :: pos_integer(). +-type frequency() :: pos_integer(). +-type seed() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}. + +-type abs_form() :: erl_parse:abstract_form(). +-type abs_expr() :: erl_parse:abstract_expr(). +-type abs_clause() :: erl_parse:abstract_clause(). + +%% TODO: Replace these with the appropriate types from stdlib. +-type abs_type() :: term(). +-type abs_rec_field() :: term(). + +-type loose_tuple(T) :: {} | {T} | {T,T} | {T,T,T} | {T,T,T,T} | {T,T,T,T,T} + | {T,T,T,T,T,T} | {T,T,T,T,T,T,T} | {T,T,T,T,T,T,T,T} + | {T,T,T,T,T,T,T,T,T} | {T,T,T,T,T,T,T,T,T,T} | tuple(). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_types.erl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_types.erl new file mode 100644 index 0000000000..fe83a0ba11 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_types.erl @@ -0,0 +1,1349 @@ +%%% Copyright 2010-2013 Manolis Papadakis , +%%% Eirini Arvaniti +%%% and Kostis Sagonas +%%% +%%% This file is part of PropEr. +%%% +%%% PropEr 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 3 of the License, or +%%% (at your option) any later version. +%%% +%%% PropEr 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 PropEr. If not, see . + +%%% @copyright 2010-2013 Manolis Papadakis, Eirini Arvaniti and Kostis Sagonas +%%% @version {@version} +%%% @author Manolis Papadakis + +%%% @doc Type manipulation functions and predefined types. +%%% +%%% == Basic types == +%%% This module defines all the basic types of the PropEr type system as +%%% functions. See the function index for an overview. +%%% +%%% Types can be combined in tuples or lists to produce other types. Exact +%%% values (such as exact numbers, atoms, binaries and strings) can be combined +%%% with types inside such structures, like in this example of the type of a +%%% tagged tuple: ``{'result', integer()}''. +%%% +%%% When including the PropEr header file, all +%%% API functions of this module are automatically +%%% imported, unless `PROPER_NO_IMPORTS' is defined. +%%% +%%% == Customized types == +%%% The following operators can be applied to basic types in order to produce +%%% new ones: +%%% +%%%
+%%%
`?LET(, , )'
+%%%
To produce an instance of this type, all appearances of the variables +%%% in `' are replaced inside `' by their corresponding values in a +%%% randomly generated instance of `'. It's OK for the `' part to +%%% evaluate to a type - in that case, an instance of the inner type is +%%% generated recursively.
+%%%
`?SUCHTHAT(, , )'
+%%%
This produces a specialization of `', which only includes those +%%% members of `' that satisfy the constraint `' - that is, +%%% those members for which the function `fun() -> end' returns +%%% `true'. If the constraint is very strict - that is, only a small +%%% percentage of instances of `' pass the test - it will take a lot of +%%% tries for the instance generation subsystem to randomly produce a valid +%%% instance. This will result in slower testing, and testing may even be +%%% stopped short, in case the `constraint_tries' limit is reached (see the +%%% "Options" section in the documentation of the {@link proper} module). If +%%% this is the case, it would be more appropriate to generate valid instances +%%% of the specialized type using the `?LET' macro. Also make sure that even +%%% small instances can satisfy the constraint, since PropEr will only try +%%% small instances at the start of testing. If this is not possible, you can +%%% instruct PropEr to start at a larger size, by supplying a suitable value +%%% for the `start_size' option (see the "Options" section in the +%%% documentation of the {@link proper} module).
+%%%
`?SUCHTHATMAYBE(, , )'
+%%%
Equivalent to the `?SUCHTHAT' macro, but the constraint `' +%%% is considered non-strict: if the `constraint_tries' limit is reached, the +%%% generator will just return an instance of `' instead of failing, +%%% even if that instance doesn't satisfy the constraint.
+%%%
`?SHRINK(, )'
+%%%
This creates a type whose instances are generated by evaluating the +%%% statement block `' (this may evaluate to a type, which will +%%% then be generated recursively). If an instance of such a type is to be +%%% shrunk, the generators in `' are first run to produce +%%% hopefully simpler instances of the type. Thus, the generators in the +%%% second argument should be simpler than the default. The simplest ones +%%% should be at the front of the list, since those are the generators +%%% preferred by the shrinking subsystem. Like the main `', the +%%% alternatives may also evaluate to a type, which is generated recursively. +%%%
+%%%
`?LETSHRINK(, , )'
+%%%
This is created by combining a `?LET' and a `?SHRINK' macro. Instances +%%% are generated by applying a randomly generated list of values inside +%%% `' (just like a `?LET', with the added constraint that the +%%% variables and types must be provided in a list - alternatively, +%%% `' may be a list or vector type). When shrinking instances +%%% of such a type, the sub-instances that were combined to produce it are +%%% first tried in place of the failing instance.
+%%%
`?LAZY()'
+%%%
This construct returns a type whose only purpose is to delay the +%%% evaluation of `' (`' can return a type, which will +%%% be generated recursively). Using this, you can simulate the lazy +%%% generation of instances: +%%% ``` stream() -> ?LAZY(frequency([ {1,[]}, {3,[0|stream()]} ])). ''' +%%% The above type produces lists of zeroes with an average length of 3. Note +%%% that, had we not enclosed the generator with a `?LAZY' macro, the +%%% evaluation would continue indefinitely, due to the eager evaluation of +%%% the Erlang language.
+%%%
`non_empty()'
+%%%
See the documentation for {@link non_empty/1}.
+%%%
`noshrink()'
+%%%
See the documentation for {@link noshrink/1}.
+%%%
`default(, )'
+%%%
See the documentation for {@link default/2}.
+%%%
`with_parameter(, , )'
+%%%
See the documentation for {@link with_parameter/3}.
+%%%
`with_parameters(, )'
+%%%
See the documentation for {@link with_parameters/2}.
+%%%
+%%% +%%% == Size manipulation == +%%% The following operators are related to the `size' parameter, which controls +%%% the maximum size of produced instances. The actual size of a produced +%%% instance is chosen randomly, but can never exceed the value of the `size' +%%% parameter at the moment of generation. A more accurate definition is the +%%% following: the maximum instance of `size S' can never be smaller than the +%%% maximum instance of `size S-1'. The actual size of an instance is measured +%%% differently for each type: the actual size of a list is its length, while +%%% the actual size of a tree may be the number of its internal nodes. Some +%%% types, e.g. unions, have no notion of size, thus their generation is not +%%% influenced by the value of `size'. The `size' parameter starts at 1 and +%%% grows automatically during testing. +%%% +%%%
+%%%
`?SIZED(, )'
+%%%
Creates a new type, whose instances are produced by replacing all +%%% appearances of the `' parameter inside the statement block +%%% `' with the value of the `size' parameter. It's OK for the +%%% `' to return a type - in that case, an instance of the inner +%%% type is generated recursively.
+%%%
`resize(, )'
+%%%
See the documentation for {@link resize/2}.
+%%%
+ +-module(proper_types). +-export([is_inst/2, is_inst/3]). + +-export([integer/2, float/2, atom/0, binary/0, binary/1, bitstring/0, + bitstring/1, list/1, vector/2, union/1, weighted_union/1, tuple/1, + loose_tuple/1, exactly/1, fixed_list/1, function/2, any/0, + shrink_list/1, safe_union/1, safe_weighted_union/1]). +-export([integer/0, non_neg_integer/0, pos_integer/0, neg_integer/0, range/2, + float/0, non_neg_float/0, number/0, boolean/0, byte/0, char/0, + list/0, tuple/0, string/0, wunion/1, term/0, timeout/0, arity/0]). +-export([int/0, nat/0, largeint/0, real/0, bool/0, choose/2, elements/1, + oneof/1, frequency/1, return/1, default/2, orderedlist/1, function0/1, + function1/1, function2/1, function3/1, function4/1, + weighted_default/2]). +-export([resize/2, non_empty/1, noshrink/1]). + +-export([cook_outer/1, is_type/1, equal_types/2, is_raw_type/1, to_binary/1, + from_binary/1, get_prop/2, find_prop/2, safe_is_instance/2, + is_instance/2, unwrap/1, weakly/1, strongly/1, satisfies_all/2, + new_type/2, subtype/2]). +-export([lazy/1, sized/1, bind/3, shrinkwith/2, add_constraint/3, + native_type/2, distlist/3, with_parameter/3, with_parameters/2, + parameter/1, parameter/2]). +-export([le/2]). + +-export_type([type/0, raw_type/0, extint/0, extnum/0]). + +-include("proper_internal.hrl"). + + +%%------------------------------------------------------------------------------ +%% Comparison with erl_types +%%------------------------------------------------------------------------------ + +%% Missing types +%% ------------------- +%% will do: +%% records, maybe_improper_list(T,S), nonempty_improper_list(T,S) +%% maybe_improper_list(), maybe_improper_list(T), iolist, iodata +%% don't need: +%% nonempty_{list,string,maybe_improper_list} +%% won't do: +%% pid, port, ref, identifier, none, no_return, module, mfa, node +%% array, dict, digraph, set, gb_tree, gb_set, queue, tid + +%% Missing type information +%% ------------------------ +%% bin types: +%% other unit sizes? what about size info? +%% functions: +%% generally some fun, unspecified number of arguments but specified +%% return type +%% any: +%% doesn't cover functions and improper lists + + +%%------------------------------------------------------------------------------ +%% Type declaration macros +%%------------------------------------------------------------------------------ + +-define(BASIC(PropList), new_type(PropList,basic)). +-define(WRAPPER(PropList), new_type(PropList,wrapper)). +-define(CONSTRUCTED(PropList), new_type(PropList,constructed)). +-define(CONTAINER(PropList), new_type(PropList,container)). +-define(SUBTYPE(Type,PropList), subtype(PropList,Type)). + + +%%------------------------------------------------------------------------------ +%% Types +%%------------------------------------------------------------------------------ + +-type type_kind() :: 'basic' | 'wrapper' | 'constructed' | 'container' | atom(). +-type instance_test() :: fun((proper_gen:imm_instance()) -> boolean()) + | {'typed', + fun((proper_types:type(), + proper_gen:imm_instance()) -> boolean())}. +-type index() :: pos_integer(). +%% @alias +-type value() :: term(). +%% @private_type +%% @alias +-type extint() :: integer() | 'inf'. +%% @private_type +%% @alias +-type extnum() :: number() | 'inf'. +-type constraint_fun() :: fun((proper_gen:instance()) -> boolean()). + +-opaque type() :: {'$type', [type_prop()]}. +%% A type of the PropEr type system +%% @type raw_type(). You can consider this as an equivalent of {@type type()}. +-type raw_type() :: type() | [raw_type()] | loose_tuple(raw_type()) | term(). +-type type_prop_name() :: 'kind' | 'generator' | 'reverse_gen' | 'parts_type' + | 'combine' | 'alt_gens' | 'shrink_to_parts' + | 'size_transform' | 'is_instance' | 'shrinkers' + | 'noshrink' | 'internal_type' | 'internal_types' + | 'get_length' | 'split' | 'join' | 'get_indices' + | 'remove' | 'retrieve' | 'update' | 'constraints' + | 'parameters' | 'env' | 'subenv'. + +-type type_prop_value() :: term(). +-type type_prop() :: + {'kind', type_kind()} + | {'generator', proper_gen:generator()} + | {'reverse_gen', proper_gen:reverse_gen()} + | {'parts_type', type()} + | {'combine', proper_gen:combine_fun()} + | {'alt_gens', proper_gen:alt_gens()} + | {'shrink_to_parts', boolean()} + | {'size_transform', fun((size()) -> size())} + | {'is_instance', instance_test()} + | {'shrinkers', [proper_shrink:shrinker()]} + | {'noshrink', boolean()} + | {'internal_type', raw_type()} + | {'internal_types', tuple() | maybe_improper_list(type(),type() | [])} + %% The items returned by 'remove' must be of this type. + | {'get_length', fun((proper_gen:imm_instance()) -> length())} + %% If this is a container type, this should return the number of elements + %% it contains. + | {'split', fun((proper_gen:imm_instance()) -> [proper_gen:imm_instance()]) + | fun((length(),proper_gen:imm_instance()) -> + {proper_gen:imm_instance(),proper_gen:imm_instance()})} + %% If present, the appropriate form depends on whether get_length is + %% defined: if get_length is undefined, this must be in the one-argument + %% form (e.g. a tree should be split into its subtrees), else it must be + %% in the two-argument form (e.g. a list should be split in two at the + %% index provided). + | {'join', fun((proper_gen:imm_instance(),proper_gen:imm_instance()) -> + proper_gen:imm_instance())} + | {'get_indices', fun((proper_types:type(), + proper_gen:imm_instance()) -> [index()])} + %% If this is a container type, this should return a list of indices we + %% can use to remove or insert elements from the given instance. + | {'remove', fun((index(),proper_gen:imm_instance()) -> + proper_gen:imm_instance())} + | {'retrieve', fun((index(), proper_gen:imm_instance() | tuple() + | maybe_improper_list(type(),type() | [])) -> + value() | type())} + | {'update', fun((index(),value(),proper_gen:imm_instance()) -> + proper_gen:imm_instance())} + | {'constraints', [{constraint_fun(), boolean()}]} + %% A list of constraints on instances of this type: each constraint is a + %% tuple of a fun that must return 'true' for each valid instance and a + %% boolean field that specifies whether the condition is strict. + | {'parameters', [{atom(),value()}]} + | {'env', term()} + | {'subenv', term()}. + + +%%------------------------------------------------------------------------------ +%% Type manipulation functions +%%------------------------------------------------------------------------------ + +%% TODO: We shouldn't need the fully qualified type name in the range of these +%% functions. + +%% @private +%% TODO: just cook/1 ? +-spec cook_outer(raw_type()) -> proper_types:type(). +cook_outer(Type = {'$type',_Props}) -> + Type; +cook_outer(RawType) -> + if + is_tuple(RawType) -> tuple(tuple_to_list(RawType)); + %% CAUTION: this must handle improper lists + is_list(RawType) -> fixed_list(RawType); + %% default case (covers integers, floats, atoms, binaries, ...): + true -> exactly(RawType) + end. + +%% @private +-spec is_type(term()) -> boolean(). +is_type({'$type',_Props}) -> + true; +is_type(_) -> + false. + +%% @private +-spec equal_types(proper_types:type(), proper_types:type()) -> boolean(). +equal_types(SameType, SameType) -> + true; +equal_types(_, _) -> + false. + +%% @private +-spec is_raw_type(term()) -> boolean(). +is_raw_type({'$type',_TypeProps}) -> + true; +is_raw_type(X) -> + if + is_tuple(X) -> is_raw_type_list(tuple_to_list(X)); + is_list(X) -> is_raw_type_list(X); + true -> false + end. + +-spec is_raw_type_list(maybe_improper_list()) -> boolean(). +%% CAUTION: this must handle improper lists +is_raw_type_list(List) -> + proper_arith:safe_any(fun is_raw_type/1, List). + +%% @private +-spec to_binary(proper_types:type()) -> binary(). +to_binary(Type) -> + term_to_binary(Type). + +%% @private +%% TODO: restore: -spec from_binary(binary()) -> proper_types:type(). +from_binary(Binary) -> + binary_to_term(Binary). + +-spec type_from_list([type_prop()]) -> proper_types:type(). +type_from_list(KeyValueList) -> + {'$type',KeyValueList}. + +-spec add_prop(type_prop_name(), type_prop_value(), proper_types:type()) -> + proper_types:type(). +add_prop(PropName, Value, {'$type',Props}) -> + {'$type',lists:keystore(PropName, 1, Props, {PropName, Value})}. + +-spec add_props([type_prop()], proper_types:type()) -> proper_types:type(). +add_props(PropList, {'$type',OldProps}) -> + {'$type', lists:foldl(fun({N,_}=NV,Acc) -> + lists:keystore(N, 1, Acc, NV) + end, OldProps, PropList)}. + +-spec append_to_prop(type_prop_name(), type_prop_value(), + proper_types:type()) -> proper_types:type(). +append_to_prop(PropName, Value, {'$type',Props}) -> + Val = case lists:keyfind(PropName, 1, Props) of + {PropName, V} -> + V; + _ -> + [] + end, + {'$type', lists:keystore(PropName, 1, Props, + {PropName, lists:reverse([Value|Val])})}. + +-spec append_list_to_prop(type_prop_name(), [type_prop_value()], + proper_types:type()) -> proper_types:type(). +append_list_to_prop(PropName, List, {'$type',Props}) -> + {PropName, Val} = lists:keyfind(PropName, 1, Props), + {'$type', lists:keystore(PropName, 1, Props, {PropName, Val++List})}. + +%% @private +-spec get_prop(type_prop_name(), proper_types:type()) -> type_prop_value(). +get_prop(PropName, {'$type',Props}) -> + {_PropName, Val} = lists:keyfind(PropName, 1, Props), + Val. + +%% @private +-spec find_prop(type_prop_name(), proper_types:type()) -> + {'ok',type_prop_value()} | 'error'. +find_prop(PropName, {'$type',Props}) -> + case lists:keyfind(PropName, 1, Props) of + {PropName, Value} -> + {ok, Value}; + _ -> + error + end. + +%% @private +-spec new_type([type_prop()], type_kind()) -> proper_types:type(). +new_type(PropList, Kind) -> + Type = type_from_list(PropList), + add_prop(kind, Kind, Type). + +%% @private +-spec subtype([type_prop()], proper_types:type()) -> proper_types:type(). +%% TODO: should the 'is_instance' function etc. be reset for subtypes? +subtype(PropList, Type) -> + add_props(PropList, Type). + +%% @private +-spec is_inst(proper_gen:instance(), raw_type()) -> + boolean() | {'error',{'typeserver',term()}}. +is_inst(Instance, RawType) -> + is_inst(Instance, RawType, 10). + +%% @private +-spec is_inst(proper_gen:instance(), raw_type(), size()) -> + boolean() | {'error',{'typeserver',term()}}. +is_inst(Instance, RawType, Size) -> + proper:global_state_init_size(Size), + Result = safe_is_instance(Instance, RawType), + proper:global_state_erase(), + Result. + +%% @private +-spec safe_is_instance(proper_gen:imm_instance(), raw_type()) -> + boolean() | {'error',{'typeserver',term()}}. +safe_is_instance(ImmInstance, RawType) -> + try is_instance(ImmInstance, RawType) catch + throw:{'$typeserver',SubReason} -> {error, {typeserver,SubReason}} + end. + +%% @private +-spec is_instance(proper_gen:imm_instance(), raw_type()) -> boolean(). +%% TODO: If the second argument is not a type, let it pass (don't even check for +%% term equality?) - if it's a raw type, don't cook it, instead recurse +%% into it. +is_instance(ImmInstance, RawType) -> + CleanInstance = proper_gen:clean_instance(ImmInstance), + Type = cook_outer(RawType), + (case get_prop(kind, Type) of + wrapper -> wrapper_test(ImmInstance, Type); + constructed -> constructed_test(ImmInstance, Type); + _ -> false + end + orelse + case find_prop(is_instance, Type) of + {ok,{typed, IsInstance}} -> IsInstance(Type, ImmInstance); + {ok,IsInstance} -> IsInstance(ImmInstance); + error -> false + end) + andalso weakly(satisfies_all(CleanInstance, Type)). + +-spec wrapper_test(proper_gen:imm_instance(), proper_types:type()) -> boolean(). +wrapper_test(ImmInstance, Type) -> + %% TODO: check if it's actually a raw type that's returned? + lists:any(fun(T) -> is_instance(ImmInstance, T) end, unwrap(Type)). + +%% @private +%% TODO: restore:-spec unwrap(proper_types:type()) -> [proper_types:type(),...]. +%% TODO: check if it's actually a raw type that's returned? +unwrap(Type) -> + RawInnerTypes = proper_gen:alt_gens(Type) ++ [proper_gen:normal_gen(Type)], + [cook_outer(T) || T <- RawInnerTypes]. + +-spec constructed_test(proper_gen:imm_instance(), proper_types:type()) -> + boolean(). +constructed_test({'$used',ImmParts,ImmInstance}, Type) -> + PartsType = get_prop(parts_type, Type), + Combine = get_prop(combine, Type), + is_instance(ImmParts, PartsType) andalso + begin + %% TODO: check if it's actually a raw type that's returned? + %% TODO: move construction code to proper_gen + %% TODO: non-type => should we check for strict term equality? + RawInnerType = Combine(proper_gen:clean_instance(ImmParts)), + is_instance(ImmInstance, RawInnerType) + end; +constructed_test({'$to_part',ImmInstance}, Type) -> + PartsType = get_prop(parts_type, Type), + get_prop(shrink_to_parts, Type) =:= true andalso + %% TODO: we reject non-container types + get_prop(kind, PartsType) =:= container andalso + case {find_prop(internal_type,PartsType), + find_prop(internal_types,PartsType)} of + {{ok,EachPartType},error} -> + %% The parts are in a list or a vector. + is_instance(ImmInstance, EachPartType); + {error,{ok,PartTypesList}} -> + %% The parts are in a fixed list. + %% TODO: It should always be a proper list. + lists:any(fun(T) -> is_instance(ImmInstance,T) end, PartTypesList) + end; +constructed_test(_CleanInstance, _Type) -> + %% TODO: can we do anything better? + false. + +%% @private +-spec weakly({boolean(),boolean()}) -> boolean(). +weakly({B1,_B2}) -> B1. + +%% @private +-spec strongly({boolean(),boolean()}) -> boolean(). +strongly({_B1,B2}) -> B2. + +-spec satisfies(proper_gen:instance(), {constraint_fun(),boolean()}) + -> {boolean(),boolean()}. +satisfies(Instance, {Test,false}) -> + {true,Test(Instance)}; +satisfies(Instance, {Test,true}) -> + Result = Test(Instance), + {Result,Result}. + +%% @private +-spec satisfies_all(proper_gen:instance(), proper_types:type()) -> + {boolean(),boolean()}. +satisfies_all(Instance, Type) -> + case find_prop(constraints, Type) of + {ok, Constraints} -> + L = [satisfies(Instance, C) || C <- Constraints], + {L1,L2} = lists:unzip(L), + {lists:all(fun(B) -> B end, L1), lists:all(fun(B) -> B end, L2)}; + error -> + {true,true} + end. + + +%%------------------------------------------------------------------------------ +%% Type definition functions +%%------------------------------------------------------------------------------ + +%% @private +-spec lazy(proper_gen:nosize_generator()) -> proper_types:type(). +lazy(Gen) -> + ?WRAPPER([ + {generator, Gen} + ]). + +%% @private +-spec sized(proper_gen:sized_generator()) -> proper_types:type(). +sized(Gen) -> + ?WRAPPER([ + {generator, Gen} + ]). + +%% @private +-spec bind(raw_type(), proper_gen:combine_fun(), boolean()) -> + proper_types:type(). +bind(RawPartsType, Combine, ShrinkToParts) -> + PartsType = cook_outer(RawPartsType), + ?CONSTRUCTED([ + {parts_type, PartsType}, + {combine, Combine}, + {shrink_to_parts, ShrinkToParts} + ]). + +%% @private +-spec shrinkwith(proper_gen:nosize_generator(), proper_gen:alt_gens()) -> + proper_types:type(). +shrinkwith(Gen, DelaydAltGens) -> + ?WRAPPER([ + {generator, Gen}, + {alt_gens, DelaydAltGens} + ]). + +%% @private +-spec add_constraint(raw_type(), constraint_fun(), boolean()) -> + proper_types:type(). +add_constraint(RawType, Condition, IsStrict) -> + Type = cook_outer(RawType), + append_to_prop(constraints, {Condition,IsStrict}, Type). + +%% @private +-spec native_type(mod_name(), string()) -> proper_types:type(). +native_type(Mod, TypeStr) -> + ?WRAPPER([ + {generator, fun() -> proper_gen:native_type_gen(Mod,TypeStr) end} + ]). + + +%%------------------------------------------------------------------------------ +%% Basic types +%%------------------------------------------------------------------------------ + +%% @doc All integers between `Low' and `High', bounds included. +%% `Low' and `High' must be Erlang expressions that evaluate to integers, with +%% `Low =< High'. Additionally, `Low' and `High' may have the value `inf', in +%% which case they represent minus infinity and plus infinity respectively. +%% Instances shrink towards 0 if `Low =< 0 =< High', or towards the bound with +%% the smallest absolute value otherwise. +-spec integer(extint(), extint()) -> proper_types:type(). +integer(Low, High) -> + ?BASIC([ + {env, {Low, High}}, + {generator, {typed, fun integer_gen/2}}, + {is_instance, {typed, fun integer_is_instance/2}}, + {shrinkers, [fun number_shrinker/3]} + ]). + +integer_gen(Type, Size) -> + {Low, High} = get_prop(env, Type), + proper_gen:integer_gen(Size, Low, High). + +integer_is_instance(Type, X) -> + {Low, High} = get_prop(env, Type), + is_integer(X) andalso le(Low, X) andalso le(X, High). + +number_shrinker(X, Type, S) -> + {Low, High} = get_prop(env, Type), + proper_shrink:number_shrinker(X, Low, High, S). + +%% @doc All floats between `Low' and `High', bounds included. +%% `Low' and `High' must be Erlang expressions that evaluate to floats, with +%% `Low =< High'. Additionally, `Low' and `High' may have the value `inf', in +%% which case they represent minus infinity and plus infinity respectively. +%% Instances shrink towards 0.0 if `Low =< 0.0 =< High', or towards the bound +%% with the smallest absolute value otherwise. +-spec float(extnum(), extnum()) -> proper_types:type(). +float(Low, High) -> + ?BASIC([ + {env, {Low, High}}, + {generator, {typed, fun float_gen/2}}, + {is_instance, {typed, fun float_is_instance/2}}, + {shrinkers, [fun number_shrinker/3]} + ]). + +float_gen(Type, Size) -> + {Low, High} = get_prop(env, Type), + proper_gen:float_gen(Size, Low, High). + +float_is_instance(Type, X) -> + {Low, High} = get_prop(env, Type), + is_float(X) andalso le(Low, X) andalso le(X, High). + +%% @private +-spec le(extnum(), extnum()) -> boolean(). +le(inf, _B) -> true; +le(_A, inf) -> true; +le(A, B) -> A =< B. + +%% @doc All atoms. All atoms used internally by PropEr start with a '`$'', so +%% such atoms will never be produced as instances of this type. You should also +%% refrain from using such atoms in your code, to avoid a potential clash. +%% Instances shrink towards the empty atom, ''. +-spec atom() -> proper_types:type(). +atom() -> + ?WRAPPER([ + {generator, fun proper_gen:atom_gen/1}, + {reverse_gen, fun proper_gen:atom_rev/1}, + {size_transform, fun(Size) -> erlang:min(Size,255) end}, + {is_instance, fun atom_is_instance/1} + ]). + +atom_is_instance(X) -> + is_atom(X) + %% We return false for atoms starting with '$', since these are + %% atoms used internally and never produced by the atom generator. + andalso (X =:= '' orelse hd(atom_to_list(X)) =/= $$). + +%% @doc All binaries. Instances shrink towards the empty binary, `<<>>'. +-spec binary() -> proper_types:type(). +binary() -> + ?WRAPPER([ + {generator, fun proper_gen:binary_gen/1}, + {reverse_gen, fun proper_gen:binary_rev/1}, + {is_instance, fun erlang:is_binary/1} + ]). + +%% @doc All binaries with a byte size of `Len'. +%% `Len' must be an Erlang expression that evaluates to a non-negative integer. +%% Instances shrink towards binaries of zeroes. +-spec binary(length()) -> proper_types:type(). +binary(Len) -> + ?WRAPPER([ + {env, Len}, + {generator, {typed, fun binary_len_gen/1}}, + {reverse_gen, fun proper_gen:binary_rev/1}, + {is_instance, {typed, fun binary_len_is_instance/2}} + ]). + +binary_len_gen(Type) -> + Len = get_prop(env, Type), + proper_gen:binary_len_gen(Len). + +binary_len_is_instance(Type, X) -> + Len = get_prop(env, Type), + is_binary(X) andalso byte_size(X) =:= Len. + +%% @doc All bitstrings. Instances shrink towards the empty bitstring, `<<>>'. +-spec bitstring() -> proper_types:type(). +bitstring() -> + ?WRAPPER([ + {generator, fun proper_gen:bitstring_gen/1}, + {reverse_gen, fun proper_gen:bitstring_rev/1}, + {is_instance, fun erlang:is_bitstring/1} + ]). + +%% @doc All bitstrings with a bit size of `Len'. +%% `Len' must be an Erlang expression that evaluates to a non-negative integer. +%% Instances shrink towards bitstrings of zeroes +-spec bitstring(length()) -> proper_types:type(). +bitstring(Len) -> + ?WRAPPER([ + {env, Len}, + {generator, {typed, fun bitstring_len_gen/1}}, + {reverse_gen, fun proper_gen:bitstring_rev/1}, + {is_instance, {typed, fun bitstring_len_is_instance/2}} + ]). + +bitstring_len_gen(Type) -> + Len = get_prop(env, Type), + proper_gen:bitstring_len_gen(Len). + +bitstring_len_is_instance(Type, X) -> + Len = get_prop(env, Type), + is_bitstring(X) andalso bit_size(X) =:= Len. + +%% @doc All lists containing elements of type `ElemType'. +%% Instances shrink towards the empty list, `[]'. +-spec list(ElemType::raw_type()) -> proper_types:type(). +% TODO: subtyping would be useful here (list, vector, fixed_list) +list(RawElemType) -> + ElemType = cook_outer(RawElemType), + ?CONTAINER([ + {generator, {typed, fun list_gen/2}}, + {is_instance, {typed, fun list_is_instance/2}}, + {internal_type, ElemType}, + {get_length, fun erlang:length/1}, + {split, fun lists:split/2}, + {join, fun lists:append/2}, + {get_indices, fun list_get_indices/2}, + {remove, fun proper_arith:list_remove/2}, + {retrieve, fun lists:nth/2}, + {update, fun proper_arith:list_update/3} + ]). + +list_gen(Type, Size) -> + ElemType = get_prop(internal_type, Type), + proper_gen:list_gen(Size, ElemType). + +list_is_instance(Type, X) -> + ElemType = get_prop(internal_type, Type), + list_test(X, ElemType). + +%% @doc A type that generates exactly the list `List'. Instances shrink towards +%% shorter sublists of the original list. +-spec shrink_list([term()]) -> proper_types:type(). +shrink_list(List) -> + ?CONTAINER([ + {env, List}, + {generator, {typed, fun shrink_list_gen/1}}, + {is_instance, {typed, fun shrink_list_is_instance/2}}, + {get_length, fun erlang:length/1}, + {split, fun lists:split/2}, + {join, fun lists:append/2}, + {get_indices, fun list_get_indices/2}, + {remove, fun proper_arith:list_remove/2} + ]). + +shrink_list_gen(Type) -> + get_prop(env, Type). + +shrink_list_is_instance(Type, X) -> + List = get_prop(env, Type), + is_sublist(X, List). + +-spec is_sublist([term()], [term()]) -> boolean(). +is_sublist([], _) -> true; +is_sublist(_, []) -> false; +is_sublist([H|T1], [H|T2]) -> is_sublist(T1, T2); +is_sublist(Slice, [_|T2]) -> is_sublist(Slice, T2). + +-spec list_test(proper_gen:imm_instance(), proper_types:type()) -> boolean(). +list_test(X, ElemType) -> + is_list(X) andalso lists:all(fun(E) -> is_instance(E, ElemType) end, X). + +%% @private +-spec list_get_indices(proper_gen:generator(), list()) -> [position()]. +list_get_indices(_, List) -> + lists:seq(1, length(List)). + +%% @private +%% This assumes that: +%% - instances of size S are always valid instances of size >S +%% - any recursive calls inside Gen are lazy +-spec distlist(size(), proper_gen:sized_generator(), boolean()) -> + proper_types:type(). +distlist(Size, Gen, NonEmpty) -> + ParentType = case NonEmpty of + true -> non_empty(list(Gen(Size))); + false -> list(Gen(Size)) + end, + ?SUBTYPE(ParentType, [ + {subenv, {Size, Gen, NonEmpty}}, + {generator, {typed, fun distlist_gen/1}} + ]). + +distlist_gen(Type) -> + {Size, Gen, NonEmpty} = get_prop(subenv, Type), + proper_gen:distlist_gen(Size, Gen, NonEmpty). + +%% @doc All lists of length `Len' containing elements of type `ElemType'. +%% `Len' must be an Erlang expression that evaluates to a non-negative integer. +-spec vector(length(), ElemType::raw_type()) -> proper_types:type(). +vector(Len, RawElemType) -> + ElemType = cook_outer(RawElemType), + ?CONTAINER([ + {env, Len}, + {generator, {typed, fun vector_gen/1}}, + {is_instance, {typed, fun vector_is_instance/2}}, + {internal_type, ElemType}, + {get_indices, fun vector_get_indices/2}, + {retrieve, fun lists:nth/2}, + {update, fun proper_arith:list_update/3} + ]). + +vector_gen(Type) -> + Len = get_prop(env, Type), + ElemType = get_prop(internal_type, Type), + proper_gen:vector_gen(Len, ElemType). + +vector_is_instance(Type, X) -> + Len = get_prop(env, Type), + ElemType = get_prop(internal_type, Type), + is_list(X) + andalso length(X) =:= Len + andalso lists:all(fun(E) -> is_instance(E, ElemType) end, X). + +vector_get_indices(Type, _X) -> + lists:seq(1, get_prop(env, Type)). + +%% @doc The union of all types in `ListOfTypes'. `ListOfTypes' can't be empty. +%% The random instance generator is equally likely to choose any one of the +%% types in `ListOfTypes'. The shrinking subsystem will always try to shrink an +%% instance of a type union to an instance of the first type in `ListOfTypes', +%% thus you should write the simplest case first. +-spec union(ListOfTypes::[raw_type(),...]) -> proper_types:type(). +union(RawChoices) -> + Choices = [cook_outer(C) || C <- RawChoices], + ?BASIC([ + {env, Choices}, + {generator, {typed, fun union_gen/1}}, + {is_instance, {typed, fun union_is_instance/2}}, + {shrinkers, [fun union_shrinker_1/3, fun union_shrinker_2/3]} + ]). + +union_gen(Type) -> + Choices = get_prop(env,Type), + proper_gen:union_gen(Choices). + +union_is_instance(Type, X) -> + Choices = get_prop(env, Type), + lists:any(fun(C) -> is_instance(X, C) end, Choices). + +union_shrinker_1(X, Type, S) -> + Choices = get_prop(env, Type), + proper_shrink:union_first_choice_shrinker(X, Choices, S). + +union_shrinker_2(X, Type, S) -> + Choices = get_prop(env, Type), + proper_shrink:union_recursive_shrinker(X, Choices, S). + +%% @doc A specialization of {@link union/1}, where each type in `ListOfTypes' is +%% assigned a frequency. Frequencies must be Erlang expressions that evaluate to +%% positive integers. Types with larger frequencies are more likely to be chosen +%% by the random instance generator. The shrinking subsystem will ignore the +%% frequencies and try to shrink towards the first type in the list. +-spec weighted_union(ListOfTypes::[{frequency(),raw_type()},...]) -> + proper_types:type(). +weighted_union(RawFreqChoices) -> + CookFreqType = fun({Freq,RawType}) -> {Freq,cook_outer(RawType)} end, + FreqChoices = lists:map(CookFreqType, RawFreqChoices), + Choices = [T || {_F,T} <- FreqChoices], + ?SUBTYPE(union(Choices), [ + {subenv, FreqChoices}, + {generator, {typed, fun weighted_union_gen/1}} + ]). + +weighted_union_gen(Gen) -> + FreqChoices = get_prop(subenv, Gen), + proper_gen:weighted_union_gen(FreqChoices). + +%% @private +-spec safe_union([raw_type(),...]) -> proper_types:type(). +safe_union(RawChoices) -> + Choices = [cook_outer(C) || C <- RawChoices], + subtype( + [{subenv, Choices}, + {generator, {typed, fun safe_union_gen/1}}], + union(Choices)). + +safe_union_gen(Type) -> + Choices = get_prop(subenv, Type), + proper_gen:safe_union_gen(Choices). + +%% @private +-spec safe_weighted_union([{frequency(),raw_type()},...]) -> + proper_types:type(). +safe_weighted_union(RawFreqChoices) -> + CookFreqType = fun({Freq,RawType}) -> + {Freq,cook_outer(RawType)} end, + FreqChoices = lists:map(CookFreqType, RawFreqChoices), + Choices = [T || {_F,T} <- FreqChoices], + subtype([{subenv, FreqChoices}, + {generator, {typed, fun safe_weighted_union_gen/1}}], + union(Choices)). + +safe_weighted_union_gen(Type) -> + FreqChoices = get_prop(subenv, Type), + proper_gen:safe_weighted_union_gen(FreqChoices). + +%% @doc All tuples whose i-th element is an instance of the type at index i of +%% `ListOfTypes'. Also written simply as a tuple of types. +-spec tuple(ListOfTypes::[raw_type()]) -> proper_types:type(). +tuple(RawFields) -> + Fields = [cook_outer(F) || F <- RawFields], + ?CONTAINER([ + {env, Fields}, + {generator, {typed, fun tuple_gen/1}}, + {is_instance, {typed, fun tuple_is_instance/2}}, + {internal_types, list_to_tuple(Fields)}, + {get_indices, fun tuple_get_indices/2}, + {retrieve, fun erlang:element/2}, + {update, fun tuple_update/3} + ]). + +tuple_gen(Type) -> + Fields = get_prop(env, Type), + proper_gen:tuple_gen(Fields). + +tuple_is_instance(Type, X) -> + Fields = get_prop(env, Type), + is_tuple(X) andalso fixed_list_test(tuple_to_list(X), Fields). + +tuple_get_indices(Type, _X) -> + lists:seq(1, length(get_prop(env, Type))). + +-spec tuple_update(index(), value(), tuple()) -> tuple(). +tuple_update(Index, NewElem, Tuple) -> + setelement(Index, Tuple, NewElem). + +%% @doc Tuples whose elements are all of type `ElemType'. +%% Instances shrink towards the 0-size tuple, `{}'. +-spec loose_tuple(ElemType::raw_type()) -> proper_types:type(). +loose_tuple(RawElemType) -> + ElemType = cook_outer(RawElemType), + ?WRAPPER([ + {env, ElemType}, + {generator, {typed, fun loose_tuple_gen/2}}, + {reverse_gen, {typed, fun loose_tuple_rev/2}}, + {is_instance, {typed, fun loose_tuple_is_instance/2}} + ]). + +loose_tuple_gen(Type, Size) -> + ElemType = get_prop(env, Type), + proper_gen:loose_tuple_gen(Size, ElemType). + +loose_tuple_rev(Type, X) -> + ElemType = get_prop(env, Type), + proper_gen:loose_tuple_rev(X, ElemType). + +loose_tuple_is_instance(Type, X) -> + ElemType = get_prop(env, Type), + is_tuple(X) andalso list_test(tuple_to_list(X), ElemType). + +%% @doc Singleton type consisting only of `E'. `E' must be an evaluated term. +%% Also written simply as `E'. +-spec exactly(term()) -> proper_types:type(). +exactly(E) -> + ?BASIC([ + {env, E}, + {generator, {typed, fun exactly_gen/1}}, + {is_instance, {typed, fun exactly_is_instance/2}} + ]). + +exactly_gen(Type) -> + E = get_prop(env, Type), + proper_gen:exactly_gen(E). + +exactly_is_instance(Type, X) -> + E = get_prop(env, Type), + X =:= E. + +%% @doc All lists whose i-th element is an instance of the type at index i of +%% `ListOfTypes'. Also written simply as a list of types. +-spec fixed_list(ListOfTypes::maybe_improper_list(raw_type(),raw_type()|[])) -> + proper_types:type(). +fixed_list(MaybeImproperRawFields) -> + %% CAUTION: must handle improper lists + {Fields, Internal, Len, Retrieve, Update} = + case proper_arith:cut_improper_tail(MaybeImproperRawFields) of + % TODO: have cut_improper_tail return the length and use it in test? + {ProperRawHead, ImproperRawTail} -> + HeadLen = length(ProperRawHead), + CookedHead = [cook_outer(F) || F <- ProperRawHead], + CookedTail = cook_outer(ImproperRawTail), + {{CookedHead,CookedTail}, + CookedHead ++ CookedTail, + HeadLen + 1, + fun(I,L) -> improper_list_retrieve(I, L, HeadLen) end, + fun(I,V,L) -> improper_list_update(I, V, L, HeadLen) end}; + ProperRawFields -> + LocalFields = [cook_outer(F) || F <- ProperRawFields], + {LocalFields, + LocalFields, + length(ProperRawFields), + fun lists:nth/2, + fun proper_arith:list_update/3} + end, + ?CONTAINER([ + {env, {Fields, Len}}, + {generator, {typed, fun fixed_list_gen/1}}, + {is_instance, {typed, fun fixed_list_is_instance/2}}, + {internal_types, Internal}, + {get_indices, fun fixed_list_get_indices/2}, + {retrieve, Retrieve}, + {update, Update} + ]). + +fixed_list_gen(Type) -> + {Fields, _} = get_prop(env, Type), + proper_gen:fixed_list_gen(Fields). + +fixed_list_is_instance(Type, X) -> + {Fields, _} = get_prop(env, Type), + fixed_list_test(X, Fields). + +fixed_list_get_indices(Type, _X) -> + {_, Len} = get_prop(env, Type), + lists:seq(1, Len). + +-spec fixed_list_test(proper_gen:imm_instance(), + [proper_types:type()] | {[proper_types:type()], + proper_types:type()}) -> + boolean(). +fixed_list_test(X, {ProperHead,ImproperTail}) -> + is_list(X) andalso + begin + ProperHeadLen = length(ProperHead), + proper_arith:head_length(X) >= ProperHeadLen andalso + begin + {XHead,XTail} = lists:split(ProperHeadLen, X), + fixed_list_test(XHead, ProperHead) + andalso is_instance(XTail, ImproperTail) + end + end; +fixed_list_test(X, ProperFields) -> + is_list(X) + andalso length(X) =:= length(ProperFields) + andalso lists:all(fun({E,T}) -> is_instance(E, T) end, + lists:zip(X, ProperFields)). + +%% TODO: Move these 2 functions to proper_arith? +-spec improper_list_retrieve(index(), nonempty_improper_list(value(),value()), + pos_integer()) -> value(). +improper_list_retrieve(Index, List, HeadLen) -> + case Index =< HeadLen of + true -> lists:nth(Index, List); + false -> lists:nthtail(HeadLen, List) + end. + +-spec improper_list_update(index(), value(), + nonempty_improper_list(value(),value()), + pos_integer()) -> + nonempty_improper_list(value(),value()). +improper_list_update(Index, Value, List, HeadLen) -> + case Index =< HeadLen of + %% TODO: This happens to work, but is not implied by list_update's spec. + true -> proper_arith:list_update(Index, Value, List); + false -> lists:sublist(List, HeadLen) ++ Value + end. + +%% @doc All pure functions that map instances of `ArgTypes' to instances of +%% `RetType'. The syntax `function(Arity, RetType)' is also acceptable. +-spec function(ArgTypes::[raw_type()] | arity(), RetType::raw_type()) -> + proper_types:type(). +function(Arity, RawRetType) when is_integer(Arity), Arity >= 0, Arity =< 255 -> + RetType = cook_outer(RawRetType), + ?BASIC([ + {env, {Arity, RetType}}, + {generator, {typed, fun function_gen/1}}, + {is_instance, {typed, fun function_is_instance/2}} + ]); +function(RawArgTypes, RawRetType) -> + function(length(RawArgTypes), RawRetType). + +function_gen(Type) -> + {Arity, RetType} = get_prop(env, Type), + proper_gen:function_gen(Arity, RetType). + +function_is_instance(Type, X) -> + {Arity, RetType} = get_prop(env, Type), + is_function(X, Arity) + %% TODO: what if it's not a function we produced? + andalso equal_types(RetType, proper_gen:get_ret_type(X)). + +%% @doc All Erlang terms (that PropEr can produce). For reasons of efficiency, +%% functions are never produced as instances of this type.
+%% CAUTION: Instances of this type are expensive to produce, shrink and instance- +%% check, both in terms of processing time and consumed memory. Only use this +%% type if you are certain that you need it. +-spec any() -> proper_types:type(). +any() -> + AllTypes = [integer(),float(),atom(),bitstring(),?LAZY(loose_tuple(any())), + ?LAZY(list(any()))], + ?SUBTYPE(union(AllTypes), [ + {generator, fun proper_gen:any_gen/1} + ]). + + +%%------------------------------------------------------------------------------ +%% Type aliases +%%------------------------------------------------------------------------------ + +%% @equiv integer(inf, inf) +-spec integer() -> proper_types:type(). +integer() -> integer(inf, inf). + +%% @equiv integer(0, inf) +-spec non_neg_integer() -> proper_types:type(). +non_neg_integer() -> integer(0, inf). + +%% @equiv integer(1, inf) +-spec pos_integer() -> proper_types:type(). +pos_integer() -> integer(1, inf). + +%% @equiv integer(inf, -1) +-spec neg_integer() -> proper_types:type(). +neg_integer() -> integer(inf, -1). + +%% @equiv integer(Low, High) +-spec range(extint(), extint()) -> proper_types:type(). +range(Low, High) -> integer(Low, High). + +%% @equiv float(inf, inf) +-spec float() -> proper_types:type(). +float() -> float(inf, inf). + +%% @equiv float(0.0, inf) +-spec non_neg_float() -> proper_types:type(). +non_neg_float() -> float(0.0, inf). + +%% @equiv union([integer(), float()]) +-spec number() -> proper_types:type(). +number() -> union([integer(), float()]). + +%% @doc The atoms `true' and `false'. Instances shrink towards `false'. +-spec boolean() -> proper_types:type(). +boolean() -> union(['false', 'true']). + +%% @equiv integer(0, 255) +-spec byte() -> proper_types:type(). +byte() -> integer(0, 255). + +%% @equiv integer(0, 16#10ffff) +-spec char() -> proper_types:type(). +char() -> integer(0, 16#10ffff). + +%% @equiv list(any()) +-spec list() -> proper_types:type(). +list() -> list(any()). + +%% @equiv loose_tuple(any()) +-spec tuple() -> proper_types:type(). +tuple() -> loose_tuple(any()). + +%% @equiv list(char()) +-spec string() -> proper_types:type(). +string() -> list(char()). + +%% @equiv weighted_union(FreqChoices) +-spec wunion([{frequency(),raw_type()},...]) -> proper_types:type(). +wunion(FreqChoices) -> weighted_union(FreqChoices). + +%% @equiv any() +-spec term() -> proper_types:type(). +term() -> any(). + +%% @equiv union([non_neg_integer() | infinity]) +-spec timeout() -> proper_types:type(). +timeout() -> union([non_neg_integer(), 'infinity']). + +%% @equiv integer(0, 255) +-spec arity() -> proper_types:type(). +arity() -> integer(0, 255). + + +%%------------------------------------------------------------------------------ +%% QuickCheck compatibility types +%%------------------------------------------------------------------------------ + +%% @doc Small integers (bound by the current value of the `size' parameter). +%% Instances shrink towards `0'. +-spec int() -> proper_types:type(). +int() -> ?SIZED(Size, integer(-Size,Size)). + +%% @doc Small non-negative integers (bound by the current value of the `size' +%% parameter). Instances shrink towards `0'. +-spec nat() -> proper_types:type(). +nat() -> ?SIZED(Size, integer(0,Size)). + +%% @equiv integer() +-spec largeint() -> proper_types:type(). +largeint() -> integer(). + +%% @equiv float() +-spec real() -> proper_types:type(). +real() -> float(). + +%% @equiv boolean() +-spec bool() -> proper_types:type(). +bool() -> boolean(). + +%% @equiv integer(Low, High) +-spec choose(extint(), extint()) -> proper_types:type(). +choose(Low, High) -> integer(Low, High). + +%% @equiv union(Choices) +-spec elements([raw_type(),...]) -> proper_types:type(). +elements(Choices) -> union(Choices). + +%% @equiv union(Choices) +-spec oneof([raw_type(),...]) -> proper_types:type(). +oneof(Choices) -> union(Choices). + +%% @equiv weighted_union(Choices) +-spec frequency([{frequency(),raw_type()},...]) -> proper_types:type(). +frequency(FreqChoices) -> weighted_union(FreqChoices). + +%% @equiv exactly(E) +-spec return(term()) -> proper_types:type(). +return(E) -> exactly(E). + +%% @doc Adds a default value, `Default', to `Type'. +%% The default serves as a primary shrinking target for instances, while it +%% is also chosen by the random instance generation subsystem half the time. +-spec default(raw_type(), raw_type()) -> proper_types:type(). +default(Default, Type) -> + union([Default, Type]). + +%% @doc All sorted lists containing elements of type `ElemType'. +%% Instances shrink towards the empty list, `[]'. +-spec orderedlist(ElemType::raw_type()) -> proper_types:type(). +orderedlist(RawElemType) -> + ?LET(L, list(RawElemType), lists:sort(L)). + +%% @equiv function(0, RetType) +-spec function0(raw_type()) -> proper_types:type(). +function0(RetType) -> + function(0, RetType). + +%% @equiv function(1, RetType) +-spec function1(raw_type()) -> proper_types:type(). +function1(RetType) -> + function(1, RetType). + +%% @equiv function(2, RetType) +-spec function2(raw_type()) -> proper_types:type(). +function2(RetType) -> + function(2, RetType). + +%% @equiv function(3, RetType) +-spec function3(raw_type()) -> proper_types:type(). +function3(RetType) -> + function(3, RetType). + +%% @equiv function(4, RetType) +-spec function4(raw_type()) -> proper_types:type(). +function4(RetType) -> + function(4, RetType). + +%% @doc A specialization of {@link default/2}, where `Default' and `Type' are +%% assigned weights to be considered by the random instance generator. The +%% shrinking subsystem will ignore the weights and try to shrink using the +%% default value. +-spec weighted_default({frequency(),raw_type()}, {frequency(),raw_type()}) -> + proper_types:type(). +weighted_default(Default, Type) -> + weighted_union([Default, Type]). + + +%%------------------------------------------------------------------------------ +%% Additional type specification functions +%%------------------------------------------------------------------------------ + +%% @doc Overrides the `size' parameter used when generating instances of +%% `Type' with `NewSize'. Has no effect on size-less types, such as unions. +%% Also, this will not affect the generation of any internal types contained in +%% `Type', such as the elements of a list - those will still be generated +%% using the test-wide value of `size'. One use of this function is to modify +%% types to produce instances that grow faster or slower, like so: +%% ```?SIZED(Size, resize(Size * 2, list(integer()))''' +%% The above specifies a list type that grows twice as fast as normal lists. +-spec resize(size(), Type::raw_type()) -> proper_types:type(). +resize(NewSize, RawType) -> + Type = cook_outer(RawType), + case find_prop(size_transform, Type) of + {ok,Transform} -> + add_prop(size_transform, fun(_S) -> Transform(NewSize) end, Type); + error -> + add_prop(size_transform, fun(_S) -> NewSize end, Type) + end. + +%% @doc This is a predefined constraint that can be applied to random-length +%% list and binary types to ensure that the produced values are never empty. +%% +%% e.g. {@link list/0}, {@link string/0}, {@link binary/0}) +-spec non_empty(ListType::raw_type()) -> proper_types:type(). +non_empty(RawListType) -> + ?SUCHTHAT(L, RawListType, L =/= [] andalso L =/= <<>>). + +%% @doc Creates a new type which is equivalent to `Type', but whose instances +%% are never shrunk by the shrinking subsystem. +-spec noshrink(Type::raw_type()) -> proper_types:type(). +noshrink(RawType) -> + add_prop(noshrink, true, cook_outer(RawType)). + +%% @doc Associates the atom key `Parameter' with the value `Value' while +%% generating instances of `Type'. +-spec with_parameter(atom(), value(), Type::raw_type()) -> proper_types:type(). +with_parameter(Parameter, Value, RawType) -> + with_parameters([{Parameter,Value}], RawType). + +%% @doc Similar to {@link with_parameter/3}, but accepts a list of +%% `{Parameter, Value}' pairs. +-spec with_parameters([{atom(),value()}], Type::raw_type()) -> + proper_types:type(). +with_parameters(PVlist, RawType) -> + Type = cook_outer(RawType), + case find_prop(parameters, Type) of + {ok,Params} when is_list(Params) -> + append_list_to_prop(parameters, PVlist, Type); + error -> + add_prop(parameters, PVlist, Type) + end. + +%% @doc Returns the value associated with `Parameter', or `Default' in case +%% `Parameter' is not associated with any value. +-spec parameter(atom(), value()) -> value(). +parameter(Parameter, Default) -> + Parameters = + case erlang:get('$parameters') of + undefined -> []; + List -> List + end, + proplists:get_value(Parameter, Parameters, Default). + +%% @equiv parameter(Parameter, undefined) +-spec parameter(atom()) -> value(). +parameter(Parameter) -> + parameter(Parameter, undefined). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl new file mode 100644 index 0000000000..b6cab5e24b --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl @@ -0,0 +1,2401 @@ +%%% Copyright 2010-2015 Manolis Papadakis , +%%% Eirini Arvaniti +%%% and Kostis Sagonas +%%% +%%% This file is part of PropEr. +%%% +%%% PropEr 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 3 of the License, or +%%% (at your option) any later version. +%%% +%%% PropEr 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 PropEr. If not, see . + +%%% @copyright 2010-2015 Manolis Papadakis, Eirini Arvaniti and Kostis Sagonas +%%% @version {@version} +%%% @author Manolis Papadakis + +%%% @doc Erlang type system - PropEr type system integration module. +%%% +%%% PropEr can parse types expressed in Erlang's type language and convert them +%%% to its own type format. Such expressions can be used instead of regular type +%%% constructors in the second argument of `?FORALL's. No extra notation is +%%% required; PropEr will detect which calls correspond to native types by +%%% applying a parse transform during compilation. This parse transform is +%%% automatically applied to any module that includes the `proper.hrl' header +%%% file. You can disable this feature by compiling your modules with +%%% `-DPROPER_NO_TRANS'. Note that this will currently also disable the +%%% automatic exporting of properties. +%%% +%%% The use of native types in properties is subject to the following usage +%%% rules: +%%%
    +%%%
  • Native types cannot be used outside of `?FORALL's.
  • +%%%
  • Inside `?FORALL's, native types can be combined with other native +%%% types, and even with PropEr types, inside tuples and lists (the constructs +%%% `[...]', `{...}' and `++' are all allowed).
  • +%%%
  • All other constructs of Erlang's built-in type system (e.g. `|' for +%%% union, `_' as an alias of `any()', `<<_:_>>' binary type syntax and +%%% `fun((...) -> ...)' function type syntax) are not allowed in `?FORALL's, +%%% because they are rejected by the Erlang parser.
  • +%%%
  • Anything other than a tuple constructor, list constructor, `++' +%%% application, local or remote call will automatically be considered a +%%% PropEr type constructor and not be processed further by the parse +%%% transform.
  • +%%%
  • Parametric native types are fully supported; of course, they can only +%%% appear instantiated in a `?FORALL'. The arguments of parametric native +%%% types are always interpreted as native types.
  • +%%%
  • Parametric PropEr types, on the other hand, can take any kind of +%%% argument. You can even mix native and PropEr types in the arguments of a +%%% PropEr type. For example, assuming that the following declarations are +%%% present: +%%% ``` my_proper_type() -> ?LET(...). +%%% -type my_native_type() :: ... .''' +%%% Then the following expressions are all legal: +%%% ``` vector(2, my_native_type()) +%%% function(0, my_native_type()) +%%% union([my_proper_type(), my_native_type()])'''
  • +%%%
  • Some type constructors can take native types as arguments (but only +%%% inside `?FORALL's): +%%%
      +%%%
    • `?SUCHTHAT', `?SUCHTHATMAYBE', `non_empty', `noshrink': these work +%%% with native types too
    • +%%%
    • `?LAZY', `?SHRINK', `resize', `?SIZED': these don't work with native +%%% types
    • +%%%
    • `?LET', `?LETSHRINK': only the top-level base type can be a native +%%% type
    • +%%%
  • +%%%
  • Native type declarations in the `?FORALL's of a module can reference any +%%% custom type declared in a `-type' or `-opaque' attribute of the same +%%% module, as long as no module identifier is used.
  • +%%%
  • Typed records cannot be referenced inside `?FORALL's using the +%%% `#rec_name{}' syntax. To use a typed record in a `?FORALL', enclose the +%%% record in a custom type like so: +%%% ``` -type rec_name() :: #rec_name{}. ''' +%%% and use the custom type instead.
  • +%%%
  • `?FORALL's may contain references to self-recursive or mutually +%%% recursive native types, so long as each type in the hierarchy has a clear +%%% base case. +%%% Currently, PropEr requires that the toplevel of any recursive type +%%% declaration is either a (maybe empty) list or a union containing at least +%%% one choice that doesn't reference the type directly (it may, however, +%%% reference any of the types that are mutually recursive with it). This +%%% means, for example, that some valid recursive type declarations, such as +%%% this one: +%%% ``` ?FORALL(..., a(), ...) ''' +%%% where: +%%% ``` -type a() :: {'a','none' | a()}. ''' +%%% are not accepted by PropEr. However, such types can be rewritten in a way +%%% that allows PropEr to parse them: +%%% ``` ?FORALL(..., a(), ...) ''' +%%% where: +%%% ``` -type a() :: {'a','none'} | {'a',a()}. ''' +%%% This also means that recursive record declarations are not allowed: +%%% ``` ?FORALL(..., rec(), ...) ''' +%%% where: +%%% ``` -type rec() :: #rec{}. +%%% -record(rec, {a = 0 :: integer(), b = 'nil' :: 'nil' | #rec{}}). ''' +%%% A little rewritting can usually remedy this problem as well: +%%% ``` ?FORALL(..., rec(), ...) ''' +%%% where: +%%% ``` -type rec() :: #rec{b :: 'nil'} | #rec{b :: rec()}. +%%% -record(rec, {a = 0 :: integer(), b = 'nil' :: 'nil' | #rec{}}). ''' +%%%
  • +%%%
  • Remote types may be referenced in a `?FORALL', so long as they are +%%% exported from the remote module. Currently, PropEr requires that any +%%% remote modules whose types are directly referenced from within properties +%%% are present in the code path at compile time, either compiled with +%%% `debug_info' enabled or in source form. If PropEr cannot find a remote +%%% module at all, finds only a compiled object file with no debug +%%% information or fails to compile the source file, all calls to that module +%%% will automatically be considered calls to PropEr type constructors.
  • +%%%
  • For native types to be translated correctly, both the module that +%%% contains the `?FORALL' declaration as well as any module that contains +%%% the declaration of a type referenced (directly or indirectly) from inside +%%% a `?FORALL' must be present in the code path at runtime, either compiled +%%% with `debug_info' enabled or in source form.
  • +%%%
  • Local types with the same name as an auto-imported BIF are not accepted +%%% by PropEr, unless the BIF in question has been declared in a +%%% `no_auto_import' option.
  • +%%%
  • When an expression can be interpreted both as a PropEr type and as a +%%% native type, the former takes precedence. This means that a function +%%% `foo()' will shadow a type `foo()' if they are both present in the module. +%%% The same rule applies to remote functions and types as well.
  • +%%%
  • The above may cause some confusion when list syntax is used: +%%%
      +%%%
    • The expression `[integer()]' can be interpreted both ways, so the +%%% PropEr way applies. Therefore, instances of this type will always be +%%% lists of length 1, not arbitrary integer lists, as would be expected +%%% when interpreting the expression as a native type.
    • +%%%
    • Assuming that a custom type foo/1 has been declared, the expression +%%% `foo([integer()])' can only be interpreted as a native type declaration, +%%% which means that the generic type of integer lists will be passed to +%%% `foo/1'.
    • +%%%
  • +%%%
  • Currently, PropEr does not detect the following mistakes: +%%%
      +%%%
    • inline record-field specializations that reference non-existent +%%% fields
    • +%%%
    • type parameters that are not present in the RHS of a `-type' +%%% declaration
    • +%%%
    • using `_' as a type variable in the LHS of a `-type' declaration
    • +%%%
    • using the same variable in more than one position in the LHS of a +%%% `-type' declaration
    • +%%%
    +%%%
  • +%%%
+%%% +%%% You can use these functions to try out the type +%%% translation subsystem. +%%% +%%% CAUTION: These functions should never be used inside properties. They are +%%% meant for demonstration purposes only. + +-module(proper_typeserver). +-behaviour(gen_server). +-export([demo_translate_type/2, demo_is_instance/3]). + +-export([start/0, restart/0, stop/0, create_spec_test/3, get_exp_specced/1, + is_instance/3, translate_type/1]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). +-export([get_exp_info/1, match/2]). + +-export_type([imm_type/0, mod_exp_types/0, mod_exp_funs/0]). + +-include("proper_internal.hrl"). + + +%%------------------------------------------------------------------------------ +%% Macros +%%------------------------------------------------------------------------------ + +-define(SRC_FILE_EXT, ".erl"). + +%% CAUTION: all these must be sorted +-define(STD_TYPES_0, + [any,arity,atom,binary,bitstring,bool,boolean,byte,char,float,integer, + list,neg_integer,non_neg_integer,number,pos_integer,string,term, + timeout]). +-define(HARD_ADTS, + %% gb_trees:iterator and gb_sets:iterator are NOT hardcoded + [{{array,0},array}, {{array,1},proper_array}, + {{dict,0},dict}, {{dict,2},proper_dict}, + {{gb_set,0},gb_sets}, {{gb_set,1},proper_gb_sets}, + {{gb_tree,0},gb_trees}, {{gb_tree,2},proper_gb_trees}, + {{orddict,2},proper_orddict}, + {{ordset,1},proper_ordsets}, + {{queue,0},queue}, {{queue,1},proper_queue}, + {{set,0},sets}, {{set,1},proper_sets}]). +-define(HARD_ADT_MODS, + [{array, [{{array,0}, + {{type,0,record,[{atom,0,array}]},[]}}]}, + {dict, [{{dict,0}, + {{type,0,record,[{atom,0,dict}]},[]}}]}, + {gb_sets, [{{gb_set,0}, + {{type,0,tuple,[{type,0,non_neg_integer,[]}, + {type,0,gb_set_node,[]}]},[]}}]}, + {gb_trees, [{{gb_tree,0}, + {{type,0,tuple,[{type,0,non_neg_integer,[]}, + {type,0,gb_tree_node,[]}]},[]}}]}, + %% Our parametric ADTs are already declared as normal types, we just + %% need to change them to opaques. + {proper_array, [{{array,1},already_declared}]}, + {proper_dict, [{{dict,2},already_declared}]}, + {proper_gb_sets, [{{gb_set,1},already_declared}, + {{iterator,1},already_declared}]}, + {proper_gb_trees, [{{gb_tree,2},already_declared}, + {{iterator,2},already_declared}]}, + {proper_orddict, [{{orddict,2},already_declared}]}, + {proper_ordsets, [{{ordset,1},already_declared}]}, + {proper_queue, [{{queue,1},already_declared}]}, + {proper_sets, [{{set,1},already_declared}]}, + {queue, [{{queue,0}, + {{type,0,tuple,[{type,0,list,[]},{type,0,list,[]}]},[]}}]}, + {sets, [{{set,0}, + {{type,0,record,[{atom,0,set}]},[]}}]}]). + + +%%------------------------------------------------------------------------------ +%% Types +%%------------------------------------------------------------------------------ + +-type type_name() :: atom(). +-type var_name() :: atom(). %% TODO: also integers? +-type field_name() :: atom(). + +-type type_kind() :: 'type' | 'record'. +-type type_ref() :: {type_kind(),type_name(),arity()}. +-ifdef(NO_MODULES_IN_OPAQUES). +-type substs_dict() :: dict(). %% dict(field_name(),ret_type()) +-else. +-type substs_dict() :: dict:dict(field_name(),ret_type()). +-endif. +-type full_type_ref() :: {mod_name(),type_kind(),type_name(), + [ret_type()] | substs_dict()}. +-type symb_info() :: 'not_symb' | {'orig_abs',abs_type()}. +-type type_repr() :: {'abs_type',abs_type(),[var_name()],symb_info()} + | {'cached',fin_type(),abs_type(),symb_info()} + | {'abs_record',[{field_name(),abs_type()}]}. +-type gen_fun() :: fun((size()) -> fin_type()). +-type rec_fun() :: fun(([gen_fun()],size()) -> fin_type()). +-type rec_arg() :: {boolean() | {'list',boolean(),rec_fun()},full_type_ref()}. +-type rec_args() :: [rec_arg()]. +-type ret_type() :: {'simple',fin_type()} | {'rec',rec_fun(),rec_args()}. +-type rec_fun_info() :: {pos_integer(),pos_integer(),[arity(),...], + [rec_fun(),...]}. + +-type imm_type_ref() :: {type_name(),arity()}. +-type hard_adt_repr() :: {abs_type(),[var_name()]} | 'already_declared'. +-type fun_ref() :: {fun_name(),arity()}. +-type fun_repr() :: fun_clause_repr(). +-type fun_clause_repr() :: {[abs_type()],abs_type()}. +-type proc_fun_ref() :: {fun_name(),[abs_type()],abs_type()}. +-type full_imm_type_ref() :: {mod_name(),type_name(),arity()}. +-type imm_stack() :: [full_imm_type_ref()]. +-type pat_field() :: 0 | 1 | atom(). +-type pattern() :: loose_tuple(pat_field()). +-type next_step() :: 'none' | 'take_head' | {'match_with',pattern()}. + +-ifdef(NO_MODULES_IN_OPAQUES). +%% @private_type +-type mod_exp_types() :: set(). %% set(imm_type_ref()) +-type mod_types() :: dict(). %% dict(type_ref(),type_repr()) +%% @private_type +-type mod_exp_funs() :: set(). %% set(fun_ref()) +-type mod_specs() :: dict(). %% dict(fun_ref(),fun_repr()) +-else. +%% @private_type +-type mod_exp_types() :: sets:set(imm_type_ref()). +-type mod_types() :: dict:dict(type_ref(),type_repr()). +%% @private_type +-type mod_exp_funs() :: sets:set(fun_ref()). +-type mod_specs() :: dict:dict(fun_ref(),fun_repr()). +-endif. + +-ifdef(NO_MODULES_IN_OPAQUES). +-record(state, + {cached = dict:new() :: dict(), %% dict(imm_type(),fin_type()) + exp_types = dict:new() :: dict(), %% dict(mod_name(),mod_exp_types()) + types = dict:new() :: dict(), %% dict(mod_name(),mod_types()) + exp_specs = dict:new() :: dict()}). %% dict(mod_name(),mod_specs()) +-else. +-record(state, + {cached = dict:new() :: dict:dict(), %% dict(imm_type(),fin_type()) + exp_types = dict:new() :: dict:dict(), %% dict(mod_name(),mod_exp_types()) + types = dict:new() :: dict:dict(), %% dict(mod_name(),mod_types()) + exp_specs = dict:new() :: dict:dict()}). %% dict(mod_name(),mod_specs()) +%% {cached = dict:new() :: dict:dict(imm_type(),fin_type()), +%% exp_types = dict:new() :: dict:dict(mod_name(),mod_exp_types()), +%% types = dict:new() :: dict:dict(mod_name(),mod_types()), +%% exp_specs = dict:new() :: dict:dict(mod_name(),mod_specs())}). +-endif. +-type state() :: #state{}. + +-record(mod_info, + {mod_exp_types = sets:new() :: mod_exp_types(), + mod_types = dict:new() :: mod_types(), + mod_opaques = sets:new() :: mod_exp_types(), + mod_exp_funs = sets:new() :: mod_exp_funs(), + mod_specs = dict:new() :: mod_specs()}). +-type mod_info() :: #mod_info{}. + +-type stack() :: [full_type_ref() | 'tuple' | 'list' | 'union' | 'fun']. +-ifdef(NO_MODULES_IN_OPAQUES). +-type var_dict() :: dict(). %% dict(var_name(),ret_type()) +-else. +-type var_dict() :: dict:dict(var_name(),ret_type()). +-endif. +%% @private_type +-type imm_type() :: {mod_name(),string()}. +%% @alias +-type fin_type() :: proper_types:type(). +-type tagged_result(T) :: {'ok',T} | 'error'. +-type tagged_result2(T,S) :: {'ok',T,S} | 'error'. +%% @alias +-type rich_result(T) :: {'ok',T} | {'error',term()}. +-type rich_result2(T,S) :: {'ok',T,S} | {'error',term()}. +-type false_positive_mfas() :: proper:false_positive_mfas(). + +-type server_call() :: {'create_spec_test',mfa(),timeout(),false_positive_mfas()} + | {'get_exp_specced',mod_name()} + | {'get_type_repr',mod_name(),type_ref(),boolean()} + | {'translate_type',imm_type()}. +-type server_response() :: rich_result(proper:test()) + | rich_result([mfa()]) + | rich_result(type_repr()) + | rich_result(fin_type()). + + +%%------------------------------------------------------------------------------ +%% Server interface functions +%%------------------------------------------------------------------------------ + +%% @private +-spec start() -> 'ok'. +start() -> + {ok,TypeserverPid} = gen_server:start_link(?MODULE, dummy, []), + put('$typeserver_pid', TypeserverPid), + ok. + +%% @private +-spec restart() -> 'ok'. +restart() -> + TypeserverPid = get('$typeserver_pid'), + case (TypeserverPid =:= undefined orelse not is_process_alive(TypeserverPid)) of + true -> start(); + false -> ok + end. + +%% @private +-spec stop() -> 'ok'. +stop() -> + TypeserverPid = get('$typeserver_pid'), + erase('$typeserver_pid'), + gen_server:cast(TypeserverPid, stop). + +%% @private +-spec create_spec_test(mfa(), timeout(), false_positive_mfas()) -> rich_result(proper:test()). +create_spec_test(MFA, SpecTimeout, FalsePositiveMFAs) -> + TypeserverPid = get('$typeserver_pid'), + gen_server:call(TypeserverPid, {create_spec_test,MFA,SpecTimeout,FalsePositiveMFAs}). + +%% @private +-spec get_exp_specced(mod_name()) -> rich_result([mfa()]). +get_exp_specced(Mod) -> + TypeserverPid = get('$typeserver_pid'), + gen_server:call(TypeserverPid, {get_exp_specced,Mod}). + +-spec get_type_repr(mod_name(), type_ref(), boolean()) -> + rich_result(type_repr()). +get_type_repr(Mod, TypeRef, IsRemote) -> + TypeserverPid = get('$typeserver_pid'), + gen_server:call(TypeserverPid, {get_type_repr,Mod,TypeRef,IsRemote}). + +%% @private +-spec translate_type(imm_type()) -> rich_result(fin_type()). +translate_type(ImmType) -> + TypeserverPid = get('$typeserver_pid'), + gen_server:call(TypeserverPid, {translate_type,ImmType}). + +%% @doc Translates the native type expression `TypeExpr' (which should be +%% provided inside a string) into a PropEr type, which can then be passed to any +%% of the demo functions defined in the {@link proper_gen} module. PropEr acts +%% as if it found this type expression inside the code of module `Mod'. +-spec demo_translate_type(mod_name(), string()) -> rich_result(fin_type()). +demo_translate_type(Mod, TypeExpr) -> + start(), + Result = translate_type({Mod,TypeExpr}), + stop(), + Result. + +%% @doc Checks if `Term' is a valid instance of native type `TypeExpr' (which +%% should be provided inside a string). PropEr acts as if it found this type +%% expression inside the code of module `Mod'. +-spec demo_is_instance(term(), mod_name(), string()) -> + boolean() | {'error',term()}. +demo_is_instance(Term, Mod, TypeExpr) -> + case parse_type(TypeExpr) of + {ok,TypeForm} -> + start(), + Result = + %% Force the typeserver to load the module. + case translate_type({Mod,"integer()"}) of + {ok,_FinType} -> + try is_instance(Term, Mod, TypeForm) + catch + throw:{'$typeserver',Reason} -> {error, Reason} + end; + {error,_Reason} = Error -> + Error + end, + stop(), + Result; + {error,_Reason} = Error -> + Error + end. + + +%%------------------------------------------------------------------------------ +%% Implementation of gen_server interface +%%------------------------------------------------------------------------------ + +%% @private +-spec init(_) -> {'ok',state()}. +init(_) -> + {ok, #state{}}. + +%% @private +-spec handle_call(server_call(), _, state()) -> + {'reply',server_response(),state()}. +handle_call({create_spec_test,MFA,SpecTimeout,FalsePositiveMFAs}, _From, State) -> + case create_spec_test(MFA, SpecTimeout, FalsePositiveMFAs, State) of + {ok,Test,NewState} -> + {reply, {ok,Test}, NewState}; + {error,_Reason} = Error -> + {reply, Error, State} + end; +handle_call({get_exp_specced,Mod}, _From, State) -> + case get_exp_specced(Mod, State) of + {ok,MFAs,NewState} -> + {reply, {ok,MFAs}, NewState}; + {error,_Reason} = Error -> + {reply, Error, State} + end; +handle_call({get_type_repr,Mod,TypeRef,IsRemote}, _From, State) -> + case get_type_repr(Mod, TypeRef, IsRemote, State) of + {ok,TypeRepr,NewState} -> + {reply, {ok,TypeRepr}, NewState}; + {error,_Reason} = Error -> + {reply, Error, State} + end; +handle_call({translate_type,ImmType}, _From, State) -> + case translate_type(ImmType, State) of + {ok,FinType,NewState} -> + {reply, {ok,FinType}, NewState}; + {error,_Reason} = Error -> + {reply, Error, State} + end. + +%% @private +-spec handle_cast('stop', state()) -> {'stop','normal',state()}. +handle_cast(stop, State) -> + {stop, normal, State}. + +%% @private +-spec handle_info(term(), state()) -> {'stop',{'received_info',term()},state()}. +handle_info(Info, State) -> + {stop, {received_info,Info}, State}. + +%% @private +-spec terminate(term(), state()) -> 'ok'. +terminate(_Reason, _State) -> + ok. + +%% @private +-spec code_change(term(), state(), _) -> {'ok',state()}. +code_change(_OldVsn, State, _) -> + {ok, State}. + + +%%------------------------------------------------------------------------------ +%% Top-level interface +%%------------------------------------------------------------------------------ + +-spec create_spec_test(mfa(), timeout(), false_positive_mfas(), state()) -> + rich_result2(proper:test(),state()). +create_spec_test(MFA, SpecTimeout, FalsePositiveMFAs, State) -> + case get_exp_spec(MFA, State) of + {ok,FunRepr,NewState} -> + make_spec_test(MFA, FunRepr, SpecTimeout, FalsePositiveMFAs, NewState); + {error,_Reason} = Error -> + Error + end. + +-spec get_exp_spec(mfa(), state()) -> rich_result2(fun_repr(),state()). +get_exp_spec({Mod,Fun,Arity} = MFA, State) -> + case add_module(Mod, State) of + {ok,#state{exp_specs = ExpSpecs} = NewState} -> + ModExpSpecs = dict:fetch(Mod, ExpSpecs), + case dict:find({Fun,Arity}, ModExpSpecs) of + {ok,FunRepr} -> + {ok, FunRepr, NewState}; + error -> + {error, {function_not_exported_or_specced,MFA}} + end; + {error,_Reason} = Error -> + Error + end. + +-spec make_spec_test(mfa(), fun_repr(), timeout(), false_positive_mfas(), state()) -> + rich_result2(proper:test(),state()). +make_spec_test({Mod,_Fun,_Arity}=MFA, {Domain,_Range}=FunRepr, SpecTimeout, FalsePositiveMFAs, State) -> + case convert(Mod, {type,0,'$fixed_list',Domain}, State) of + {ok,FinType,NewState} -> + Test = ?FORALL(Args, FinType, apply_spec_test(MFA, FunRepr, SpecTimeout, FalsePositiveMFAs, Args)), + {ok, Test, NewState}; + {error,_Reason} = Error -> + Error + end. + +-spec apply_spec_test(mfa(), fun_repr(), timeout(), false_positive_mfas(), term()) -> proper:test(). +apply_spec_test({Mod,Fun,_Arity}=MFA, {_Domain,Range}, SpecTimeout, FalsePositiveMFAs, Args) -> + ?TIMEOUT(SpecTimeout, + begin + %% NOTE: only call apply/3 inside try/catch (do not trust ?MODULE:is_instance/3) + Result = + try apply(Mod,Fun,Args) of + X -> {ok, X} + catch + X:Y -> {X, Y} + end, + case Result of + {ok, Z} -> + case ?MODULE:is_instance(Z,Mod,Range) of + true -> + true; + false when is_function(FalsePositiveMFAs) -> + FalsePositiveMFAs(MFA, Args, {fail, Z}); + false -> + false + end; + Exception when is_function(FalsePositiveMFAs) -> + case FalsePositiveMFAs(MFA, Args, Exception) of + true -> + true; + false -> + error(Exception, erlang:get_stacktrace()) + end; + Exception -> + error(Exception, erlang:get_stacktrace()) + end + end). + +-spec get_exp_specced(mod_name(), state()) -> rich_result2([mfa()],state()). +get_exp_specced(Mod, State) -> + case add_module(Mod, State) of + {ok,#state{exp_specs = ExpSpecs} = NewState} -> + ModExpSpecs = dict:fetch(Mod, ExpSpecs), + ExpSpecced = [{Mod,F,A} || {F,A} <- dict:fetch_keys(ModExpSpecs)], + {ok, ExpSpecced, NewState}; + {error,_Reason} = Error -> + Error + end. + +-spec get_type_repr(mod_name(), type_ref(), boolean(), state()) -> + rich_result2(type_repr(),state()). +get_type_repr(Mod, {type,Name,Arity} = TypeRef, true, State) -> + case prepare_for_remote(Mod, Name, Arity, State) of + {ok,NewState} -> + get_type_repr(Mod, TypeRef, false, NewState); + {error,_Reason} = Error -> + Error + end; +get_type_repr(Mod, TypeRef, false, #state{types = Types} = State) -> + ModTypes = dict:fetch(Mod, Types), + case dict:find(TypeRef, ModTypes) of + {ok,TypeRepr} -> + {ok, TypeRepr, State}; + error -> + {error, {missing_type,Mod,TypeRef}} + end. + +-spec prepare_for_remote(mod_name(), type_name(), arity(), state()) -> + rich_result(state()). +prepare_for_remote(RemMod, Name, Arity, State) -> + case add_module(RemMod, State) of + {ok,#state{exp_types = ExpTypes} = NewState} -> + RemModExpTypes = dict:fetch(RemMod, ExpTypes), + case sets:is_element({Name,Arity}, RemModExpTypes) of + true -> {ok, NewState}; + false -> {error, {type_not_exported,{RemMod,Name,Arity}}} + end; + {error,_Reason} = Error -> + Error + end. + +-spec translate_type(imm_type(), state()) -> rich_result2(fin_type(),state()). +translate_type({Mod,Str} = ImmType, #state{cached = Cached} = State) -> + case dict:find(ImmType, Cached) of + {ok,Type} -> + {ok, Type, State}; + error -> + case parse_type(Str) of + {ok,TypeForm} -> + case add_module(Mod, State) of + {ok,NewState} -> + case convert(Mod, TypeForm, NewState) of + {ok,FinType, + #state{cached = Cached} = FinalState} -> + NewCached = dict:store(ImmType, FinType, + Cached), + {ok, FinType, + FinalState#state{cached = NewCached}}; + {error,_Reason} = Error -> + Error + end; + {error,_Reason} = Error -> + Error + end; + {error,Reason} -> + {error, {parse_error,Str,Reason}} + end + end. + +-spec parse_type(string()) -> rich_result(abs_type()). +parse_type(Str) -> + TypeStr = "-type mytype() :: " ++ Str ++ ".", + case erl_scan:string(TypeStr) of + {ok,Tokens,_EndLocation} -> + case erl_parse:parse_form(Tokens) of + {ok,{attribute,_Line,type,{mytype,TypeExpr,[]}}} -> + {ok, TypeExpr}; + {error,_ErrorInfo} = Error -> + Error + end; + {error,ErrorInfo,_EndLocation} -> + {error, ErrorInfo} + end. + +-spec add_module(mod_name(), state()) -> rich_result(state()). +add_module(Mod, #state{exp_types = ExpTypes} = State) -> + case dict:is_key(Mod, ExpTypes) of + true -> + {ok, State}; + false -> + case get_code_and_exports(Mod) of + {ok,AbsCode,ModExpFuns} -> + RawModInfo = get_mod_info(Mod, AbsCode, ModExpFuns), + ModInfo = process_adts(Mod, RawModInfo), + {ok, store_mod_info(Mod,ModInfo,State)}; + {error,Reason} -> + {error, {cant_load_code,Mod,Reason}} + end + end. + +%% @private +-spec get_exp_info(mod_name()) -> rich_result2(mod_exp_types(),mod_exp_funs()). +get_exp_info(Mod) -> + case get_code_and_exports(Mod) of + {ok,AbsCode,ModExpFuns} -> + RawModInfo = get_mod_info(Mod, AbsCode, ModExpFuns), + {ok, RawModInfo#mod_info.mod_exp_types, ModExpFuns}; + {error,_Reason} = Error -> + Error + end. + +-spec get_code_and_exports(mod_name()) -> + rich_result2([abs_form()],mod_exp_funs()). +get_code_and_exports(Mod) -> + case code:get_object_code(Mod) of + {Mod, ObjBin, _ObjFileName} -> + case get_chunks(ObjBin) of + {ok,_AbsCode,_ModExpFuns} = Result -> + Result; + {error,Reason} -> + get_code_and_exports_from_source(Mod, Reason) + end; + error -> + get_code_and_exports_from_source(Mod, cant_find_object_file) + end. + +-spec get_code_and_exports_from_source(mod_name(), term()) -> + rich_result2([abs_form()],mod_exp_funs()). +get_code_and_exports_from_source(Mod, ObjError) -> + SrcFileName = atom_to_list(Mod) ++ ?SRC_FILE_EXT, + case code:where_is_file(SrcFileName) of + FullSrcFileName when is_list(FullSrcFileName) -> + Opts = [binary,debug_info,return_errors,{d,'PROPER_REMOVE_PROPS'}], + case compile:file(FullSrcFileName, Opts) of + {ok,Mod,Binary} -> + get_chunks(Binary); + {error,Errors,_Warnings} -> + {error, {ObjError,{cant_compile_source_file,Errors}}} + end; + non_existing -> + {error, {ObjError,cant_find_source_file}} + end. + +-spec get_chunks(string() | binary()) -> + rich_result2([abs_form()],mod_exp_funs()). +get_chunks(ObjFile) -> + case beam_lib:chunks(ObjFile, [abstract_code,exports]) of + {ok,{_Mod,[{abstract_code,AbsCodeChunk},{exports,ExpFunsList}]}} -> + case AbsCodeChunk of + {raw_abstract_v1,AbsCode} -> + %% HACK: Add a declaration for iolist() to every module + {ok, add_iolist(AbsCode), sets:from_list(ExpFunsList)}; + no_abstract_code -> + {error, no_abstract_code}; + _ -> + {error, unsupported_abstract_code_format} + end; + {error,beam_lib,Reason} -> + {error, Reason} + end. + +-spec add_iolist([abs_form()]) -> [abs_form()]. +add_iolist(Forms) -> + IOListDef = + {type,0,maybe_improper_list, + [{type,0,union,[{type,0,byte,[]},{type,0,binary,[]}, + {type,0,iolist,[]}]}, + {type,0,binary,[]}]}, + IOListDecl = {attribute,0,type,{iolist,IOListDef,[]}}, + [IOListDecl | Forms]. + +-spec get_mod_info(mod_name(), [abs_form()], mod_exp_funs()) -> mod_info(). +get_mod_info(Mod, AbsCode, ModExpFuns) -> + StartModInfo = #mod_info{mod_exp_funs = ModExpFuns}, + ImmModInfo = lists:foldl(fun add_mod_info/2, StartModInfo, AbsCode), + #mod_info{mod_specs = AllModSpecs} = ImmModInfo, + IsExported = fun(FunRef,_FunRepr) -> sets:is_element(FunRef,ModExpFuns) end, + ModExpSpecs = dict:filter(IsExported, AllModSpecs), + ModInfo = ImmModInfo#mod_info{mod_specs = ModExpSpecs}, + case orddict:find(Mod, ?HARD_ADT_MODS) of + {ok,ModADTs} -> + #mod_info{mod_exp_types = ModExpTypes, mod_types = ModTypes, + mod_opaques = ModOpaques} = ModInfo, + ModADTsSet = + sets:from_list([ImmTypeRef + || {ImmTypeRef,_HardADTRepr} <- ModADTs]), + NewModExpTypes = sets:union(ModExpTypes, ModADTsSet), + NewModTypes = lists:foldl(fun store_hard_adt/2, ModTypes, ModADTs), + NewModOpaques = sets:union(ModOpaques, ModADTsSet), + ModInfo#mod_info{mod_exp_types = NewModExpTypes, + mod_types = NewModTypes, + mod_opaques = NewModOpaques}; + error -> + ModInfo + end. + +-spec store_hard_adt({imm_type_ref(),hard_adt_repr()}, mod_types()) -> + mod_types(). +store_hard_adt({_ImmTypeRef,already_declared}, ModTypes) -> + ModTypes; +store_hard_adt({{Name,Arity},{TypeForm,VarNames}}, ModTypes) -> + TypeRef = {type,Name,Arity}, + TypeRepr = {abs_type,TypeForm,VarNames,not_symb}, + dict:store(TypeRef, TypeRepr, ModTypes). + +-spec add_mod_info(abs_form(), mod_info()) -> mod_info(). +add_mod_info({attribute,_Line,export_type,TypesList}, + #mod_info{mod_exp_types = ModExpTypes} = ModInfo) -> + NewModExpTypes = sets:union(sets:from_list(TypesList), ModExpTypes), + ModInfo#mod_info{mod_exp_types = NewModExpTypes}; +add_mod_info({attribute,_Line,type,{{record,RecName},Fields,[]}}, + #mod_info{mod_types = ModTypes} = ModInfo) -> + FieldInfo = [process_rec_field(F) || F <- Fields], + NewModTypes = dict:store({record,RecName,0}, {abs_record,FieldInfo}, + ModTypes), + ModInfo#mod_info{mod_types = NewModTypes}; +add_mod_info({attribute,_Line,record,{RecName,Fields}}, + #mod_info{mod_types = ModTypes} = ModInfo) -> + case dict:is_key(RecName, ModTypes) of + true -> + ModInfo; + false -> + TypedRecord = {attribute,0,type,{{record,RecName},Fields,[]}}, + add_mod_info(TypedRecord, ModInfo) + end; +add_mod_info({attribute,_Line,Kind,{Name,TypeForm,VarForms}}, + #mod_info{mod_types = ModTypes, + mod_opaques = ModOpaques} = ModInfo) + when Kind =:= type; Kind =:= opaque -> + Arity = length(VarForms), + VarNames = [V || {var,_,V} <- VarForms], + %% TODO: No check whether variables are different, or non-'_'. + NewModTypes = dict:store({type,Name,Arity}, + {abs_type,TypeForm,VarNames,not_symb}, ModTypes), + NewModOpaques = + case Kind of + type -> ModOpaques; + opaque -> sets:add_element({Name,Arity}, ModOpaques) + end, + ModInfo#mod_info{mod_types = NewModTypes, mod_opaques = NewModOpaques}; +add_mod_info({attribute,_Line,spec,{RawFunRef,[RawFirstClause | _Rest]}}, + #mod_info{mod_specs = ModSpecs} = ModInfo) -> + FunRef = case RawFunRef of + {_Mod,Name,Arity} -> {Name,Arity}; + {_Name,_Arity} = F -> F + end, + %% TODO: We just take the first function clause. + FirstClause = process_fun_clause(RawFirstClause), + NewModSpecs = dict:store(FunRef, FirstClause, ModSpecs), + ModInfo#mod_info{mod_specs = NewModSpecs}; +add_mod_info(_Form, ModInfo) -> + ModInfo. + +-spec process_rec_field(abs_rec_field()) -> {field_name(),abs_type()}. +process_rec_field({record_field,_,{atom,_,FieldName}}) -> + {FieldName, {type,0,any,[]}}; +process_rec_field({record_field,_,{atom,_,FieldName},_Initialization}) -> + {FieldName, {type,0,any,[]}}; +process_rec_field({typed_record_field,RecField,FieldType}) -> + {FieldName,_} = process_rec_field(RecField), + {FieldName, FieldType}. + +-spec process_fun_clause(abs_type()) -> fun_clause_repr(). +process_fun_clause({type,_,'fun',[{type,_,product,Domain},Range]}) -> + {Domain, Range}; +process_fun_clause({type,_,bounded_fun,[MainClause,Constraints]}) -> + {RawDomain,RawRange} = process_fun_clause(MainClause), + VarSubsts = [{V,T} || {type,_,constraint, + [{atom,_,is_subtype},[{var,_,V},T]]} <- Constraints, + V =/= '_'], + VarSubstsDict = dict:from_list(VarSubsts), + Domain = [update_vars(A, VarSubstsDict, false) || A <- RawDomain], + Range = update_vars(RawRange, VarSubstsDict, false), + {Domain, Range}. + +-spec store_mod_info(mod_name(), mod_info(), state()) -> state(). +store_mod_info(Mod, #mod_info{mod_exp_types = ModExpTypes, mod_types = ModTypes, + mod_specs = ImmModExpSpecs}, + #state{exp_types = ExpTypes, types = Types, + exp_specs = ExpSpecs} = State) -> + NewExpTypes = dict:store(Mod, ModExpTypes, ExpTypes), + NewTypes = dict:store(Mod, ModTypes, Types), + ModExpSpecs = dict:map(fun unbound_to_any/2, ImmModExpSpecs), + NewExpSpecs = dict:store(Mod, ModExpSpecs, ExpSpecs), + State#state{exp_types = NewExpTypes, types = NewTypes, + exp_specs = NewExpSpecs}. + +-spec unbound_to_any(fun_ref(), fun_repr()) -> fun_repr(). +unbound_to_any(_FunRef, {Domain,Range}) -> + EmptySubstsDict = dict:new(), + NewDomain = [update_vars(A,EmptySubstsDict,true) || A <- Domain], + NewRange = update_vars(Range, EmptySubstsDict, true), + {NewDomain, NewRange}. + + +%%------------------------------------------------------------------------------ +%% ADT translation functions +%%------------------------------------------------------------------------------ + +-spec process_adts(mod_name(), mod_info()) -> mod_info(). +process_adts(Mod, + #mod_info{mod_exp_types = ModExpTypes, mod_opaques = ModOpaques, + mod_specs = ModExpSpecs} = ModInfo) -> + %% TODO: No warning on unexported opaques. + case sets:to_list(sets:intersection(ModExpTypes,ModOpaques)) of + [] -> + ModInfo; + ModADTs -> + %% TODO: No warning on unexported API functions. + ModExpSpecsList = [{Name,Domain,Range} + || {{Name,_Arity},{Domain,Range}} + <- dict:to_list(ModExpSpecs)], + AddADT = fun(ADT,Acc) -> add_adt(Mod,ADT,Acc,ModExpSpecsList) end, + lists:foldl(AddADT, ModInfo, ModADTs) + end. + +-spec add_adt(mod_name(), imm_type_ref(), mod_info(), [proc_fun_ref()]) -> + mod_info(). +add_adt(Mod, {Name,Arity}, #mod_info{mod_types = ModTypes} = ModInfo, + ModExpFunSpecs) -> + ADTRef = {type,Name,Arity}, + {abs_type,InternalRepr,VarNames,not_symb} = dict:fetch(ADTRef, ModTypes), + FullADTRef = {Mod,Name,Arity}, + %% TODO: No warning on unsuitable range. + SymbCalls1 = [get_symb_call(FullADTRef,Spec) || Spec <- ModExpFunSpecs], + %% TODO: No warning on bad use of variables. + SymbCalls2 = [fix_vars(FullADTRef,Call,RangeVars,VarNames) + || {ok,Call,RangeVars} <- SymbCalls1], + case [Call || {ok,Call} <- SymbCalls2] of + [] -> + %% TODO: No warning on no acceptable spec. + ModInfo; + SymbCalls3 -> + NewADTRepr = {abs_type,{type,0,union,SymbCalls3},VarNames, + {orig_abs,InternalRepr}}, + NewModTypes = dict:store(ADTRef, NewADTRepr, ModTypes), + ModInfo#mod_info{mod_types = NewModTypes} + end. + +-spec get_symb_call(full_imm_type_ref(), proc_fun_ref()) -> + tagged_result2(abs_type(),[var_name()]). +get_symb_call({Mod,_TypeName,_Arity} = FullADTRef, {FunName,Domain,Range}) -> + BaseCall = {type,0,tuple,[{atom,0,'$call'},{atom,0,Mod},{atom,0,FunName}, + {type,0,'$fixed_list',Domain}]}, + unwrap_range(FullADTRef, BaseCall, Range, false). + +-spec unwrap_range(full_imm_type_ref(), abs_type() | next_step(), abs_type(), + boolean()) -> + tagged_result2(abs_type() | next_step(),[var_name()]). +unwrap_range(FullADTRef, Call, {paren_type,_,[Type]}, TestRun) -> + unwrap_range(FullADTRef, Call, Type, TestRun); +unwrap_range(FullADTRef, Call, {ann_type,_,[_Var,Type]}, TestRun) -> + unwrap_range(FullADTRef, Call, Type, TestRun); +unwrap_range(FullADTRef, Call, {type,_,list,[ElemType]}, TestRun) -> + unwrap_list(FullADTRef, Call, ElemType, TestRun); +unwrap_range(FullADTRef, Call, {type,_,maybe_improper_list,[Cont,_Term]}, + TestRun) -> + unwrap_list(FullADTRef, Call, Cont, TestRun); +unwrap_range(FullADTRef, Call, {type,_,nonempty_list,[ElemType]}, TestRun) -> + unwrap_list(FullADTRef, Call, ElemType, TestRun); +unwrap_range(FullADTRef, Call, {type,_,nonempty_improper_list,[Cont,_Term]}, + TestRun) -> + unwrap_list(FullADTRef, Call, Cont, TestRun); +unwrap_range(FullADTRef, Call, + {type,_,nonempty_maybe_improper_list,[Cont,_Term]}, TestRun) -> + unwrap_list(FullADTRef, Call, Cont, TestRun); +unwrap_range(_FullADTRef, _Call, {type,_,tuple,any}, _TestRun) -> + error; +unwrap_range(FullADTRef, Call, {type,_,tuple,FieldForms}, TestRun) -> + Translates = fun(T) -> unwrap_range(FullADTRef,none,T,true) =/= error end, + case proper_arith:find_first(Translates, FieldForms) of + none -> + error; + {TargetPos,TargetElem} -> + Pattern = get_pattern(TargetPos, FieldForms), + case TestRun of + true -> + NewCall = + case Call of + none -> {match_with,Pattern}; + _ -> Call + end, + {ok, NewCall, []}; + false -> + AbsPattern = term_to_singleton_type(Pattern), + NewCall = + {type,0,tuple, + [{atom,0,'$call'},{atom,0,?MODULE},{atom,0,match}, + {type,0,'$fixed_list',[AbsPattern,Call]}]}, + unwrap_range(FullADTRef, NewCall, TargetElem, TestRun) + end + end; +unwrap_range(FullADTRef, Call, {type,_,union,Choices}, TestRun) -> + TestedChoices = [unwrap_range(FullADTRef,none,C,true) || C <- Choices], + NotError = fun(error) -> false; (_) -> true end, + case proper_arith:find_first(NotError, TestedChoices) of + none -> + error; + {_ChoicePos,{ok,none,_RangeVars}} -> + error; + {ChoicePos,{ok,NextStep,_RangeVars}} -> + {A, [ChoiceElem|B]} = lists:split(ChoicePos-1, Choices), + OtherChoices = A ++ B, + DistinctChoice = + case NextStep of + take_head -> + fun cant_have_head/1; + {match_with,Pattern} -> + fun(C) -> cant_match(Pattern, C) end + end, + case {lists:all(DistinctChoice,OtherChoices), TestRun} of + {true,true} -> + {ok, NextStep, []}; + {true,false} -> + unwrap_range(FullADTRef, Call, ChoiceElem, TestRun); + {false,_} -> + error + end + end; +unwrap_range({_Mod,SameName,Arity}, Call, {type,_,SameName,ArgForms}, + _TestRun) -> + RangeVars = [V || {var,_,V} <- ArgForms, V =/= '_'], + case length(ArgForms) =:= Arity andalso length(RangeVars) =:= Arity of + true -> {ok, Call, RangeVars}; + false -> error + end; +unwrap_range({SameMod,SameName,_Arity} = FullADTRef, Call, + {remote_type,_,[{atom,_,SameMod},{atom,_,SameName},ArgForms]}, + TestRun) -> + unwrap_range(FullADTRef, Call, {type,0,SameName,ArgForms}, TestRun); +unwrap_range(_FullADTRef, _Call, _Range, _TestRun) -> + error. + +-spec unwrap_list(full_imm_type_ref(), abs_type() | next_step(), abs_type(), + boolean()) -> + tagged_result2(abs_type() | next_step(),[var_name()]). +unwrap_list(FullADTRef, Call, HeadType, TestRun) -> + NewCall = + case TestRun of + true -> + case Call of + none -> take_head; + _ -> Call + end; + false -> + {type,0,tuple,[{atom,0,'$call'},{atom,0,erlang},{atom,0,hd}, + {type,0,'$fixed_list',[Call]}]} + end, + unwrap_range(FullADTRef, NewCall, HeadType, TestRun). + +-spec fix_vars(full_imm_type_ref(), abs_type(), [var_name()], [var_name()]) -> + tagged_result(abs_type()). +fix_vars(FullADTRef, Call, RangeVars, VarNames) -> + NotAnyVar = fun(V) -> V =/= '_' end, + case no_duplicates(VarNames) andalso lists:all(NotAnyVar,VarNames) of + true -> + RawUsedVars = + collect_vars(FullADTRef, Call, [[V] || V <- RangeVars]), + UsedVars = [lists:usort(L) || L <- RawUsedVars], + case correct_var_use(UsedVars) of + true -> + PairAll = fun(L,Y) -> [{X,{var,0,Y}} || X <- L] end, + VarSubsts = + lists:flatten(lists:zipwith(PairAll,UsedVars,VarNames)), + VarSubstsDict = dict:from_list(VarSubsts), + {ok, update_vars(Call,VarSubstsDict,true)}; + false -> + error + end; + false -> + error + end. + +-spec no_duplicates(list()) -> boolean(). +no_duplicates(L) -> + length(lists:usort(L)) =:= length(L). + +-spec correct_var_use([[var_name() | 0]]) -> boolean(). +correct_var_use(UsedVars) -> + NoNonVarArgs = fun([0|_]) -> false; (_) -> true end, + lists:all(NoNonVarArgs, UsedVars) + andalso no_duplicates(lists:flatten(UsedVars)). + +-spec collect_vars(full_imm_type_ref(), abs_type(), [[var_name() | 0]]) -> + [[var_name() | 0]]. +collect_vars(FullADTRef, {paren_type,_,[Type]}, UsedVars) -> + collect_vars(FullADTRef, Type, UsedVars); +collect_vars(FullADTRef, {ann_type,_,[_Var,Type]}, UsedVars) -> + collect_vars(FullADTRef, Type, UsedVars); +collect_vars(_FullADTRef, {type,_,tuple,any}, UsedVars) -> + UsedVars; +collect_vars({_Mod,SameName,Arity} = FullADTRef, {type,_,SameName,ArgForms}, + UsedVars) -> + case length(ArgForms) =:= Arity of + true -> + VarArgs = [V || {var,_,V} <- ArgForms, V =/= '_'], + case length(VarArgs) =:= Arity of + true -> + AddToList = fun(X,L) -> [X | L] end, + lists:zipwith(AddToList, VarArgs, UsedVars); + false -> + [[0|L] || L <- UsedVars] + end; + false -> + multi_collect_vars(FullADTRef, ArgForms, UsedVars) + end; +collect_vars(FullADTRef, {type,_,_Name,ArgForms}, UsedVars) -> + multi_collect_vars(FullADTRef, ArgForms, UsedVars); +collect_vars({SameMod,SameName,_Arity} = FullADTRef, + {remote_type,_,[{atom,_,SameMod},{atom,_,SameName},ArgForms]}, + UsedVars) -> + collect_vars(FullADTRef, {type,0,SameName,ArgForms}, UsedVars); +collect_vars(FullADTRef, {remote_type,_,[_RemModForm,_NameForm,ArgForms]}, + UsedVars) -> + multi_collect_vars(FullADTRef, ArgForms, UsedVars); +collect_vars(_FullADTRef, _Call, UsedVars) -> + UsedVars. + +-spec multi_collect_vars(full_imm_type_ref(), [abs_type()], + [[var_name() | 0]]) -> [[var_name() | 0]]. +multi_collect_vars({_Mod,_Name,Arity} = FullADTRef, Forms, UsedVars) -> + NoUsedVars = lists:duplicate(Arity, []), + MoreUsedVars = [collect_vars(FullADTRef,T,NoUsedVars) || T <- Forms], + CombineVars = fun(L1,L2) -> lists:zipwith(fun erlang:'++'/2, L1, L2) end, + lists:foldl(CombineVars, UsedVars, MoreUsedVars). + +-ifdef(NO_MODULES_IN_OPAQUES). +-type var_substs_dict() :: dict(). +-else. +-type var_substs_dict() :: dict:dict(var_name(),abs_type()). +-endif. +-spec update_vars(abs_type(), var_substs_dict(), boolean()) -> abs_type(). +update_vars({paren_type,Line,[Type]}, VarSubstsDict, UnboundToAny) -> + {paren_type, Line, [update_vars(Type,VarSubstsDict,UnboundToAny)]}; +update_vars({ann_type,Line,[Var,Type]}, VarSubstsDict, UnboundToAny) -> + {ann_type, Line, [Var,update_vars(Type,VarSubstsDict,UnboundToAny)]}; +update_vars({var,Line,VarName} = Call, VarSubstsDict, UnboundToAny) -> + case dict:find(VarName, VarSubstsDict) of + {ok,SubstType} -> + SubstType; + error when UnboundToAny =:= false -> + Call; + error when UnboundToAny =:= true -> + {type,Line,any,[]} + end; +update_vars({remote_type,Line,[RemModForm,NameForm,ArgForms]}, VarSubstsDict, + UnboundToAny) -> + NewArgForms = [update_vars(A,VarSubstsDict,UnboundToAny) || A <- ArgForms], + {remote_type, Line, [RemModForm,NameForm,NewArgForms]}; +update_vars({type,_,tuple,any} = Call, _VarSubstsDict, _UnboundToAny) -> + Call; +update_vars({type,Line,Name,ArgForms}, VarSubstsDict, UnboundToAny) -> + {type, Line, Name, [update_vars(A,VarSubstsDict,UnboundToAny) + || A <- ArgForms]}; +update_vars(Call, _VarSubstsDict, _UnboundToAny) -> + Call. + + +%%------------------------------------------------------------------------------ +%% Match-related functions +%%------------------------------------------------------------------------------ + +-spec get_pattern(position(), [abs_type()]) -> pattern(). +get_pattern(TargetPos, FieldForms) -> + {0,RevPattern} = lists:foldl(fun add_field/2, {TargetPos,[]}, FieldForms), + list_to_tuple(lists:reverse(RevPattern)). + +-spec add_field(abs_type(), {non_neg_integer(),[pat_field()]}) -> + {non_neg_integer(),[pat_field(),...]}. +add_field(_Type, {1,Acc}) -> + {0, [1|Acc]}; +add_field({atom,_,Tag}, {Left,Acc}) -> + {erlang:max(0,Left-1), [Tag|Acc]}; +add_field(_Type, {Left,Acc}) -> + {erlang:max(0,Left-1), [0|Acc]}. + +%% @private +-spec match(pattern(), tuple()) -> term(). +match(Pattern, Term) when tuple_size(Pattern) =:= tuple_size(Term) -> + match(tuple_to_list(Pattern), tuple_to_list(Term), none, false); +match(_Pattern, _Term) -> + throw(no_match). + +-spec match([pat_field()], [term()], 'none' | {'ok',T}, boolean()) -> T. +match([], [], {ok,Target}, _TypeMode) -> + Target; +match([0|PatRest], [_|ToMatchRest], Acc, TypeMode) -> + match(PatRest, ToMatchRest, Acc, TypeMode); +match([1|PatRest], [Target|ToMatchRest], none, TypeMode) -> + match(PatRest, ToMatchRest, {ok,Target}, TypeMode); +match([Tag|PatRest], [X|ToMatchRest], Acc, TypeMode) when is_atom(Tag) -> + MatchesTag = + case TypeMode of + true -> can_be_tag(Tag, X); + false -> Tag =:= X + end, + case MatchesTag of + true -> match(PatRest, ToMatchRest, Acc, TypeMode); + false -> throw(no_match) + end. + +%% CAUTION: these must be sorted +-define(NON_ATOM_TYPES, + [arity,binary,bitstring,byte,char,float,'fun',function,integer,iodata, + iolist,list,maybe_improper_list,mfa,neg_integer,nil,no_return, + non_neg_integer,none,nonempty_improper_list,nonempty_list, + nonempty_maybe_improper_list,nonempty_string,number,pid,port, + pos_integer,range,record,reference,string,tuple]). +-define(NON_TUPLE_TYPES, + [arity,atom,binary,bitstring,bool,boolean,byte,char,float,'fun', + function,identifier,integer,iodata,iolist,list,maybe_improper_list, + neg_integer,nil,no_return,node,non_neg_integer,none, + nonempty_improper_list,nonempty_list,nonempty_maybe_improper_list, + nonempty_string,number,pid,port,pos_integer,range,reference,string, + timeout]). +-define(NO_HEAD_TYPES, + [arity,atom,binary,bitstring,bool,boolean,byte,char,float,'fun', + function,identifier,integer,mfa,module,neg_integer,nil,no_return,node, + non_neg_integer,none,number,pid,port,pos_integer,range,record, + reference,timeout,tuple]). + +-spec can_be_tag(atom(), abs_type()) -> boolean(). +can_be_tag(Tag, {ann_type,_,[_Var,Type]}) -> + can_be_tag(Tag, Type); +can_be_tag(Tag, {paren_type,_,[Type]}) -> + can_be_tag(Tag, Type); +can_be_tag(Tag, {atom,_,Atom}) -> + Tag =:= Atom; +can_be_tag(_Tag, {integer,_,_Int}) -> + false; +can_be_tag(_Tag, {op,_,_Op,_Arg}) -> + false; +can_be_tag(_Tag, {op,_,_Op,_Arg1,_Arg2}) -> + false; +can_be_tag(Tag, {type,_,BName,[]}) when BName =:= bool; BName =:= boolean -> + is_boolean(Tag); +can_be_tag(Tag, {type,_,timeout,[]}) -> + Tag =:= infinity; +can_be_tag(Tag, {type,_,union,Choices}) -> + lists:any(fun(C) -> can_be_tag(Tag,C) end, Choices); +can_be_tag(_Tag, {type,_,Name,_Args}) -> + not ordsets:is_element(Name, ?NON_ATOM_TYPES); +can_be_tag(_Tag, _Type) -> + true. + +-spec cant_match(pattern(), abs_type()) -> boolean(). +cant_match(Pattern, {ann_type,_,[_Var,Type]}) -> + cant_match(Pattern, Type); +cant_match(Pattern, {paren_type,_,[Type]}) -> + cant_match(Pattern, Type); +cant_match(_Pattern, {atom,_,_Atom}) -> + true; +cant_match(_Pattern, {integer,_,_Int}) -> + true; +cant_match(_Pattern, {op,_,_Op,_Arg}) -> + true; +cant_match(_Pattern, {op,_,_Op,_Arg1,_Arg2}) -> + true; +cant_match(Pattern, {type,_,mfa,[]}) -> + cant_match(Pattern, {type,0,tuple,[{type,0,atom,[]},{type,0,atom,[]}, + {type,0,arity,[]}]}); +cant_match(Pattern, {type,_,union,Choices}) -> + lists:all(fun(C) -> cant_match(Pattern,C) end, Choices); +cant_match(_Pattern, {type,_,tuple,any}) -> + false; +cant_match(Pattern, {type,_,tuple,Fields}) -> + tuple_size(Pattern) =/= length(Fields) orelse + try match(tuple_to_list(Pattern), Fields, none, true) of + _ -> false + catch + throw:no_match -> true + end; +cant_match(_Pattern, {type,_,Name,_Args}) -> + ordsets:is_element(Name, ?NON_TUPLE_TYPES); +cant_match(_Pattern, _Type) -> + false. + +-spec cant_have_head(abs_type()) -> boolean(). +cant_have_head({ann_type,_,[_Var,Type]}) -> + cant_have_head(Type); +cant_have_head({paren_type,_,[Type]}) -> + cant_have_head(Type); +cant_have_head({atom,_,_Atom}) -> + true; +cant_have_head({integer,_,_Int}) -> + true; +cant_have_head({op,_,_Op,_Arg}) -> + true; +cant_have_head({op,_,_Op,_Arg1,_Arg2}) -> + true; +cant_have_head({type,_,union,Choices}) -> + lists:all(fun cant_have_head/1, Choices); +cant_have_head({type,_,Name,_Args}) -> + ordsets:is_element(Name, ?NO_HEAD_TYPES); +cant_have_head(_Type) -> + false. + +%% Only covers atoms, integers and tuples, i.e. those that can be specified +%% through singleton types. +-spec term_to_singleton_type(atom() | integer() + | loose_tuple(atom() | integer())) -> abs_type(). +term_to_singleton_type(Atom) when is_atom(Atom) -> + {atom,0,Atom}; +term_to_singleton_type(Int) when is_integer(Int), Int >= 0 -> + {integer,0,Int}; +term_to_singleton_type(Int) when is_integer(Int), Int < 0 -> + {op,0,'-',{integer,0,-Int}}; +term_to_singleton_type(Tuple) when is_tuple(Tuple) -> + Fields = tuple_to_list(Tuple), + {type,0,tuple,[term_to_singleton_type(F) || F <- Fields]}. + + +%%------------------------------------------------------------------------------ +%% Instance testing functions +%%------------------------------------------------------------------------------ + +%% CAUTION: this must be sorted +-define(EQUIV_TYPES, + [{arity, {type,0,range,[{integer,0,0},{integer,0,255}]}}, + {bool, {type,0,boolean,[]}}, + {byte, {type,0,range,[{integer,0,0},{integer,0,255}]}}, + {char, {type,0,range,[{integer,0,0},{integer,0,16#10ffff}]}}, + {function, {type,0,'fun',[]}}, + {identifier, {type,0,union,[{type,0,pid,[]},{type,0,port,[]}, + {type,0,reference,[]}]}}, + {iodata, {type,0,union,[{type,0,binary,[]},{type,0,iolist,[]}]}}, + {iolist, {type,0,maybe_improper_list, + [{type,0,union,[{type,0,byte,[]},{type,0,binary,[]}, + {type,0,iolist,[]}]}, + {type,0,binary,[]}]}}, + {list, {type,0,list,[{type,0,any,[]}]}}, + {maybe_improper_list, {type,0,maybe_improper_list,[{type,0,any,[]}, + {type,0,any,[]}]}}, + {mfa, {type,0,tuple,[{type,0,atom,[]},{type,0,atom,[]}, + {type,0,arity,[]}]}}, + {node, {type,0,atom,[]}}, + {nonempty_list, {type,0,nonempty_list,[{type,0,any,[]}]}}, + {nonempty_maybe_improper_list, {type,0,nonempty_maybe_improper_list, + [{type,0,any,[]},{type,0,any,[]}]}}, + {nonempty_string, {type,0,nonempty_list,[{type,0,char,[]}]}}, + {string, {type,0,list,[{type,0,char,[]}]}}, + {term, {type,0,any,[]}}, + {timeout, {type,0,union,[{atom,0,infinity}, + {type,0,non_neg_integer,[]}]}}]). + +%% @private +%% TODO: Most of these functions accept an extended form of abs_type(), namely +%% the addition of a custom wrapper: {'from_mod',mod_name(),...} +-spec is_instance(term(), mod_name(), abs_type()) -> boolean(). +is_instance(X, Mod, TypeForm) -> + is_instance(X, Mod, TypeForm, []). + +-spec is_instance(term(), mod_name(), abs_type(), imm_stack()) -> boolean(). +is_instance(X, _Mod, {from_mod,OrigMod,Type}, Stack) -> + is_instance(X, OrigMod, Type, Stack); +is_instance(_X, _Mod, {var,_,'_'}, _Stack) -> + true; +is_instance(_X, _Mod, {var,_,Name}, _Stack) -> + %% All unconstrained spec vars have been replaced by 'any()' and we always + %% replace the variables on the RHS of types before recursing into them. + %% Provided that '-type' declarations contain no unbound variables, we + %% don't expect to find any non-'_' variables while recursing. + throw({'$typeserver',{unbound_var_in_type_declaration,Name}}); +is_instance(X, Mod, {ann_type,_,[_Var,Type]}, Stack) -> + is_instance(X, Mod, Type, Stack); +is_instance(X, Mod, {paren_type,_,[Type]}, Stack) -> + is_instance(X, Mod, Type, Stack); +is_instance(X, Mod, {remote_type,_,[{atom,_,RemMod},{atom,_,Name},ArgForms]}, + Stack) -> + is_custom_instance(X, Mod, RemMod, Name, ArgForms, true, Stack); +is_instance(SameAtom, _Mod, {atom,_,SameAtom}, _Stack) -> + true; +is_instance(SameInt, _Mod, {integer,_,SameInt}, _Stack) -> + true; +is_instance(X, _Mod, {op,_,_Op,_Arg} = Expr, _Stack) -> + is_int_const(X, Expr); +is_instance(X, _Mod, {op,_,_Op,_Arg1,_Arg2} = Expr, _Stack) -> + is_int_const(X, Expr); +is_instance(_X, _Mod, {type,_,any,[]}, _Stack) -> + true; +is_instance(X, _Mod, {type,_,atom,[]}, _Stack) -> + is_atom(X); +is_instance(X, _Mod, {type,_,binary,[]}, _Stack) -> + is_binary(X); +is_instance(X, _Mod, {type,_,binary,[BaseExpr,UnitExpr]}, _Stack) -> + %% <<_:X,_:_*Y>> means "bitstrings of X + k*Y bits, k >= 0" + case eval_int(BaseExpr) of + {ok,Base} when Base >= 0 -> + case eval_int(UnitExpr) of + {ok,Unit} when Unit >= 0 -> + case is_bitstring(X) of + true -> + BitSizeX = bit_size(X), + case Unit =:= 0 of + true -> + BitSizeX =:= Base; + false -> + BitSizeX >= Base + andalso + (BitSizeX - Base) rem Unit =:= 0 + end; + false -> false + end; + _ -> + abs_expr_error(invalid_unit, UnitExpr) + end; + _ -> + abs_expr_error(invalid_base, BaseExpr) + end; +is_instance(X, _Mod, {type,_,bitstring,[]}, _Stack) -> + is_bitstring(X); +is_instance(X, _Mod, {type,_,boolean,[]}, _Stack) -> + is_boolean(X); +is_instance(X, _Mod, {type,_,float,[]}, _Stack) -> + is_float(X); +is_instance(X, _Mod, {type,_,'fun',[]}, _Stack) -> + is_function(X); +%% TODO: how to check range type? random inputs? special case for 0-arity? +is_instance(X, _Mod, {type,_,'fun',[{type,_,any,[]},_Range]}, _Stack) -> + is_function(X); +is_instance(X, _Mod, {type,_,'fun',[{type,_,product,Domain},_Range]}, _Stack) -> + is_function(X, length(Domain)); +is_instance(X, _Mod, {type,_,integer,[]}, _Stack) -> + is_integer(X); +is_instance(X, Mod, {type,_,list,[Type]}, _Stack) -> + list_test(X, Mod, Type, dummy, true, true, false); +is_instance(X, Mod, {type,_,maybe_improper_list,[Cont,Term]}, _Stack) -> + list_test(X, Mod, Cont, Term, true, true, true); +is_instance(X, _Mod, {type,_,module,[]}, _Stack) -> + is_atom(X) orelse + is_tuple(X) andalso X =/= {} andalso is_atom(element(1,X)); +is_instance([], _Mod, {type,_,nil,[]}, _Stack) -> + true; +is_instance(X, _Mod, {type,_,neg_integer,[]}, _Stack) -> + is_integer(X) andalso X < 0; +is_instance(X, _Mod, {type,_,non_neg_integer,[]}, _Stack) -> + is_integer(X) andalso X >= 0; +is_instance(X, Mod, {type,_,nonempty_list,[Type]}, _Stack) -> + list_test(X, Mod, Type, dummy, false, true, false); +is_instance(X, Mod, {type,_,nonempty_improper_list,[Cont,Term]}, _Stack) -> + list_test(X, Mod, Cont, Term, false, false, true); +is_instance(X, Mod, {type,_,nonempty_maybe_improper_list,[Cont,Term]}, + _Stack) -> + list_test(X, Mod, Cont, Term, false, true, true); +is_instance(X, _Mod, {type,_,number,[]}, _Stack) -> + is_number(X); +is_instance(X, _Mod, {type,_,pid,[]}, _Stack) -> + is_pid(X); +is_instance(X, _Mod, {type,_,port,[]}, _Stack) -> + is_port(X); +is_instance(X, _Mod, {type,_,pos_integer,[]}, _Stack) -> + is_integer(X) andalso X > 0; +is_instance(_X, _Mod, {type,_,product,_Elements}, _Stack) -> + throw({'$typeserver',{internal,product_in_is_instance}}); +is_instance(X, _Mod, {type,_,range,[LowExpr,HighExpr]}, _Stack) -> + case {eval_int(LowExpr),eval_int(HighExpr)} of + {{ok,Low},{ok,High}} when Low =< High -> + X >= Low andalso X =< High; + _ -> + abs_expr_error(invalid_range, LowExpr, HighExpr) + end; +is_instance(X, Mod, {type,_,record,[{atom,_,Name} = NameForm | RawSubsts]}, + Stack) -> + Substs = [{N,T} || {type,_,field_type,[{atom,_,N},T]} <- RawSubsts], + SubstsDict = dict:from_list(Substs), + case get_type_repr(Mod, {record,Name,0}, false) of + {ok,{abs_record,OrigFields}} -> + Fields = [case dict:find(FieldName, SubstsDict) of + {ok,NewFieldType} -> NewFieldType; + error -> OrigFieldType + end + || {FieldName,OrigFieldType} <- OrigFields], + is_instance(X, Mod, {type,0,tuple,[NameForm|Fields]}, Stack); + {error,Reason} -> + throw({'$typeserver',Reason}) + end; +is_instance(X, _Mod, {type,_,reference,[]}, _Stack) -> + is_reference(X); +is_instance(X, _Mod, {type,_,tuple,any}, _Stack) -> + is_tuple(X); +is_instance(X, Mod, {type,_,tuple,Fields}, _Stack) -> + is_tuple(X) andalso tuple_test(tuple_to_list(X), Mod, Fields); +is_instance(X, Mod, {type,_,union,Choices}, Stack) -> + IsInstance = fun(Choice) -> is_instance(X,Mod,Choice,Stack) end, + lists:any(IsInstance, Choices); +is_instance(X, Mod, {type,_,Name,[]}, Stack) -> + case orddict:find(Name, ?EQUIV_TYPES) of + {ok,EquivType} -> + is_instance(X, Mod, EquivType, Stack); + error -> + is_maybe_hard_adt(X, Mod, Name, [], Stack) + end; +is_instance(X, Mod, {type,_,Name,ArgForms}, Stack) -> + is_maybe_hard_adt(X, Mod, Name, ArgForms, Stack); +is_instance(_X, _Mod, _Type, _Stack) -> + false. + +-spec is_int_const(term(), abs_expr()) -> boolean(). +is_int_const(X, Expr) -> + case eval_int(Expr) of + {ok,Int} -> + X =:= Int; + error -> + abs_expr_error(invalid_int_const, Expr) + end. + +%% TODO: We implicitly add the '| []' at the termination of maybe_improper_list. +%% TODO: We ignore a '[]' termination in improper_list. +-spec list_test(term(), mod_name(), abs_type(), 'dummy' | abs_type(), boolean(), + boolean(), boolean()) -> boolean(). +list_test(X, Mod, Content, Termination, CanEmpty, CanProper, CanImproper) -> + is_list(X) andalso + list_rec(X, Mod, Content, Termination, CanEmpty, CanProper, CanImproper). + +-spec list_rec(term(), mod_name(), abs_type(), 'dummy' | abs_type(), boolean(), + boolean(), boolean()) -> boolean(). +list_rec([], _Mod, _Content, _Termination, CanEmpty, CanProper, _CanImproper) -> + CanEmpty andalso CanProper; +list_rec([X | Rest], Mod, Content, Termination, _CanEmpty, CanProper, + CanImproper) -> + is_instance(X, Mod, Content, []) andalso + list_rec(Rest, Mod, Content, Termination, true, CanProper, CanImproper); +list_rec(X, Mod, _Content, Termination, _CanEmpty, _CanProper, CanImproper) -> + CanImproper andalso is_instance(X, Mod, Termination, []). + +-spec tuple_test([term()], mod_name(), [abs_type()]) -> boolean(). +tuple_test([], _Mod, []) -> + true; +tuple_test([X | XTail], Mod, [T | TTail]) -> + is_instance(X, Mod, T, []) andalso tuple_test(XTail, Mod, TTail); +tuple_test(_, _Mod, _) -> + false. + +-spec is_maybe_hard_adt(term(), mod_name(), type_name(), [abs_type()], + imm_stack()) -> boolean(). +is_maybe_hard_adt(X, Mod, Name, ArgForms, Stack) -> + case orddict:find({Name,length(ArgForms)}, ?HARD_ADTS) of + {ok,ADTMod} -> + is_custom_instance(X, Mod, ADTMod, Name, ArgForms, true, Stack); + error -> + is_custom_instance(X, Mod, Mod, Name, ArgForms, false, Stack) + end. + +-spec is_custom_instance(term(), mod_name(), mod_name(), type_name(), + [abs_type()], boolean(), imm_stack()) -> boolean(). +is_custom_instance(X, Mod, RemMod, Name, RawArgForms, IsRemote, Stack) -> + ArgForms = case Mod =/= RemMod of + true -> [{from_mod,Mod,A} || A <- RawArgForms]; + false -> RawArgForms + end, + Arity = length(ArgForms), + FullTypeRef = {RemMod,Name,Arity}, + case lists:member(FullTypeRef, Stack) of + true -> + throw({'$typeserver',{self_reference,FullTypeRef}}); + false -> + TypeRef = {type,Name,Arity}, + AbsType = get_abs_type(RemMod, TypeRef, ArgForms, IsRemote), + is_instance(X, RemMod, AbsType, [FullTypeRef|Stack]) + end. + +-spec get_abs_type(mod_name(), type_ref(), [abs_type()], boolean()) -> + abs_type(). +get_abs_type(RemMod, TypeRef, ArgForms, IsRemote) -> + case get_type_repr(RemMod, TypeRef, IsRemote) of + {ok,TypeRepr} -> + {FinalAbsType,SymbInfo,VarNames} = + case TypeRepr of + {cached,_FinType,FAT,SI} -> {FAT,SI,[]}; + {abs_type,FAT,VN,SI} -> {FAT,SI,VN} + end, + AbsType = + case SymbInfo of + not_symb -> FinalAbsType; + {orig_abs,OrigAbsType} -> OrigAbsType + end, + VarSubstsDict = dict:from_list(lists:zip(VarNames,ArgForms)), + update_vars(AbsType, VarSubstsDict, false); + {error,Reason} -> + throw({'$typeserver',Reason}) + end. + +-spec abs_expr_error(atom(), abs_expr()) -> no_return(). +abs_expr_error(ImmReason, Expr) -> + {error,Reason} = expr_error(ImmReason, Expr), + throw({'$typeserver',Reason}). + +-spec abs_expr_error(atom(), abs_expr(), abs_expr()) -> no_return(). +abs_expr_error(ImmReason, Expr1, Expr2) -> + {error,Reason} = expr_error(ImmReason, Expr1, Expr2), + throw({'$typeserver',Reason}). + + +%%------------------------------------------------------------------------------ +%% Type translation functions +%%------------------------------------------------------------------------------ + +-spec convert(mod_name(), abs_type(), state()) -> + rich_result2(fin_type(),state()). +convert(Mod, TypeForm, State) -> + case convert(Mod, TypeForm, State, [], dict:new()) of + {ok,{simple,Type},NewState} -> + {ok, Type, NewState}; + {ok,{rec,_RecFun,_RecArgs},_NewState} -> + {error, {internal,rec_returned_to_toplevel}}; + {error,_Reason} = Error -> + Error + end. + +-spec convert(mod_name(), abs_type(), state(), stack(), var_dict()) -> + rich_result2(ret_type(),state()). +convert(Mod, {paren_type,_,[Type]}, State, Stack, VarDict) -> + convert(Mod, Type, State, Stack, VarDict); +convert(Mod, {ann_type,_,[_Var,Type]}, State, Stack, VarDict) -> + convert(Mod, Type, State, Stack, VarDict); +convert(_Mod, {var,_,'_'}, State, _Stack, _VarDict) -> + {ok, {simple,proper_types:any()}, State}; +convert(_Mod, {var,_,VarName}, State, _Stack, VarDict) -> + case dict:find(VarName, VarDict) of + %% TODO: do we need to check if we are at toplevel of a recursive? + {ok,RetType} -> {ok, RetType, State}; + error -> {error, {unbound_var,VarName}} + end; +convert(Mod, {remote_type,_,[{atom,_,RemMod},{atom,_,Name},ArgForms]}, State, + Stack, VarDict) -> + case prepare_for_remote(RemMod, Name, length(ArgForms), State) of + {ok,NewState} -> + convert_custom(Mod,RemMod,Name,ArgForms,NewState,Stack,VarDict); + {error,_Reason} = Error -> + Error + end; +convert(_Mod, {atom,_,Atom}, State, _Stack, _VarDict) -> + {ok, {simple,proper_types:exactly(Atom)}, State}; +convert(_Mod, {integer,_,_Int} = IntExpr, State, _Stack, _VarDict) -> + convert_integer(IntExpr, State); +convert(_Mod, {op,_,_Op,_Arg} = OpExpr, State, _Stack, _VarDict) -> + convert_integer(OpExpr, State); +convert(_Mod, {op,_,_Op,_Arg1,_Arg2} = OpExpr, State, _Stack, _VarDict) -> + convert_integer(OpExpr, State); +convert(_Mod, {type,_,binary,[BaseExpr,UnitExpr]}, State, _Stack, _VarDict) -> + %% <<_:X,_:_*Y>> means "bitstrings of X + k*Y bits, k >= 0" + case eval_int(BaseExpr) of + {ok,0} -> + case eval_int(UnitExpr) of + {ok,0} -> {ok, {simple,proper_types:exactly(<<>>)}, State}; + {ok,1} -> {ok, {simple,proper_types:bitstring()}, State}; + {ok,8} -> {ok, {simple,proper_types:binary()}, State}; + {ok,N} when N > 0 -> + Gen = ?LET(L, proper_types:list(proper_types:bitstring(N)), + concat_bitstrings(L)), + {ok, {simple,Gen}, State}; + _ -> expr_error(invalid_unit, UnitExpr) + end; + {ok,Base} when Base > 0 -> + Head = proper_types:bitstring(Base), + case eval_int(UnitExpr) of + {ok,0} -> {ok, {simple,Head}, State}; + {ok,1} -> + Tail = proper_types:bitstring(), + {ok, {simple,concat_binary_gens(Head, Tail)}, State}; + {ok,8} -> + Tail = proper_types:binary(), + {ok, {simple,concat_binary_gens(Head, Tail)}, State}; + {ok,N} when N > 0 -> + Tail = + ?LET(L, proper_types:list(proper_types:bitstring(N)), + concat_bitstrings(L)), + {ok, {simple,concat_binary_gens(Head, Tail)}, State}; + _ -> expr_error(invalid_unit, UnitExpr) + end; + _ -> + expr_error(invalid_base, BaseExpr) + end; +convert(_Mod, {type,_,range,[LowExpr,HighExpr]}, State, _Stack, _VarDict) -> + case {eval_int(LowExpr),eval_int(HighExpr)} of + {{ok,Low},{ok,High}} when Low =< High -> + {ok, {simple,proper_types:integer(Low,High)}, State}; + _ -> + expr_error(invalid_range, LowExpr, HighExpr) + end; +convert(_Mod, {type,_,nil,[]}, State, _Stack, _VarDict) -> + {ok, {simple,proper_types:exactly([])}, State}; +convert(Mod, {type,_,list,[ElemForm]}, State, Stack, VarDict) -> + convert_list(Mod, false, ElemForm, State, Stack, VarDict); +convert(Mod, {type,_,nonempty_list,[ElemForm]}, State, Stack, VarDict) -> + convert_list(Mod, true, ElemForm, State, Stack, VarDict); +convert(_Mod, {type,_,nonempty_list,[]}, State, _Stack, _VarDict) -> + {ok, {simple,proper_types:non_empty(proper_types:list())}, State}; +convert(_Mod, {type,_,nonempty_string,[]}, State, _Stack, _VarDict) -> + {ok, {simple,proper_types:non_empty(proper_types:string())}, State}; +convert(_Mod, {type,_,tuple,any}, State, _Stack, _VarDict) -> + {ok, {simple,proper_types:tuple()}, State}; +convert(Mod, {type,_,tuple,ElemForms}, State, Stack, VarDict) -> + convert_tuple(Mod, ElemForms, false, State, Stack, VarDict); +convert(Mod, {type,_,'$fixed_list',ElemForms}, State, Stack, VarDict) -> + convert_tuple(Mod, ElemForms, true, State, Stack, VarDict); +convert(Mod, {type,_,record,[{atom,_,Name}|FieldForms]}, State, Stack, + VarDict) -> + convert_record(Mod, Name, FieldForms, State, Stack, VarDict); +convert(Mod, {type,_,union,ChoiceForms}, State, Stack, VarDict) -> + convert_union(Mod, ChoiceForms, State, Stack, VarDict); +convert(Mod, {type,_,'fun',[{type,_,product,Domain},Range]}, State, Stack, + VarDict) -> + convert_fun(Mod, length(Domain), Range, State, Stack, VarDict); +%% TODO: These types should be replaced with accurate types. +%% TODO: Add support for nonempty_improper_list/2. +convert(Mod, {type,_,maybe_improper_list,[]}, State, Stack, VarDict) -> + convert(Mod, {type,0,list,[]}, State, Stack, VarDict); +convert(Mod, {type,_,maybe_improper_list,[Cont,_Ter]}, State, Stack, VarDict) -> + convert(Mod, {type,0,list,[Cont]}, State, Stack, VarDict); +convert(Mod, {type,_,nonempty_maybe_improper_list,[]}, State, Stack, VarDict) -> + convert(Mod, {type,0,nonempty_list,[]}, State, Stack, VarDict); +convert(Mod, {type,_,nonempty_maybe_improper_list,[Cont,_Term]}, State, Stack, + VarDict) -> + convert(Mod, {type,0,nonempty_list,[Cont]}, State, Stack, VarDict); +convert(Mod, {type,_,iodata,[]}, State, Stack, VarDict) -> + RealType = {type,0,union,[{type,0,binary,[]},{type,0,iolist,[]}]}, + convert(Mod, RealType, State, Stack, VarDict); +convert(Mod, {type,_,Name,[]}, State, Stack, VarDict) -> + case ordsets:is_element(Name, ?STD_TYPES_0) of + true -> + {ok, {simple,proper_types:Name()}, State}; + false -> + convert_maybe_hard_adt(Mod, Name, [], State, Stack, VarDict) + end; +convert(Mod, {type,_,Name,ArgForms}, State, Stack, VarDict) -> + convert_maybe_hard_adt(Mod, Name, ArgForms, State, Stack, VarDict); +convert(_Mod, TypeForm, _State, _Stack, _VarDict) -> + {error, {unsupported_type,TypeForm}}. + +-spec concat_bitstrings([bitstring()]) -> bitstring(). +concat_bitstrings(BitStrings) -> + concat_bitstrings_tr(BitStrings, <<>>). + +-spec concat_bitstrings_tr([bitstring()], bitstring()) -> bitstring(). +concat_bitstrings_tr([], Acc) -> + Acc; +concat_bitstrings_tr([BitString | Rest], Acc) -> + concat_bitstrings_tr(Rest, <>). + +-spec concat_binary_gens(fin_type(), fin_type()) -> fin_type(). +concat_binary_gens(HeadType, TailType) -> + ?LET({H,T}, {HeadType,TailType}, <>). + +-spec convert_fun(mod_name(), arity(), abs_type(), state(), stack(), + var_dict()) -> rich_result2(ret_type(),state()). +convert_fun(Mod, Arity, Range, State, Stack, VarDict) -> + case convert(Mod, Range, State, ['fun' | Stack], VarDict) of + {ok,{simple,RangeType},NewState} -> + {ok, {simple,proper_types:function(Arity,RangeType)}, NewState}; + {ok,{rec,RecFun,RecArgs},NewState} -> + case at_toplevel(RecArgs, Stack) of + true -> base_case_error(Stack); + false -> convert_rec_fun(Arity, RecFun, RecArgs, NewState) + end; + {error,_Reason} = Error -> + Error + end. + +-spec convert_rec_fun(arity(), rec_fun(), rec_args(), state()) -> + {'ok',ret_type(),state()}. +convert_rec_fun(Arity, RecFun, RecArgs, State) -> + %% We bind the generated value by size. + NewRecFun = + fun(GenFuns,Size) -> + proper_types:function(Arity, RecFun(GenFuns,Size)) + end, + NewRecArgs = clean_rec_args(RecArgs), + {ok, {rec,NewRecFun,NewRecArgs}, State}. + +-spec convert_list(mod_name(), boolean(), abs_type(), state(), stack(), + var_dict()) -> rich_result2(ret_type(),state()). +convert_list(Mod, NonEmpty, ElemForm, State, Stack, VarDict) -> + case convert(Mod, ElemForm, State, [list | Stack], VarDict) of + {ok,{simple,ElemType},NewState} -> + InnerType = proper_types:list(ElemType), + FinType = case NonEmpty of + true -> proper_types:non_empty(InnerType); + false -> InnerType + end, + {ok, {simple,FinType}, NewState}; + {ok,{rec,RecFun,RecArgs},NewState} -> + case {at_toplevel(RecArgs,Stack), NonEmpty} of + {true,true} -> + base_case_error(Stack); + {true,false} -> + NewRecFun = + fun(GenFuns,Size) -> + ElemGen = fun(S) -> ?LAZY(RecFun(GenFuns,S)) end, + proper_types:distlist(Size, ElemGen, false) + end, + NewRecArgs = clean_rec_args(RecArgs), + {ok, {rec,NewRecFun,NewRecArgs}, NewState}; + {false,_} -> + {NewRecFun,NewRecArgs} = + convert_rec_list(RecFun, RecArgs, NonEmpty), + {ok, {rec,NewRecFun,NewRecArgs}, NewState} + end; + {error,_Reason} = Error -> + Error + end. + +-spec convert_rec_list(rec_fun(), rec_args(), boolean()) -> + {rec_fun(),rec_args()}. +convert_rec_list(RecFun, [{true,FullTypeRef}] = RecArgs, NonEmpty) -> + {NewRecFun,_NormalRecArgs} = + convert_normal_rec_list(RecFun, RecArgs, NonEmpty), + AltRecFun = + fun([InstListGen],Size) -> + InstTypesList = + proper_types:get_prop(internal_types, InstListGen(Size)), + proper_types:fixed_list([RecFun([fun(_Size) -> I end],0) + || I <- InstTypesList]) + end, + NewRecArgs = [{{list,NonEmpty,AltRecFun},FullTypeRef}], + {NewRecFun, NewRecArgs}; +convert_rec_list(RecFun, RecArgs, NonEmpty) -> + convert_normal_rec_list(RecFun, RecArgs, NonEmpty). + +-spec convert_normal_rec_list(rec_fun(), rec_args(), boolean()) -> + {rec_fun(),rec_args()}. +convert_normal_rec_list(RecFun, RecArgs, NonEmpty) -> + NewRecFun = fun(GenFuns,Size) -> + ElemGen = fun(S) -> RecFun(GenFuns, S) end, + proper_types:distlist(Size, ElemGen, NonEmpty) + end, + NewRecArgs = clean_rec_args(RecArgs), + {NewRecFun, NewRecArgs}. + +-spec convert_tuple(mod_name(), [abs_type()], boolean(), state(), stack(), + var_dict()) -> rich_result2(ret_type(),state()). +convert_tuple(Mod, ElemForms, ToList, State, Stack, VarDict) -> + case process_list(Mod, ElemForms, State, [tuple | Stack], VarDict) of + {ok,RetTypes,NewState} -> + case combine_ret_types(RetTypes, {tuple,ToList}) of + {simple,_FinType} = RetType -> + {ok, RetType, NewState}; + {rec,_RecFun,RecArgs} = RetType -> + case at_toplevel(RecArgs, Stack) of + true -> base_case_error(Stack); + false -> {ok, RetType, NewState} + end + end; + {error,_Reason} = Error -> + Error + end. + +-spec convert_union(mod_name(), [abs_type()], state(), stack(), var_dict()) -> + rich_result2(ret_type(),state()). +convert_union(Mod, ChoiceForms, State, Stack, VarDict) -> + case process_list(Mod, ChoiceForms, State, [union | Stack], VarDict) of + {ok,RawChoices,NewState} -> + ProcessChoice = fun(T,A) -> process_choice(T,A,Stack) end, + {RevSelfRecs,RevNonSelfRecs,RevNonRecs} = + lists:foldl(ProcessChoice, {[],[],[]}, RawChoices), + case {lists:reverse(RevSelfRecs),lists:reverse(RevNonSelfRecs), + lists:reverse(RevNonRecs)} of + {_SelfRecs,[],[]} -> + base_case_error(Stack); + {[],NonSelfRecs,NonRecs} -> + {ok, combine_ret_types(NonRecs ++ NonSelfRecs, union), + NewState}; + {SelfRecs,NonSelfRecs,NonRecs} -> + {BCaseRecFun,BCaseRecArgs} = + case combine_ret_types(NonRecs ++ NonSelfRecs, union) of + {simple,BCaseType} -> + {fun([],_Size) -> BCaseType end,[]}; + {rec,BCRecFun,BCRecArgs} -> + {BCRecFun,BCRecArgs} + end, + NumBCaseGens = length(BCaseRecArgs), + [ParentRef | _Upper] = Stack, + FallbackRecFun = fun([SelfGen],_Size) -> SelfGen(0) end, + FallbackRecArgs = [{false,ParentRef}], + FallbackRetType = {rec,FallbackRecFun,FallbackRecArgs}, + {rec,RCaseRecFun,RCaseRecArgs} = + combine_ret_types([FallbackRetType] ++ SelfRecs + ++ NonSelfRecs, wunion), + NewRecFun = + fun(AllGens,Size) -> + {BCaseGens,RCaseGens} = + lists:split(NumBCaseGens, AllGens), + case Size of + 0 -> BCaseRecFun(BCaseGens,0); + _ -> RCaseRecFun(RCaseGens,Size) + end + end, + NewRecArgs = BCaseRecArgs ++ RCaseRecArgs, + {ok, {rec,NewRecFun,NewRecArgs}, NewState} + end; + {error,_Reason} = Error -> + Error + end. + +-spec process_choice(ret_type(), {[ret_type()],[ret_type()],[ret_type()]}, + stack()) -> {[ret_type()],[ret_type()],[ret_type()]}. +process_choice({simple,_} = RetType, {SelfRecs,NonSelfRecs,NonRecs}, _Stack) -> + {SelfRecs, NonSelfRecs, [RetType | NonRecs]}; +process_choice({rec,RecFun,RecArgs}, {SelfRecs,NonSelfRecs,NonRecs}, Stack) -> + case at_toplevel(RecArgs, Stack) of + true -> + case partition_by_toplevel(RecArgs, Stack, true) of + {[],[],_,_} -> + NewRecArgs = clean_rec_args(RecArgs), + {[{rec,RecFun,NewRecArgs} | SelfRecs], NonSelfRecs, + NonRecs}; + {SelfRecArgs,SelfPos,OtherRecArgs,_OtherPos} -> + NumInstances = length(SelfRecArgs), + IsListInst = fun({true,_FTRef}) -> false + ; ({{list,_NE,_AltRecFun},_FTRef}) -> true + end, + NewRecFun = + case proper_arith:filter(IsListInst,SelfRecArgs) of + {[],[]} -> + no_list_inst_rec_fun(RecFun,NumInstances, + SelfPos); + {[{{list,NonEmpty,AltRecFun},_}],[ListInstPos]} -> + list_inst_rec_fun(AltRecFun,NumInstances, + SelfPos,NonEmpty,ListInstPos) + end, + [{_B,SelfRef} | _] = SelfRecArgs, + NewRecArgs = + [{false,SelfRef} | clean_rec_args(OtherRecArgs)], + {[{rec,NewRecFun,NewRecArgs} | SelfRecs], NonSelfRecs, + NonRecs} + end; + false -> + NewRecArgs = clean_rec_args(RecArgs), + {SelfRecs, [{rec,RecFun,NewRecArgs} | NonSelfRecs], NonRecs} + end. + +-spec no_list_inst_rec_fun(rec_fun(), pos_integer(), [position()]) -> rec_fun(). +no_list_inst_rec_fun(RecFun, NumInstances, SelfPos) -> + fun([SelfGen|OtherGens], Size) -> + ?LETSHRINK( + Instances, + %% Size distribution will be a little off if both normal and + %% instance-accepting generators are present. + lists:duplicate(NumInstances, SelfGen(Size div NumInstances)), + begin + InstGens = [fun(_Size) -> proper_types:exactly(I) end + || I <- Instances], + AllGens = proper_arith:insert(InstGens, SelfPos, OtherGens), + RecFun(AllGens, Size) + end) + end. + +-spec list_inst_rec_fun(rec_fun(), pos_integer(), [position()], boolean(), + position()) -> rec_fun(). +list_inst_rec_fun(AltRecFun, NumInstances, SelfPos, NonEmpty, ListInstPos) -> + fun([SelfGen|OtherGens], Size) -> + ?LETSHRINK( + AllInsts, + lists:duplicate(NumInstances - 1, SelfGen(Size div NumInstances)) + ++ proper_types:distlist(Size div NumInstances, SelfGen, NonEmpty), + begin + {Instances,InstList} = lists:split(NumInstances - 1, AllInsts), + InstGens = [fun(_Size) -> proper_types:exactly(I) end + || I <- Instances], + InstTypesList = [proper_types:exactly(I) || I <- InstList], + InstListGen = + fun(_Size) -> proper_types:fixed_list(InstTypesList) end, + AllInstGens = proper_arith:list_insert(ListInstPos, InstListGen, + InstGens), + AllGens = proper_arith:insert(AllInstGens, SelfPos, OtherGens), + AltRecFun(AllGens, Size) + end) + end. + +-spec convert_maybe_hard_adt(mod_name(), type_name(), [abs_type()], state(), + stack(), var_dict()) -> + rich_result2(ret_type(),state()). +convert_maybe_hard_adt(Mod, Name, ArgForms, State, Stack, VarDict) -> + Arity = length(ArgForms), + case orddict:find({Name,Arity}, ?HARD_ADTS) of + {ok,Mod} -> + convert_custom(Mod, Mod, Name, ArgForms, State, Stack, VarDict); + {ok,ADTMod} -> + ADT = {remote_type,0,[{atom,0,ADTMod},{atom,0,Name},ArgForms]}, + convert(Mod, ADT, State, Stack, VarDict); + error -> + convert_custom(Mod, Mod, Name, ArgForms, State, Stack, VarDict) + end. + +-spec convert_custom(mod_name(), mod_name(), type_name(), [abs_type()], state(), + stack(), var_dict()) -> rich_result2(ret_type(),state()). +convert_custom(Mod, RemMod, Name, ArgForms, State, Stack, VarDict) -> + case process_list(Mod, ArgForms, State, Stack, VarDict) of + {ok,Args,NewState} -> + Arity = length(Args), + TypeRef = {type,Name,Arity}, + FullTypeRef = {RemMod,type,Name,Args}, + convert_type(TypeRef, FullTypeRef, NewState, Stack); + {error,_Reason} = Error -> + Error + end. + +-spec convert_record(mod_name(), type_name(), [abs_type()], state(), stack(), + var_dict()) -> rich_result2(ret_type(),state()). +convert_record(Mod, Name, RawSubsts, State, Stack, VarDict) -> + Substs = [{N,T} || {type,_,field_type,[{atom,_,N},T]} <- RawSubsts], + {SubstFields,SubstTypeForms} = lists:unzip(Substs), + case process_list(Mod, SubstTypeForms, State, Stack, VarDict) of + {ok,SubstTypes,NewState} -> + SubstsDict = dict:from_list(lists:zip(SubstFields, SubstTypes)), + TypeRef = {record,Name,0}, + FullTypeRef = {Mod,record,Name,SubstsDict}, + convert_type(TypeRef, FullTypeRef, NewState, Stack); + {error,_Reason} = Error -> + Error + end. + +-spec convert_type(type_ref(), full_type_ref(), state(), stack()) -> + rich_result2(ret_type(),state()). +convert_type(TypeRef, {Mod,_Kind,_Name,_Spec} = FullTypeRef, State, Stack) -> + case stack_position(FullTypeRef, Stack) of + none -> + case get_type_repr(Mod, TypeRef, false, State) of + {ok,TypeRepr,NewState} -> + convert_new_type(TypeRef, FullTypeRef, TypeRepr, NewState, + Stack); + {error,_Reason} = Error -> + Error + end; + 1 -> + base_case_error(Stack); + _Pos -> + {ok, {rec,fun([Gen],Size) -> Gen(Size) end,[{true,FullTypeRef}]}, + State} + end. + +-spec convert_new_type(type_ref(), full_type_ref(), type_repr(), state(), + stack()) -> rich_result2(ret_type(),state()). +convert_new_type(_TypeRef, {_Mod,type,_Name,[]}, + {cached,FinType,_TypeForm,_SymbInfo}, State, _Stack) -> + {ok, {simple,FinType}, State}; +convert_new_type(TypeRef, {Mod,type,_Name,Args} = FullTypeRef, + {abs_type,TypeForm,Vars,SymbInfo}, State, Stack) -> + VarDict = dict:from_list(lists:zip(Vars, Args)), + case convert(Mod, TypeForm, State, [FullTypeRef | Stack], VarDict) of + {ok, {simple,ImmFinType}, NewState} -> + FinType = case SymbInfo of + not_symb -> + ImmFinType; + {orig_abs,_OrigAbsType} -> + proper_symb:internal_well_defined(ImmFinType) + end, + FinalState = case Vars of + [] -> cache_type(Mod, TypeRef, FinType, TypeForm, + SymbInfo, NewState); + _ -> NewState + end, + {ok, {simple,FinType}, FinalState}; + {ok, {rec,RecFun,RecArgs}, NewState} -> + convert_maybe_rec(FullTypeRef, SymbInfo, RecFun, RecArgs, NewState, + Stack); + {error,_Reason} = Error -> + Error + end; +convert_new_type(_TypeRef, {Mod,record,Name,SubstsDict} = FullTypeRef, + {abs_record,OrigFields}, State, Stack) -> + Fields = [case dict:find(FieldName, SubstsDict) of + {ok,NewFieldType} -> NewFieldType; + error -> OrigFieldType + end + || {FieldName,OrigFieldType} <- OrigFields], + case convert_tuple(Mod, [{atom,0,Name} | Fields], false, State, + [FullTypeRef | Stack], dict:new()) of + {ok, {simple,_FinType}, _NewState} = Result -> + Result; + {ok, {rec,RecFun,RecArgs}, NewState} -> + convert_maybe_rec(FullTypeRef, not_symb, RecFun, RecArgs, NewState, + Stack); + {error,_Reason} = Error -> + Error + end. + +-spec cache_type(mod_name(), type_ref(), fin_type(), abs_type(), symb_info(), + state()) -> state(). +cache_type(Mod, TypeRef, FinType, TypeForm, SymbInfo, + #state{types = Types} = State) -> + TypeRepr = {cached,FinType,TypeForm,SymbInfo}, + ModTypes = dict:fetch(Mod, Types), + NewModTypes = dict:store(TypeRef, TypeRepr, ModTypes), + NewTypes = dict:store(Mod, NewModTypes, Types), + State#state{types = NewTypes}. + +-spec convert_maybe_rec(full_type_ref(), symb_info(), rec_fun(), rec_args(), + state(), stack()) -> rich_result2(ret_type(),state()). +convert_maybe_rec(FullTypeRef, SymbInfo, RecFun, RecArgs, State, Stack) -> + case at_toplevel(RecArgs, Stack) of + true -> base_case_error(Stack); + false -> safe_convert_maybe_rec(FullTypeRef, SymbInfo, RecFun, RecArgs, + State) + end. + +-spec safe_convert_maybe_rec(full_type_ref(),symb_info(),rec_fun(),rec_args(), + state()) -> rich_result2(ret_type(),state()). +safe_convert_maybe_rec(FullTypeRef, SymbInfo, RecFun, RecArgs, State) -> + case partition_rec_args(FullTypeRef, RecArgs, false) of + {[],[],_,_} -> + {ok, {rec,RecFun,RecArgs}, State}; + {MyRecArgs,MyPos,OtherRecArgs,_OtherPos} -> + case lists:all(fun({B,_T}) -> B =:= false end, MyRecArgs) of + true -> convert_rec_type(SymbInfo, RecFun, MyPos, OtherRecArgs, + State); + false -> {error, {internal,true_rec_arg_reached_type}} + end + end. + +-spec convert_rec_type(symb_info(), rec_fun(), [position()], rec_args(), + state()) -> {ok, ret_type(), state()}. +convert_rec_type(SymbInfo, RecFun, MyPos, [], State) -> + NumRecArgs = length(MyPos), + M = fun(GenFun) -> + fun(Size) -> + GenFuns = lists:duplicate(NumRecArgs, GenFun), + RecFun(GenFuns, erlang:max(0,Size - 1)) + end + end, + SizedGen = y(M), + ImmFinType = ?SIZED(Size,SizedGen(Size + 1)), + FinType = case SymbInfo of + not_symb -> + ImmFinType; + {orig_abs,_OrigAbsType} -> + proper_symb:internal_well_defined(ImmFinType) + end, + {ok, {simple,FinType}, State}; +convert_rec_type(_SymbInfo, RecFun, MyPos, OtherRecArgs, State) -> + NumRecArgs = length(MyPos), + NewRecFun = + fun(OtherGens,TopSize) -> + M = fun(GenFun) -> + fun(Size) -> + GenFuns = lists:duplicate(NumRecArgs, GenFun), + AllGens = + proper_arith:insert(GenFuns, MyPos, OtherGens), + RecFun(AllGens, erlang:max(0,Size - 1)) + end + end, + (y(M))(TopSize) + end, + NewRecArgs = clean_rec_args(OtherRecArgs), + {ok, {rec,NewRecFun,NewRecArgs}, State}. + +%% Y Combinator: Read more at http://bc.tech.coop/blog/070611.html. +-spec y(fun((fun((T) -> S)) -> fun((T) -> S))) -> fun((T) -> S). +y(M) -> + G = fun(F) -> + M(fun(A) -> (F(F))(A) end) + end, + G(G). + +-spec process_list(mod_name(), [abs_type() | ret_type()], state(), stack(), + var_dict()) -> rich_result2([ret_type()],state()). +process_list(Mod, RawTypes, State, Stack, VarDict) -> + Process = fun({simple,_FinType} = Type, {ok,Types,State1}) -> + {ok, [Type|Types], State1}; + ({rec,_RecFun,_RecArgs} = Type, {ok,Types,State1}) -> + {ok, [Type|Types], State1}; + (TypeForm, {ok,Types,State1}) -> + case convert(Mod, TypeForm, State1, Stack, VarDict) of + {ok,Type,State2} -> {ok,[Type|Types],State2}; + {error,_} = Err -> Err + end; + (_RawType, {error,_} = Err) -> + Err + end, + case lists:foldl(Process, {ok,[],State}, RawTypes) of + {ok,RevTypes,NewState} -> + {ok, lists:reverse(RevTypes), NewState}; + {error,_Reason} = Error -> + Error + end. + +-spec convert_integer(abs_expr(), state()) -> rich_result2(ret_type(),state()). +convert_integer(Expr, State) -> + case eval_int(Expr) of + {ok,Int} -> {ok, {simple,proper_types:exactly(Int)}, State}; + error -> expr_error(invalid_int_const, Expr) + end. + +-spec eval_int(abs_expr()) -> tagged_result(integer()). +eval_int(Expr) -> + NoBindings = erl_eval:new_bindings(), + try erl_eval:expr(Expr, NoBindings) of + {value,Value,_NewBindings} when is_integer(Value) -> + {ok, Value}; + _ -> + error + catch + error:_ -> + error + end. + +-spec expr_error(atom(), abs_expr()) -> {'error',term()}. +expr_error(Reason, Expr) -> + {error, {Reason,lists:flatten(erl_pp:expr(Expr))}}. + +-spec expr_error(atom(), abs_expr(), abs_expr()) -> {'error',term()}. +expr_error(Reason, Expr1, Expr2) -> + Str1 = lists:flatten(erl_pp:expr(Expr1)), + Str2 = lists:flatten(erl_pp:expr(Expr2)), + {error, {Reason,Str1,Str2}}. + +-spec base_case_error(stack()) -> {'error',term()}. +%% TODO: This might confuse, since it doesn't record the arguments to parametric +%% types or the type subsitutions of a record. +base_case_error([{Mod,type,Name,Args} | _Upper]) -> + Arity = length(Args), + {error, {no_base_case,{Mod,type,Name,Arity}}}; +base_case_error([{Mod,record,Name,_SubstsDict} | _Upper]) -> + {error, {no_base_case,{Mod,record,Name}}}. + + +%%------------------------------------------------------------------------------ +%% Helper datatypes handling functions +%%------------------------------------------------------------------------------ + +-spec stack_position(full_type_ref(), stack()) -> 'none' | pos_integer(). +stack_position(FullTypeRef, Stack) -> + SameType = fun(A) -> same_full_type_ref(A,FullTypeRef) end, + case proper_arith:find_first(SameType, Stack) of + {Pos,_} -> Pos; + none -> none + end. + +-spec partition_by_toplevel(rec_args(), stack(), boolean()) -> + {rec_args(),[position()],rec_args(),[position()]}. +partition_by_toplevel(RecArgs, [], _OnlyInstanceAccepting) -> + {[],[],RecArgs,lists:seq(1,length(RecArgs))}; +partition_by_toplevel(RecArgs, [_Parent | _Upper], _OnlyInstanceAccepting) + when is_atom(_Parent) -> + {[],[],RecArgs,lists:seq(1,length(RecArgs))}; +partition_by_toplevel(RecArgs, [Parent | _Upper], OnlyInstanceAccepting) -> + partition_rec_args(Parent, RecArgs, OnlyInstanceAccepting). + +-spec at_toplevel(rec_args(), stack()) -> boolean(). +at_toplevel(RecArgs, Stack) -> + case partition_by_toplevel(RecArgs, Stack, false) of + {[],[],_,_} -> false; + _ -> true + end. + +-spec partition_rec_args(full_type_ref(), rec_args(), boolean()) -> + {rec_args(),[position()],rec_args(),[position()]}. +partition_rec_args(FullTypeRef, RecArgs, OnlyInstanceAccepting) -> + SameType = + case OnlyInstanceAccepting of + true -> fun({false,_T}) -> false + ; ({_B,T}) -> same_full_type_ref(T,FullTypeRef) end; + false -> fun({_B,T}) -> same_full_type_ref(T,FullTypeRef) end + end, + proper_arith:partition(SameType, RecArgs). + +%% Tuples can be of 0 arity, unions of 1 and wunions at least of 2. +-spec combine_ret_types([ret_type()], {'tuple',boolean()} | 'union' + | 'wunion') -> ret_type(). +combine_ret_types(RetTypes, EnclosingType) -> + case lists:all(fun is_simple_ret_type/1, RetTypes) of + true -> + %% This should never happen for wunion. + Combine = case EnclosingType of + {tuple,false} -> fun proper_types:tuple/1; + {tuple,true} -> fun proper_types:fixed_list/1; + union -> fun proper_types:union/1 + end, + FinTypes = [T || {simple,T} <- RetTypes], + {simple, Combine(FinTypes)}; + false -> + NumTypes = length(RetTypes), + {RevRecFuns,RevRecArgsList,NumRecs} = + lists:foldl(fun add_ret_type/2, {[],[],0}, RetTypes), + RecFuns = lists:reverse(RevRecFuns), + RecArgsList = lists:reverse(RevRecArgsList), + RecArgLens = [length(RecArgs) || RecArgs <- RecArgsList], + RecFunInfo = {NumTypes,NumRecs,RecArgLens,RecFuns}, + FlatRecArgs = lists:flatten(RecArgsList), + {NewRecFun,NewRecArgs} = + case EnclosingType of + {tuple,ToList} -> + {tuple_rec_fun(RecFunInfo,ToList), + soft_clean_rec_args(FlatRecArgs,RecFunInfo,ToList)}; + union -> + {union_rec_fun(RecFunInfo),clean_rec_args(FlatRecArgs)}; + wunion -> + {wunion_rec_fun(RecFunInfo), + clean_rec_args(FlatRecArgs)} + end, + {rec, NewRecFun, NewRecArgs} + end. + +-spec tuple_rec_fun(rec_fun_info(), boolean()) -> rec_fun(). +tuple_rec_fun({_NumTypes,NumRecs,RecArgLens,RecFuns}, ToList) -> + Combine = case ToList of + true -> fun proper_types:fixed_list/1; + false -> fun proper_types:tuple/1 + end, + fun(AllGFs,TopSize) -> + Size = TopSize div NumRecs, + GFsList = proper_arith:unflatten(AllGFs, RecArgLens), + ArgsList = [[GenFuns,Size] || GenFuns <- GFsList], + ZipFun = fun erlang:apply/2, + Combine(lists:zipwith(ZipFun, RecFuns, ArgsList)) + end. + +-spec union_rec_fun(rec_fun_info()) -> rec_fun(). +union_rec_fun({_NumTypes,_NumRecs,RecArgLens,RecFuns}) -> + fun(AllGFs,Size) -> + GFsList = proper_arith:unflatten(AllGFs, RecArgLens), + ArgsList = [[GenFuns,Size] || GenFuns <- GFsList], + ZipFun = fun(F,A) -> ?LAZY(apply(F,A)) end, + proper_types:union(lists:zipwith(ZipFun, RecFuns, ArgsList)) + end. + +-spec wunion_rec_fun(rec_fun_info()) -> rec_fun(). +wunion_rec_fun({NumTypes,_NumRecs,RecArgLens,RecFuns}) -> + fun(AllGFs,Size) -> + GFsList = proper_arith:unflatten(AllGFs, RecArgLens), + ArgsList = [[GenFuns,Size] || GenFuns <- GFsList], + ZipFun = fun(W,F,A) -> {W,?LAZY(apply(F,A))} end, + RecWeight = erlang:max(1, Size div (NumTypes - 1)), + Weights = [1 | lists:duplicate(NumTypes - 1, RecWeight)], + WeightedChoices = lists:zipwith3(ZipFun, Weights, RecFuns, ArgsList), + proper_types:wunion(WeightedChoices) + end. + +-spec add_ret_type(ret_type(), {[rec_fun()],[rec_args()],non_neg_integer()}) -> + {[rec_fun()],[rec_args()],non_neg_integer()}. +add_ret_type({simple,FinType}, {RecFuns,RecArgsList,NumRecs}) -> + {[fun([],_) -> FinType end | RecFuns], [[] | RecArgsList], NumRecs}; +add_ret_type({rec,RecFun,RecArgs}, {RecFuns,RecArgsList,NumRecs}) -> + {[RecFun | RecFuns], [RecArgs | RecArgsList], NumRecs + 1}. + +-spec is_simple_ret_type(ret_type()) -> boolean(). +is_simple_ret_type({simple,_FinType}) -> + true; +is_simple_ret_type({rec,_RecFun,_RecArgs}) -> + false. + +-spec clean_rec_args(rec_args()) -> rec_args(). +clean_rec_args(RecArgs) -> + [{false,F} || {_B,F} <- RecArgs]. + +-spec soft_clean_rec_args(rec_args(), rec_fun_info(), boolean()) -> rec_args(). +soft_clean_rec_args(RecArgs, RecFunInfo, ToList) -> + soft_clean_rec_args_tr(RecArgs, [], RecFunInfo, ToList, false, 1). + +-spec soft_clean_rec_args_tr(rec_args(), rec_args(), rec_fun_info(), boolean(), + boolean(), position()) -> rec_args(). +soft_clean_rec_args_tr([], Acc, _RecFunInfo, _ToList, _FoundListInst, _Pos) -> + lists:reverse(Acc); +soft_clean_rec_args_tr([{{list,_NonEmpty,_AltRecFun},FTRef} | Rest], Acc, + RecFunInfo, ToList, true, Pos) -> + NewArg = {false,FTRef}, + soft_clean_rec_args_tr(Rest, [NewArg|Acc], RecFunInfo, ToList, true, Pos+1); +soft_clean_rec_args_tr([{{list,NonEmpty,AltRecFun},FTRef} | Rest], Acc, + RecFunInfo, ToList, false, Pos) -> + {NumTypes,NumRecs,RecArgLens,RecFuns} = RecFunInfo, + AltRecFunPos = get_group(Pos, RecArgLens), + AltRecFuns = proper_arith:list_update(AltRecFunPos, AltRecFun, RecFuns), + AltRecFunInfo = {NumTypes,NumRecs,RecArgLens,AltRecFuns}, + NewArg = {{list,NonEmpty,tuple_rec_fun(AltRecFunInfo,ToList)},FTRef}, + soft_clean_rec_args_tr(Rest, [NewArg|Acc], RecFunInfo, ToList, true, Pos+1); +soft_clean_rec_args_tr([Arg | Rest], Acc, RecFunInfo, ToList, FoundListInst, + Pos) -> + soft_clean_rec_args_tr(Rest, [Arg | Acc], RecFunInfo, ToList, FoundListInst, + Pos+1). + +-spec get_group(pos_integer(), [non_neg_integer()]) -> pos_integer(). +get_group(Pos, AllMembers) -> + get_group_tr(Pos, AllMembers, 1). + +-spec get_group_tr(pos_integer(), [non_neg_integer()], pos_integer()) -> + pos_integer(). +get_group_tr(Pos, [Members | Rest], GroupNum) -> + case Pos =< Members of + true -> GroupNum; + false -> get_group_tr(Pos - Members, Rest, GroupNum + 1) + end. + +-spec same_full_type_ref(full_type_ref(), term()) -> boolean(). +same_full_type_ref({SameMod,type,SameName,Args1}, + {SameMod,type,SameName,Args2}) -> + length(Args1) =:= length(Args2) + andalso lists:all(fun({A,B}) -> same_ret_type(A,B) end, + lists:zip(Args1, Args2)); +same_full_type_ref({SameMod,record,SameName,SubstsDict1}, + {SameMod,record,SameName,SubstsDict2}) -> + same_substs_dict(SubstsDict1, SubstsDict2); +same_full_type_ref(_, _) -> + false. + +-spec same_ret_type(ret_type(), ret_type()) -> boolean(). +same_ret_type({simple,FinType1}, {simple,FinType2}) -> + same_fin_type(FinType1, FinType2); +same_ret_type({rec,RecFun1,RecArgs1}, {rec,RecFun2,RecArgs2}) -> + NumRecArgs = length(RecArgs1), + length(RecArgs2) =:= NumRecArgs + andalso lists:all(fun({A1,A2}) -> same_rec_arg(A1,A2,NumRecArgs) end, + lists:zip(RecArgs1,RecArgs2)) + andalso same_rec_fun(RecFun1, RecFun2, NumRecArgs); +same_ret_type(_, _) -> + false. + +%% TODO: Is this too strict? +-spec same_rec_arg(rec_arg(), rec_arg(), arity()) -> boolean(). +same_rec_arg({{list,SameBool,AltRecFun1},FTRef1}, + {{list,SameBool,AltRecFun2},FTRef2}, NumRecArgs) -> + same_rec_fun(AltRecFun1, AltRecFun2, NumRecArgs) + andalso same_full_type_ref(FTRef1, FTRef2); +same_rec_arg({true,FTRef1}, {true,FTRef2}, _NumRecArgs) -> + same_full_type_ref(FTRef1, FTRef2); +same_rec_arg({false,FTRef1}, {false,FTRef2}, _NumRecArgs) -> + same_full_type_ref(FTRef1, FTRef2); +same_rec_arg(_, _, _NumRecArgs) -> + false. + +-spec same_substs_dict(substs_dict(), substs_dict()) -> boolean(). +same_substs_dict(SubstsDict1, SubstsDict2) -> + SameKVPair = fun({{_K,V1},{_K,V2}}) -> same_ret_type(V1,V2); + (_) -> false + end, + SubstsKVList1 = lists:sort(dict:to_list(SubstsDict1)), + SubstsKVList2 = lists:sort(dict:to_list(SubstsDict2)), + length(SubstsKVList1) =:= length(SubstsKVList2) + andalso lists:all(SameKVPair, lists:zip(SubstsKVList1,SubstsKVList2)). + +-spec same_fin_type(fin_type(), fin_type()) -> boolean(). +same_fin_type(Type1, Type2) -> + proper_types:equal_types(Type1, Type2). + +-spec same_rec_fun(rec_fun(), rec_fun(), arity()) -> boolean(). +same_rec_fun(RecFun1, RecFun2, NumRecArgs) -> + %% It's ok that we return a type, even if there's a 'true' for use of + %% an instance. + GenFun = fun(_Size) -> proper_types:exactly('$dummy') end, + GenFuns = lists:duplicate(NumRecArgs,GenFun), + same_fin_type(RecFun1(GenFuns,0), RecFun2(GenFuns,0)). -- cgit v1.2.3 From 63f3bcc5e1d9290b3b3d6d5cfdd5a7ae53732cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jimmy=20Z=C3=B6ger?= Date: Thu, 20 Aug 2015 15:30:43 +0200 Subject: Correct conversion from seconds to milliseconds --- lib/inets/src/http_client/httpc_response.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl index 10af1949a4..4bf2ba2b9b 100644 --- a/lib/inets/src/http_client/httpc_response.erl +++ b/lib/inets/src/http_client/httpc_response.erl @@ -328,7 +328,7 @@ status_service_unavailable(Response = {_, Headers, _}, Request) -> undefined -> status_server_error_50x(Response, Request); Time when (length(Time) < 3) -> % Wait only 99 s or less - NewTime = list_to_integer(Time) * 100, % time in ms + NewTime = list_to_integer(Time) * 1000, % time in ms {_, Data} = format_response(Response), {retry, {NewTime, Request}, Data}; _ -> -- cgit v1.2.3 From b3c7bf872f7fbe304cdcb449a2d501933805aa48 Mon Sep 17 00:00:00 2001 From: Shane Howley Date: Wed, 15 Jul 2015 18:46:21 +0100 Subject: stdlib: Fix bug with unicode detection in re Fix bug with unrecognised 'unicode' option in re:split/2,3 & re:replace/3,4 when using pre-compiled regex. --- lib/stdlib/src/re.erl | 101 ++++++++++++++++----------------- lib/stdlib/test/re_SUITE.erl | 129 ++++++++++++++++++++++--------------------- 2 files changed, 114 insertions(+), 116 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl index e5d9fc51d2..80bfe38970 100644 --- a/lib/stdlib/src/re.erl +++ b/lib/stdlib/src/re.erl @@ -132,8 +132,9 @@ split(Subject,RE) -> split(Subject,RE,Options) -> try - {NewOpt,Convert,Unicode,Limit,Strip,Group} = - process_split_params(Options,iodata,false,-1,false,false), + {NewOpt,Convert,Limit,Strip,Group} = + process_split_params(Options,iodata,-1,false,false), + Unicode = check_for_unicode(RE, Options), FlatSubject = to_binary(Subject, Unicode), case compile_split(RE,NewOpt) of {error,_Err} -> @@ -324,8 +325,8 @@ replace(Subject,RE,Replacement) -> replace(Subject,RE,Replacement,Options) -> try - {NewOpt,Convert,Unicode} = - process_repl_params(Options,iodata,false), + {NewOpt,Convert} = process_repl_params(Options,iodata), + Unicode = check_for_unicode(RE, Options), FlatSubject = to_binary(Subject, Unicode), FlatReplacement = to_binary(Replacement, Unicode), IoList = do_replace(FlatSubject,Subject,RE,FlatReplacement,NewOpt), @@ -367,65 +368,59 @@ do_replace(FlatSubject,Subject,RE,Replacement,Options) -> apply_mlist(FlatSubject,Replacement,[Slist]) end. -process_repl_params([],Convert,Unicode) -> - {[],Convert,Unicode}; -process_repl_params([unicode|T],C,_U) -> - {NT,NC,NU} = process_repl_params(T,C,true), - {[unicode|NT],NC,NU}; -process_repl_params([report_errors|_],_,_) -> +process_repl_params([],Convert) -> + {[],Convert}; +process_repl_params([report_errors|_],_) -> throw(badopt); -process_repl_params([{capture,_,_}|_],_,_) -> +process_repl_params([{capture,_,_}|_],_) -> throw(badopt); -process_repl_params([{capture,_}|_],_,_) -> +process_repl_params([{capture,_}|_],_) -> throw(badopt); -process_repl_params([{return,iodata}|T],_C,U) -> - process_repl_params(T,iodata,U); -process_repl_params([{return,list}|T],_C,U) -> - process_repl_params(T,list,U); -process_repl_params([{return,binary}|T],_C,U) -> - process_repl_params(T,binary,U); -process_repl_params([{return,_}|_],_,_) -> +process_repl_params([{return,iodata}|T],_C) -> + process_repl_params(T,iodata); +process_repl_params([{return,list}|T],_C) -> + process_repl_params(T,list); +process_repl_params([{return,binary}|T],_C) -> + process_repl_params(T,binary); +process_repl_params([{return,_}|_],_) -> throw(badopt); -process_repl_params([H|T],C,U) -> - {NT,NC,NU} = process_repl_params(T,C,U), - {[H|NT],NC,NU}. - -process_split_params([],Convert,Unicode,Limit,Strip,Group) -> - {[],Convert,Unicode,Limit,Strip,Group}; -process_split_params([unicode|T],C,_U,L,S,G) -> - {NT,NC,NU,NL,NS,NG} = process_split_params(T,C,true,L,S,G), - {[unicode|NT],NC,NU,NL,NS,NG}; -process_split_params([trim|T],C,U,_L,_S,G) -> - process_split_params(T,C,U,-1,true,G); -process_split_params([{parts,0}|T],C,U,_L,_S,G) -> - process_split_params(T,C,U,-1,true,G); -process_split_params([{parts,N}|T],C,U,_L,_S,G) when is_integer(N), N >= 1 -> - process_split_params(T,C,U,N-1,false,G); -process_split_params([{parts,infinity}|T],C,U,_L,_S,G) -> - process_split_params(T,C,U,-1,false,G); -process_split_params([{parts,_}|_],_,_,_,_,_) -> +process_repl_params([H|T],C) -> + {NT,NC} = process_repl_params(T,C), + {[H|NT],NC}. + +process_split_params([],Convert,Limit,Strip,Group) -> + {[],Convert,Limit,Strip,Group}; +process_split_params([trim|T],C,_L,_S,G) -> + process_split_params(T,C,-1,true,G); +process_split_params([{parts,0}|T],C,_L,_S,G) -> + process_split_params(T,C,-1,true,G); +process_split_params([{parts,N}|T],C,_L,_S,G) when is_integer(N), N >= 1 -> + process_split_params(T,C,N-1,false,G); +process_split_params([{parts,infinity}|T],C,_L,_S,G) -> + process_split_params(T,C,-1,false,G); +process_split_params([{parts,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([group|T],C,U,L,S,_G) -> - process_split_params(T,C,U,L,S,true); -process_split_params([global|_],_,_,_,_,_) -> +process_split_params([group|T],C,L,S,_G) -> + process_split_params(T,C,L,S,true); +process_split_params([global|_],_,_,_,_) -> throw(badopt); -process_split_params([report_errors|_],_,_,_,_,_) -> +process_split_params([report_errors|_],_,_,_,_) -> throw(badopt); -process_split_params([{capture,_,_}|_],_,_,_,_,_) -> +process_split_params([{capture,_,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([{capture,_}|_],_,_,_,_,_) -> +process_split_params([{capture,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([{return,iodata}|T],_C,U,L,S,G) -> - process_split_params(T,iodata,U,L,S,G); -process_split_params([{return,list}|T],_C,U,L,S,G) -> - process_split_params(T,list,U,L,S,G); -process_split_params([{return,binary}|T],_C,U,L,S,G) -> - process_split_params(T,binary,U,L,S,G); -process_split_params([{return,_}|_],_,_,_,_,_) -> +process_split_params([{return,iodata}|T],_C,L,S,G) -> + process_split_params(T,iodata,L,S,G); +process_split_params([{return,list}|T],_C,L,S,G) -> + process_split_params(T,list,L,S,G); +process_split_params([{return,binary}|T],_C,L,S,G) -> + process_split_params(T,binary,L,S,G); +process_split_params([{return,_}|_],_,_,_,_) -> throw(badopt); -process_split_params([H|T],C,U,L,S,G) -> - {NT,NC,NU,NL,NS,NG} = process_split_params(T,C,U,L,S,G), - {[H|NT],NC,NU,NL,NS,NG}. +process_split_params([H|T],C,L,S,G) -> + {NT,NC,NL,NS,NG} = process_split_params(T,C,L,S,G), + {[H|NT],NC,NL,NS,NG}. apply_mlist(Subject,Replacement,Mlist) -> do_mlist(Subject,Subject,0,precomp_repl(Replacement), Mlist). diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl index b8c20d9745..d78d6153da 100644 --- a/lib/stdlib/test/re_SUITE.erl +++ b/lib/stdlib/test/re_SUITE.erl @@ -28,7 +28,7 @@ pcre_compile_workspace_overflow/1,re_infinite_loop/1, re_backwards_accented/1,opt_dupnames/1,opt_all_names/1,inspect/1, opt_no_start_optimize/1,opt_never_utf/1,opt_ucp/1, - match_limit/1,sub_binaries/1]). + match_limit/1,sub_binaries/1,copt/1]). -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -319,32 +319,26 @@ replace_return(doc) -> ["Tests return options of replace together with global searching"]; replace_return(Config) when is_list(Config) -> Dog = ?t:timetrap(?t:minutes(3)), - ?line {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")), - ?line <<"nasse">> = re:replace(<<"nisse">>,"i","a",[{return,binary}]), - ?line <<"ABCÅXABCXA">> = re:replace("ABC\305abcdABCabcdA","a(?bcd)","X",[global,{return,binary}]), - - ?line [<<"ABCÅ">>, - <<"X">>, - <<"ABC">>, - <<"X">> | - <<"A">> ] = - re:replace("ABCÅabcdABCabcdA","a(?bcd)","X",[global,{return,iodata}]), - ?line "ABCÅXABCXA" = re:replace("ABCÅabcdABCabcdA","a(?bcd)","X",[global,{return,list},unicode]), - ?line <<65,66,67,195,133,88,65,66,67,88,65>> = re:replace("ABCÅabcdABCabcdA","a(?bcd)","X",[global,{return,binary},unicode]), - ?line <<65,66,67,195,133,88,65,66,67,97,98,99,100,65>> = re:replace("ABCÅabcdABCabcdA","a(?bcd)","X",[{return,binary},unicode]), - ?line <<"iXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}]), - ?line <<"jXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}]), - ?line <<"Xk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}]), - ?line <<"9X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g9X",[{return,binary}]), - ?line <<"0X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g10X",[{return,binary}]), - ?line <<"X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g11X",[{return,binary}]), - ?line <<"971">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{9}7",[{return,binary}]), - ?line <<"071">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{10}7",[{return,binary}]), - ?line <<"71">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{11}7",[{return,binary}]), - ?line "a\x{400}bcX" = re:replace("a\x{400}bcd","d","X",[global,{return,list},unicode]), - ?line <<"a",208,128,"bcX">> = re:replace("a\x{400}bcd","d","X",[global,{return,binary},unicode]), - ?line "a\x{400}bcd" = re:replace("a\x{400}bcd","Z","X",[global,{return,list},unicode]), - ?line <<"a",208,128,"bcd">> = re:replace("a\x{400}bcd","Z","X",[global,{return,binary},unicode]), + {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")), + ok = replacetest(<<"nisse">>,"i","a",[{return,binary}],<<"nasse">>), + ok = replacetest("ABC\305abcdABCabcdA","a(?bcd)","X",[global,{return,binary}],<<"ABCÅXABCXA">>), + ok = replacetest("ABCÅabcdABCabcdA","a(?bcd)","X",[global,{return,iodata}],[<<"ABCÅ">>,<<"X">>,<<"ABC">>,<<"X">>|<<"A">>]), + ok = replacetest("ABCÅabcdABCabcdA","a(?bcd)","X",[global,{return,list},unicode],"ABCÅXABCXA"), + ok = replacetest("ABCÅabcdABCabcdA","a(?bcd)","X",[global,{return,binary},unicode],<<65,66,67,195,133,88,65,66,67,88,65>>), + ok = replacetest("ABCÅabcdABCabcdA","a(?bcd)","X",[{return,binary},unicode],<<65,66,67,195,133,88,65,66,67,97,98,99,100,65>>), + ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}],<<"iXk">>), + ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}],<<"jXk">>), + ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}],<<"Xk">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g9X",[{return,binary}],<<"9X1">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g10X",[{return,binary}],<<"0X1">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g11X",[{return,binary}],<<"X1">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{9}7",[{return,binary}],<<"971">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{10}7",[{return,binary}],<<"071">>), + ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{11}7",[{return,binary}],<<"71">>), + ok = replacetest("a\x{400}bcd","d","X",[global,{return,list},unicode],"a\x{400}bcX"), + ok = replacetest("a\x{400}bcd","d","X",[global,{return,binary},unicode],<<"a",208,128,"bcX">>), + ok = replacetest("a\x{400}bcd","Z","X",[global,{return,list},unicode],"a\x{400}bcd"), + ok = replacetest("a\x{400}bcd","Z","X",[global,{return,binary},unicode],<<"a",208,128,"bcd">>), ?t:timetrap_cancel(Dog), ok. @@ -389,6 +383,35 @@ crtest(Subject,RE,Options,true,Result) -> error end. +replacetest(Subject,RE,Replacement,Options,Result) -> + Result = re:replace(Subject,RE,Replacement,Options), + {CompileOptions,ReplaceOptions} = lists:partition(fun copt/1, Options), + {ok,MP} = re:compile(RE,CompileOptions), + Result = re:replace(Subject,MP,Replacement,ReplaceOptions), + ok. + +splittest(Subject,RE,Options,Result) -> + Result = re:split(Subject,RE,Options), + {CompileOptions,SplitOptions} = lists:partition(fun copt/1, Options), + {ok,MP} = re:compile(RE,CompileOptions), + Result = re:split(Subject,MP,SplitOptions), + ok. + +copt(caseless) -> true; +copt(no_start_optimize) -> true; +copt(never_utf) -> true; +copt(ucp) -> true; +copt(dollar_endonly) -> true; +copt(dotall) -> true; +copt(extended) -> true; +copt(firstline) -> true; +copt(multiline) -> true; +copt(no_auto_capture) -> true; +copt(dupnames) -> true; +copt(ungreedy) -> true; +copt(unicode) -> true; +copt(_) -> false. + split_autogen(doc) -> ["Test split with autogenerated erlang module"]; split_autogen(Config) when is_list(Config) -> @@ -401,43 +424,23 @@ split_options(doc) -> ["Test special options to split."]; split_options(Config) when is_list(Config) -> Dog = ?t:timetrap(?t:minutes(1)), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,trim]), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,{parts,0}]), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] = - re:split("a b c ","( )",[{parts,infinity},group]), - ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] = - re:split("a b c ","( )",[group]), - ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], - [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] = - re:split(" a b c d ","( +)",[group,trim]), - ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], - [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] = - re:split(" a b c d ","( +)",[{parts,0},group]), - ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], - [<<"c">>,<<" ">>],[<<"d">>,<<" ">>],[<<>>]] = - re:split(" a b c d ","( +)",[{parts,infinity},group]), - ?line [[<<"a">>,<<" ">>],[<<"b c d">>]] = - re:split("a b c d","( +)",[{parts,2},group]), - ?line [[[967]," "],["b c d"]] = - re:split([967]++" b c d","( +)", - [{parts,2},group,{return,list},unicode]), - ?line [[<<207,135>>,<<" ">>],[<<"b c d">>]] = - re:split([967]++" b c d","( +)", - [{parts,2},group,{return,binary},unicode]), - ?line {'EXIT',{badarg,_}} = - (catch re:split([967]++" b c d","( +)", - [{parts,2},group,{return,binary}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{parts,-2}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{parts,banan}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{capture,all}])), - ?line {'EXIT',{badarg,_}} = - (catch re:split("a b c d","( +)",[{capture,[],binary}])), + ok = splittest("a b c ","( )",[group,trim],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]), + ok = splittest("a b c ","( )",[group,{parts,0}],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]), + ok = splittest("a b c ","( )",[{parts,infinity},group],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]]), + ok = splittest("a b c ","( )",[group],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]]), + ok = splittest(" a b c d ","( +)",[group,trim],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>]]), + ok = splittest(" a b c d ","( +)",[{parts,0},group],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>]]), + ok = splittest(" a b c d ","( +)",[{parts,infinity},group],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>],[<<>>]]), + ok = splittest("a b c d","( +)",[{parts,2},group],[[<<"a">>,<<" ">>],[<<"b c d">>]]), + ok = splittest([967]++" b c d","( +)",[{parts,2},group,{return,list},unicode],[[[967]," "],["b c d"]]), + ok = splittest([967]++" b c d","( +)",[{parts,2},group,{return,binary},unicode],[[<<207,135>>,<<" ">>],[<<"b c d">>]]), + {'EXIT',{badarg,_}} = (catch re:split([967]++" b c d","( +)",[{parts,2},group,{return,binary}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{parts,-2}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{parts,banan}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,all}])), + {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,[],binary}])), % Parts 0 is equal to no parts specification (implicit strip) - ?line ["a"," ","b"," ","c"," ","d"] = - re:split("a b c d","( *)",[{parts,0},{return,list}]), + ok = splittest("a b c d","( *)",[{parts,0},{return,list}],["a"," ","b"," ","c"," ","d"]), ?t:timetrap_cancel(Dog), ok. -- cgit v1.2.3 From 1a1deb03240e7b1f738b8bc0fb172e6ae8e7061d Mon Sep 17 00:00:00 2001 From: Yuki Ito Date: Mon, 6 Jul 2015 05:46:31 +0900 Subject: Fix cover output file This is introduced by ab435488a. If a module includes lines which are less than 1, for example a module which includes `eunit.hrl`, its cover output file misses the coverage lines. --- lib/tools/src/cover.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 8d1cb96504..366d6bcbd9 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -2437,7 +2437,7 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) -> "\n\n"]), Pattern = {#bump{module=Module,line='$1',_='_'},'$2'}, - MS = [{Pattern,[],[{{'$1','$2'}}]}], + MS = [{Pattern,[{is_integer,'$1'},{'>','$1',0}],[{{'$1','$2'}}]}], CovLines = lists:keysort(1,ets:select(?COLLECTION_TABLE, MS)), print_lines(Module, CovLines, InFd, OutFd, 1, HTML), -- cgit v1.2.3 From 1cd00d0d139a23b1abc8ec73e9e49031974b2acb Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 29 Jun 2015 12:45:08 +0200 Subject: inets: httpd - Mend broken fd option --- lib/inets/src/http_lib/http_transport.erl | 2 +- lib/inets/src/http_server/httpd_sup.erl | 34 ++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index bbe3ec9e4c..719dc4c425 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -269,7 +269,7 @@ get_socket_info(Addr, Port, Fd) -> undefined -> {Port, sock_opts(Addr, BaseOpts)}; Fd -> - {0, sock_opts(Addr, [{fd, Fd} | BaseOpts])} + {0, sock_opts([{fd, Fd} | BaseOpts])} end. %%------------------------------------------------------------------------- diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl index de08624d44..f0b1942e2f 100644 --- a/lib/inets/src/http_server/httpd_sup.erl +++ b/lib/inets/src/http_server/httpd_sup.erl @@ -185,12 +185,16 @@ httpd_child_spec(ConfigFile, AcceptTimeoutDef, DebugDef) -> end. httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port, Profile) -> - Fd = proplists:get_value(fd, Config, undefined), - case Port == 0 orelse Fd =/= undefined of - true -> - httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile); - false -> - httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port, Profile) + case get_fd(Port) of + {ok, Fd} -> + case Port == 0 orelse Fd =/= undefined of + true -> + httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile); + false -> + httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port, Profile) + end; + Error -> + Error end. httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile) -> @@ -236,7 +240,7 @@ listen(Address, Port, Config) -> SocketType -> case http_transport:start(SocketType) of ok -> - Fd = proplists:get_value(fd, Config), + {ok, Fd} = get_fd(Port), IpFamily = proplists:get_value(ipfamily, Config, inet6fb4), case http_transport:listen(SocketType, Address, Port, Fd, IpFamily) of {ok, ListenSocket} -> @@ -355,3 +359,19 @@ ssl_ca_certificate_file(Config) -> File -> [{cacertfile, File}] end. + +get_fd(0) -> + {ok, undefined}; +get_fd(Port) -> + FdKey = list_to_atom("httpd_" ++ integer_to_list(Port)), + case init:get_argument(FdKey) of + {ok, [[Value]]} -> + case (catch list_to_integer(Value)) of + N when is_integer(N) -> + {ok, N}; + _ -> + {error, {bad_descriptor, Value}} + end; + _ -> + {ok, undefined} + end. -- cgit v1.2.3 From cdcc5ae200ffd47bdb8704e20d1a5d50db12808d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 14 Aug 2015 16:01:01 +0200 Subject: inets: tftpd - Mend broken fd option --- lib/inets/src/tftp/tftp_engine.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/tftp/tftp_engine.erl b/lib/inets/src/tftp/tftp_engine.erl index fa44cd61ce..d0510e795b 100644 --- a/lib/inets/src/tftp/tftp_engine.erl +++ b/lib/inets/src/tftp/tftp_engine.erl @@ -128,8 +128,8 @@ daemon_start(Options) when is_list(Options) -> daemon_init(Config) when is_record(Config, config), is_pid(Config#config.parent_pid) -> process_flag(trap_exit, true), - UdpOptions = prepare_daemon_udp(Config), - case catch gen_udp:open(Config#config.udp_port, UdpOptions) of + {Port, UdpOptions} = prepare_daemon_udp(Config), + case catch gen_udp:open(Port, UdpOptions) of {ok, Socket} -> {ok, ActualPort} = inet:port(Socket), proc_lib:init_ack({ok, self()}), @@ -157,7 +157,7 @@ prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) case lists:keymember(fd, 1, UdpOptions) of true -> %% Use explicit fd - UdpOptions; + {Port, UdpOptions}; false -> %% Use fd from setuid_socket_wrap, such as -tftpd_69 InitArg = list_to_atom("tftpd_" ++ integer_to_list(Port)), @@ -165,7 +165,7 @@ prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) {ok, [[FdStr]] = Badarg} when is_list(FdStr) -> case catch list_to_integer(FdStr) of Fd when is_integer(Fd) -> - [{fd, Fd} | UdpOptions]; + {0, [{fd, Fd} | lists:keydelete(ip, 1, UdpOptions)]}; {'EXIT', _} -> Text = lists:flatten(io_lib:format("Illegal prebound fd ~p: ~p", [InitArg, Badarg])), print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")), @@ -176,7 +176,7 @@ prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")), exit({badarg, {prebound_fd, InitArg, Badarg}}); error -> - UdpOptions + {Port, UdpOptions} end end. -- cgit v1.2.3 From da6854e9557a045ae1a858c6f2949594228341f7 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 26 Aug 2015 09:07:43 +0200 Subject: inets: Ctify inets_SUITE Also remove all form of io:formats that can easily be achieved by tracing. --- lib/inets/test/inets_SUITE.erl | 167 ++++++----------------------------------- 1 file changed, 25 insertions(+), 142 deletions(-) (limited to 'lib') diff --git a/lib/inets/test/inets_SUITE.erl b/lib/inets/test/inets_SUITE.erl index c3586f09e3..928d9dc391 100644 --- a/lib/inets/test/inets_SUITE.erl +++ b/lib/inets/test/inets_SUITE.erl @@ -21,7 +21,6 @@ -module(inets_SUITE). -include_lib("common_test/include/ct.hrl"). --include("test_server_line.hrl"). -include("inets_test_lib.hrl"). %% Note: This directive should only be used in test suites. @@ -37,8 +36,12 @@ all() -> groups() -> [{services_test, [], - [start_inets, start_httpc, start_httpd, start_ftpc, - start_tftpd]}, + [start_inets, + start_httpc, + start_httpd, + start_ftpc, + start_tftpd + ]}, {app_test, [], [{inets_app_test, all}]}, {appup_test, [], [{inets_appup_test, all}]}]. @@ -48,9 +51,6 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - - - %%-------------------------------------------------------------------- %% Function: init_per_suite(Config) -> Config %% Config - [tuple()] @@ -103,14 +103,8 @@ end_per_testcase(_, Config) -> %% Test cases starts here. %%------------------------------------------------------------------------- - - -%%------------------------------------------------------------------------- - -start_inets(doc) -> - ["Test inets API functions"]; -start_inets(suite) -> - []; +start_inets() -> + [{doc, "Test inets API functions"}]. start_inets(Config) when is_list(Config) -> [_|_] = inets:service_names(), @@ -134,134 +128,85 @@ start_inets(Config) when is_list(Config) -> ok = inets:start(permanent), ok = inets:stop(). - %%------------------------------------------------------------------------- -start_httpc(doc) -> - ["Start/stop of httpc service"]; -start_httpc(suite) -> - []; +start_httpc() -> + [{doc, "Start/stop of httpc service"}]. start_httpc(Config) when is_list(Config) -> process_flag(trap_exit, true), - tsp("start_httpc -> entry with" - "~n Config: ~p", [Config]), - PrivDir = ?config(priv_dir, Config), - tsp("start_httpc -> start (empty) inets"), ok = inets:start(), - - tsp("start_httpc -> start httpc (as inets service) with profile foo"), {ok, Pid0} = inets:start(httpc, [{profile, foo}]), - tsp("start_httpc -> check running services"), Pids0 = [ServicePid || {_, ServicePid} <- inets:services()], true = lists:member(Pid0, Pids0), [_|_] = inets:services_info(), - tsp("start_httpc -> stop httpc"), inets:stop(httpc, Pid0), - tsp("start_httpc -> sleep some"), test_server:sleep(100), - tsp("start_httpc -> check running services"), Pids1 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid0, Pids1), - tsp("start_httpc -> start httpc (stand-alone) with profile bar"), {ok, Pid1} = inets:start(httpc, [{profile, bar}], stand_alone), - tsp("start_httpc -> check running services"), Pids2 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid1, Pids2), - tsp("start_httpc -> stop httpc"), ok = inets:stop(stand_alone, Pid1), receive {'EXIT', Pid1, shutdown} -> ok after 100 -> - tsf(stand_alone_not_shutdown) + ct:fail(stand_alone_not_shutdown) end, - tsp("start_httpc -> stop inets"), ok = inets:stop(), - tsp("start_httpc -> unload inets"), application:load(inets), - - tsp("start_httpc -> set inets environment (httpc profile foo)"), application:set_env(inets, services, [{httpc,[{profile, foo}, {data_dir, PrivDir}]}]), - - tsp("start_httpc -> start inets"), ok = inets:start(), - tsp("start_httpc -> check running services"), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - tsp("start_httpc -> unset inets env"), application:unset_env(inets, services), - - tsp("start_httpc -> stop inets"), ok = inets:stop(), - - tsp("start_httpc -> start (empty) inets"), ok = inets:start(), - tsp("start_httpc -> start inets httpc service with profile foo"), {ok, Pid3} = inets:start(httpc, [{profile, foo}]), - - tsp("start_httpc -> stop inets service httpc with profile foo"), ok = inets:stop(httpc, foo), - - tsp("start_httpc -> check running services"), Pids3 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid3, Pids3), - - tsp("start_httpc -> stop inets"), - ok = inets:stop(), - - tsp("start_httpc -> done"), - ok. - + ok = inets:stop(). %%------------------------------------------------------------------------- -start_httpd(doc) -> - ["Start/stop of httpd service"]; -start_httpd(suite) -> - []; +start_httpd() -> + [{doc, "Start/stop of httpd service"}]. start_httpd(Config) when is_list(Config) -> process_flag(trap_exit, true), - i("start_httpd -> entry with" - "~n Config: ~p", [Config]), PrivDir = ?config(priv_dir, Config), HttpdConf = [{server_name, "httpd_test"}, {server_root, PrivDir}, - {document_root, PrivDir}, {bind_address, "localhost"}], + {document_root, PrivDir}, {bind_address, any}], - i("start_httpd -> start inets"), ok = inets:start(), - - i("start_httpd -> start httpd service"), {ok, Pid0} = inets:start(httpd, [{port, 0}, {ipfamily, inet} | HttpdConf]), Pids0 = [ServicePid || {_, ServicePid} <- inets:services()], true = lists:member(Pid0, Pids0), [_|_] = inets:services_info(), - i("start_httpd -> stop httpd service"), inets:stop(httpd, Pid0), test_server:sleep(500), Pids1 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid0, Pids1), - i("start_httpd -> start (stand-alone) httpd service"), {ok, Pid1} = inets:start(httpd, [{port, 0}, {ipfamily, inet} | HttpdConf], stand_alone), Pids2 = [ServicePid || {_, ServicePid} <- inets:services()], false = lists:member(Pid1, Pids2), - i("start_httpd -> stop (stand-alone) httpd service"), ok = inets:stop(stand_alone, Pid1), receive {'EXIT', Pid1, shutdown} -> @@ -269,7 +214,6 @@ start_httpd(Config) when is_list(Config) -> after 100 -> test_server:fail(stand_alone_not_shutdown) end, - i("start_httpd -> stop inets"), ok = inets:stop(), File0 = filename:join(PrivDir, "httpd.conf"), {ok, Fd0} = file:open(File0, [write]), @@ -277,17 +221,12 @@ start_httpd(Config) when is_list(Config) -> ok = file:write(Fd0, Str), file:close(Fd0), - i("start_httpd -> [application] load inets"), application:load(inets), - i("start_httpd -> [application] set httpd services env with proplist-file"), application:set_env(inets, services, [{httpd, [{proplist_file, File0}]}]), - i("start_httpd -> start inets"), ok = inets:start(), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - i("start_httpd -> [application] unset services env"), application:unset_env(inets, services), - i("start_httpd -> stop inets"), ok = inets:stop(), File1 = filename:join(PrivDir, "httpd_apache.conf"), @@ -300,68 +239,46 @@ start_httpd(Config) when is_list(Config) -> file:write(Fd1, "Port 0\r\n"), file:close(Fd1), - i("start_httpd -> [application] load inets"), application:load(inets), - i("start_httpd -> [application] set httpd services env with file"), application:set_env(inets, services, [{httpd, [{file, File1}]}]), - i("start_httpd -> start inets"), ok = inets:start(), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - i("start_httpd -> [application] unset services env"), application:unset_env(inets, services), - i("start_httpd -> stop inets"), ok = inets:stop(), %% OLD format - i("start_httpd -> [application] load inets"), application:load(inets), - i("start_httpd -> [application] set httpd services OLD env"), application:set_env(inets, services, [{httpd, File1}]), - i("start_httpd -> start inets"), ok = inets:start(), (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()), - i("start_httpd -> [application] unset services enc"), application:unset_env(inets, services), - i("start_httpd -> stop inets"), ok = inets:stop(), - - i("start_httpd -> start inets"), ok = inets:start(), - i("start_httpd -> try (and fail) start httpd service - server_name"), {error, {missing_property, server_name}} = inets:start(httpd, [{port, 0}, {server_root, PrivDir}, {document_root, PrivDir}, {bind_address, "localhost"}]), - i("start_httpd -> try (and fail) start httpd service - missing document_root"), {error, {missing_property, document_root}} = inets:start(httpd, [{port, 0}, {server_name, "httpd_test"}, {server_root, PrivDir}, {bind_address, "localhost"}]), - i("start_httpd -> try (and fail) start httpd service - missing server_root"), {error, {missing_property, server_root}} = inets:start(httpd, [{port, 0}, {server_name, "httpd_test"}, {document_root, PrivDir}, {bind_address, "localhost"}]), - i("start_httpd -> try (and fail) start httpd service - missing port"), {error, {missing_property, port}} = inets:start(httpd, HttpdConf), - i("start_httpd -> stop inets"), - ok = inets:stop(), - i("start_httpd -> done"), - ok. - + ok = inets:stop(). %%------------------------------------------------------------------------- start_ftpc(doc) -> - ["Start/stop of ftpc service"]; -start_ftpc(suite) -> - []; + [{doc, "Start/stop of ftpc service"}]; start_ftpc(Config) when is_list(Config) -> process_flag(trap_exit, true), ok = inets:start(), @@ -389,7 +306,7 @@ start_ftpc(Config) when is_list(Config) -> {'EXIT', Pid1, shutdown} -> ok after 100 -> - tsf(stand_alone_not_shutdown) + ct:fail(stand_alone_not_shutdown) end, ok = inets:stop(), ok; @@ -401,15 +318,11 @@ start_ftpc(Config) when is_list(Config) -> throw:{error, not_found} -> {skip, "No available FTP servers"} end. - - %%------------------------------------------------------------------------- -start_tftpd(doc) -> - ["Start/stop of tfpd service"]; -start_tftpd(suite) -> - []; +start_tftpd() -> + [{doc, "Start/stop of tfpd service"}]. start_tftpd(Config) when is_list(Config) -> process_flag(trap_exit, true), ok = inets:start(), @@ -441,16 +354,12 @@ start_tftpd(Config) when is_list(Config) -> application:unset_env(inets, services), ok = inets:stop(). - %%------------------------------------------------------------------------- -httpd_reload(doc) -> - ["Reload httpd configuration without restarting service"]; -httpd_reload(suite) -> - []; +httpd_reload() -> + [{doc, "Reload httpd configuration without restarting service"}]. httpd_reload(Config) when is_list(Config) -> process_flag(trap_exit, true), - i("httpd_reload -> starting"), PrivDir = ?config(priv_dir, Config), DataDir = ?config(data_dir, Config), HttpdConf = [{server_name, "httpd_test"}, @@ -458,23 +367,18 @@ httpd_reload(Config) when is_list(Config) -> {document_root, PrivDir}, {bind_address, "localhost"}], - i("httpd_reload -> start inets"), - ok = inets:start(), test_server:sleep(5000), - i("httpd_reload -> inets started - start httpd service"), - {ok, Pid0} = inets:start(httpd, [{port, 0}, {ipfamily, inet} | HttpdConf]), + {ok, Pid0} = inets:start(httpd, [{port, 0}, + {ipfamily, inet} | HttpdConf]), test_server:sleep(5000), - i("httpd_reload -> httpd service started (~p) - get port", [Pid0]), [{port, Port0}] = httpd:info(Pid0, [port]), test_server:sleep(5000), - i("httpd_reload -> Port: ~p - get document root", [Port0]), [{document_root, PrivDir}] = httpd:info(Pid0, [document_root]), test_server:sleep(5000), - i("httpd_reload -> document root: ~p - reload config", [PrivDir]), ok = httpd:reload_config([{port, Port0}, {ipfamily, inet}, {server_name, "httpd_test"}, @@ -482,11 +386,8 @@ httpd_reload(Config) when is_list(Config) -> {document_root, DataDir}, {bind_address, "localhost"}], non_disturbing), test_server:sleep(5000), - io:format("~w:~w:httpd_reload - reloaded - get document root~n", [?MODULE, ?LINE]), - [{document_root, DataDir}] = httpd:info(Pid0, [document_root]), test_server:sleep(5000), - i("httpd_reload -> document root: ~p - reload config", [DataDir]), ok = httpd:reload_config([{port, Port0}, {ipfamily, inet}, {server_name, "httpd_test"}, @@ -539,23 +440,5 @@ httpd_reload(Config) when is_list(Config) -> ok = inets:stop(httpd, Pid1), application:unset_env(inets, services), - ok = inets:stop(), - i("httpd_reload -> starting"), - ok. - - -tsf(Reason) -> - test_server:fail(Reason). - -tsp(F) -> - tsp(F, []). -tsp(F, A) -> - Timestamp = inets_lib:formated_timestamp(), - test_server:format("** ~s ** ~p ~p:" ++ F ++ "~n", [Timestamp, self(), ?MODULE | A]). - -i(F) -> - i(F, []). + ok = inets:stop(). -i(F, A) -> - Timestamp = inets_lib:formated_timestamp(), - io:format("*** ~s ~w:" ++ F ++ "~n", [Timestamp, ?MODULE | A]). -- cgit v1.2.3 From 628553c2946649ef1715feacc05e8f75d38ef2e3 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 8 Sep 2015 16:39:38 +0200 Subject: inets: Add test suite for socket_wrap feature On Linux systems a socket may be opened pre starting Erlang and then passed to Erlangs ftpd or httpd daemon. This is useful as the wrap program can open a privileged port and Erlang does not have to be run as root. The test program will only open a random port, but it exercises the code so that the feature will remain intact. --- lib/inets/test/Makefile | 7 +- lib/inets/test/inets_socketwrap_SUITE.erl | 154 ++++++++++++ .../test/inets_socketwrap_SUITE_data/Makefile.src | 39 ++++ .../setuid_socket_wrap.c | 259 +++++++++++++++++++++ lib/inets/test/inets_test_lib.erl | 9 + 5 files changed, 465 insertions(+), 3 deletions(-) create mode 100644 lib/inets/test/inets_socketwrap_SUITE.erl create mode 100644 lib/inets/test/inets_socketwrap_SUITE_data/Makefile.src create mode 100644 lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c (limited to 'lib') diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile index cae77a05f3..607ec7c182 100644 --- a/lib/inets/test/Makefile +++ b/lib/inets/test/Makefile @@ -174,7 +174,8 @@ MODULES = \ inets_appup_test \ tftp_test_lib \ tftp_SUITE \ - uri_SUITE + uri_SUITE \ + inets_socketwrap_SUITE EBIN = . @@ -203,7 +204,7 @@ INETS_FILES = inets.config $(INETS_SPECS) # inets_ftp_suite \ # inets_tftp_suite -INETS_DATADIRS = inets_SUITE_data inets_sup_SUITE_data +INETS_DATADIRS = inets_SUITE_data inets_socketwrap_SUITE_data HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data HTTPC_DATADIRS = httpc_SUITE_data httpc_proxy_SUITE_data FTP_DATADIRS = ftp_SUITE_data @@ -250,7 +251,7 @@ ERL_COMPILE_FLAGS += \ # 1) INETS_PRIV_DIR must be created # ---------------------------------------------------- -tests debug opt: $(BUILDTARGET) +tests debug opt: $(BUILDTARGET) targets: $(TARGET_FILES) diff --git a/lib/inets/test/inets_socketwrap_SUITE.erl b/lib/inets/test/inets_socketwrap_SUITE.erl new file mode 100644 index 0000000000..cfbda3ccf5 --- /dev/null +++ b/lib/inets/test/inets_socketwrap_SUITE.erl @@ -0,0 +1,154 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% +-module(inets_socketwrap_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include("inets_test_lib.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + [start_httpd_fd, start_tftpd_fd]. + +init_per_suite(Config) -> + case os:type() of + {unix, linux} -> + Config; + _ -> + {skip, linux_feature} + end. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +init_per_testcase(Case, Config) -> + end_per_testcase(Case, Config), + Config. + +end_per_testcase(_, Config) -> + inets:stop(), + Config. + +%%------------------------------------------------------------------------- +start_httpd_fd() -> + [{doc, "Start/stop of httpd service with socket wrapper"}]. +start_httpd_fd(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + DataDir = ?config(data_dir, Config), + HttpdConf = [{port, 80}, {ipfamily, inet}, + {server_name, "httpd_fd_test"}, {server_root, PrivDir}, + {document_root, PrivDir}, {bind_address, any}], + case setup_node_info(node()) of + {skip, _} = Skip -> + Skip; + {Node, NodeArg} -> + InetPort = inets_test_lib:inet_port(node()), + ct:pal("Node: ~p Port ~p~n", [Node, InetPort]), + Wrapper = filename:join(DataDir, "setuid_socket_wrap"), + Cmd = Wrapper ++ + " -s -httpd_80,0:" ++ integer_to_list(InetPort) + ++ " -p " ++ os:find_executable("erl") ++ + " -- " ++ NodeArg, + ct:pal("cmd: ~p~n", [Cmd]), + case open_port({spawn, Cmd}, [stderr_to_stdout]) of + Port when is_port(Port) -> + wait_node_up(Node, 10), + ct:pal("~p", [rpc:call(Node, init, get_argument, [httpd_80])]), + ok = rpc:call(Node, inets, start, []), + {ok, Pid} = rpc:call(Node, inets, start, [httpd, HttpdConf]), + [{port, InetPort}] = rpc:call(Node, httpd, info, [Pid, [port]]), + rpc:call(Node, erlang, halt, []); + _ -> + ct:fail(open_port_failed) + end + end. +%%------------------------------------------------------------------------- +start_tftpd_fd() -> + [{doc, "Start/stop of tfpd service with socket wrapper"}]. +start_tftpd_fd(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + case setup_node_info(node()) of + {skip, _} = Skip -> + Skip; + {Node, NodeArg} -> + InetPort = inets_test_lib:inet_port(node()), + ct:pal("Node: ~p~n", [Node]), + Wrapper = filename:join(DataDir, "setuid_socket_wrap"), + Cmd = Wrapper ++ + " -s -tftpd_69,0:" ++ integer_to_list(InetPort) + ++ " -p " ++ os:find_executable("erl") ++ + " -- " ++ NodeArg, + ct:pal("cmd: ~p~n", [Cmd]), + case open_port({spawn, Cmd}, [stderr_to_stdout]) of + Port when is_port(Port) -> + wait_node_up(Node, 10), + ct:pal("~p", [rpc:call(Node, init, get_argument, [tftpd_69])]), + ok = rpc:call(Node, inets, start, []), + {ok, Pid} = rpc:call(Node, inets, start, + [tftpd,[{host, "localhost"}]]), + {ok, Info} = rpc:call(Node, tftp, info, [Pid]), + {value,{port, InetPort}} = lists:keysearch(port, 1, Info), + rpc:call(Node, erlang, halt, []); + _ -> + ct:fail(open_port_failed) + end + end. +%%------------------------------------------------------------------------- +%% Internal functions +%%------------------------------------------------------------------------- +setup_node_info(nonode@nohost) -> + {skip, needs_distributed_node}; +setup_node_info(Node) -> + Static = "-detached -noinput", + Name = "inets_fd_test", + NameSw = case net_kernel:longnames() of + false -> "-sname "; + _ -> "-name " + end, + StrNode = + Static ++ " " + ++ NameSw ++ " " ++ Name ++ " " + ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()), + [_, Location] = string:tokens(atom_to_list(Node), "$@"), + TestNode = Name ++ "@" ++ Location, + {list_to_atom(TestNode), StrNode}. + +wait_node_up(Node, 0) -> + ct:fail({failed_to_start_node, Node}); +wait_node_up(Node, N) -> + ct:pal("(Node ~p: net_adm:ping(~p)~n", [node(), Node]), + case net_adm:ping(Node) of + pong -> + ok; + pang -> + ct:sleep(5000), + wait_node_up(Node, N-1) + end. diff --git a/lib/inets/test/inets_socketwrap_SUITE_data/Makefile.src b/lib/inets/test/inets_socketwrap_SUITE_data/Makefile.src new file mode 100644 index 0000000000..0933815b58 --- /dev/null +++ b/lib/inets/test/inets_socketwrap_SUITE_data/Makefile.src @@ -0,0 +1,39 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2015-2015. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# %CopyrightEnd% +# + +CC = @CC@ +LD = @LD@ +CFLAGS = @CFLAGS@ +CROSSLDFLAGS = @CROSSLDFLAGS@ + +PROGS = setuid_socket_wrap@exe@ + +.PHONY: all +@IFEQ@ (@os@, linux-gnu) +all: $(PROGS) +@ELSE@ +all: +@ENDIF@ + +setuid_socket_wrap@exe@: setuid_socket_wrap@obj@ + $(LD) $(CROSSLDFLAGS) -o setuid_socket_wrap setuid_socket_wrap@obj@ @LIBS@ + +setuid_socket_wrap@obj@: setuid_socket_wrap.c + $(CC) -c $(CFLAGS) -o setuid_socket_wrap@obj@ setuid_socket_wrap.c diff --git a/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c b/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c new file mode 100644 index 0000000000..b28f6b1c08 --- /dev/null +++ b/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c @@ -0,0 +1,259 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1999-2009. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ +/* + * setuid_socket_wrap.c + * + * ./a.out [-s [tag,][addr]:[port]]* [-d [tag,][addr]:[port]]* + * [-r [tag,]proto]* [-p erl_path]* -- program args + * + * Where: -s = stream socket, -d datagram socket and -r means raw socket. + * + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +struct sock_list { + struct sock_list *next; + int fd; + int type; + int protocol; + struct sockaddr_in addr; + char *arg; +}; + +int parse_addr(addr, str) + struct sockaddr_in *addr; + char *str; +{ + int port = 0; + char *cp; + struct hostent *hp; + struct servent *se; + + if ((cp = strrchr(str, (int)':')) != NULL) + *cp++ = '\0'; + if (cp) { + if (!isdigit((int)cp[0])) { + if ((se = getservbyname(cp, "tcp")) != NULL) { + port = ntohs(se->s_port); + } else { + fprintf(stderr, "unknown port %s\n", cp); + return -1; + } + } else { + port = atoi(cp); + } + } + if (port < 0 || port > 0xffff) { + fprintf(stderr, "bad port number %d\n", port); + return -1; + } + + bzero(addr, sizeof(*addr)); + addr->sin_family = AF_INET; + addr->sin_port = htons(port); + if (*str == '\000') { + addr->sin_addr.s_addr = INADDR_ANY; + } else { + if ((addr->sin_addr.s_addr = inet_addr(str)) == INADDR_NONE) { + if ((hp = gethostbyname(str)) == NULL) { + fprintf(stderr, "\"%s\" unknown host or address!\n", str); + return -1; + } else { + bcopy(hp->h_addr_list[0], &addr->sin_addr.s_addr,hp->h_length); + } + } + } + return 0; +} + +struct sock_list *new_entry(type, argstr) + int type; + char *argstr; +{ + struct sock_list *sle; + char *cp; + + sle = (struct sock_list *)malloc(sizeof(struct sock_list)); + if (!sle) + return NULL; + sle->next = NULL; + sle->fd = -1; + + if ((cp = strchr(argstr, (int)',')) != NULL) { + *cp++ = '\0'; + sle->arg = argstr; + argstr = cp; + } else { + sle->arg = "-fd"; + } + sle->type = type; + switch (type) { + case SOCK_RAW: { + struct protoent *pe; + pe = getprotobyname(argstr); + if (!pe) { + fprintf(stderr, "Unknown protocol: %s\n", argstr); + free(sle); + return NULL; + } + sle->protocol = pe->p_proto; + break; + } + case SOCK_STREAM: + case SOCK_DGRAM: + sle->protocol = 0; + if (parse_addr(&sle->addr, argstr) < 0) { + free(sle); + return NULL; + } + break; + } + return sle; +} + +int open_socket(sle) + struct sock_list *sle; +{ + sle->fd = socket(AF_INET, sle->type, sle->protocol); + if (sle->fd < 0) { + perror("socket"); + return -1; + } + if (sle->type != SOCK_RAW) { +#if 0 + printf("binding fd %d to %s:%d\n", sle->fd, + inet_ntoa(sle->addr.sin_addr), ntohs(sle->addr.sin_port)); +#endif + if (bind(sle->fd, (struct sockaddr *)&sle->addr, sizeof(sle->addr))<0){ + perror("bind"); + close(sle->fd); + return -1; + } + } + return sle->fd; +} + +int main(argc, argv) + int argc; + char *argv[]; +{ + struct sock_list *sl = NULL, *sltmp = NULL; + int count = 0; + int c; + char *run_prog = NULL; + + while ((c = getopt(argc, argv, "s:d:r:p:")) != EOF) + switch (c) { + case 's': + sltmp = new_entry(SOCK_STREAM, optarg); + if (!sltmp) { + exit(1); + } + sltmp->next = sl; + sl = sltmp; + count++; + break; + case 'd': + sltmp = new_entry(SOCK_DGRAM, optarg); + if (!sltmp) { + exit(1); + } + sltmp->next = sl; + sl = sltmp; + count++; + break; + case 'r': + sltmp = new_entry(SOCK_RAW, optarg); + if (!sltmp) { + exit(1); + } + sltmp->next = sl; + sl = sltmp; + count++; + break; + case 'p': + run_prog = optarg; + break; + default: + exit(1); + } + argc -= optind; + argv += optind; + + for(sltmp = sl; sltmp != NULL; sltmp = sltmp->next) + if (open_socket(sltmp) < 0) { + fprintf(stderr, "failed to create socket!\n"); + exit(1); + } + + setuid(getuid()); + + { + int i; + char **newargv; + char *run_prog_name; + + newargv = (char **)malloc((1 + 2*count + argc + 1) * sizeof(char*)); + + if ((run_prog_name = strrchr(run_prog, (int)'/')) == NULL) + run_prog_name = run_prog; + else + run_prog_name++; + + i = 0; + newargv[i++] = run_prog_name; + + for (; argc; argc--, argv++, i++) + newargv[i] = *argv; + for(sltmp = sl; sltmp != NULL; ) { + char *fd_str = (char *)malloc(8); + if (!fd_str) exit(1); + sprintf(fd_str, "%d", sltmp->fd); + if (sltmp->arg && *(sltmp->arg)) + newargv[i++] = sltmp->arg; + newargv[i++] = fd_str; + sl = sltmp; + sltmp = sltmp->next; + free(sl); + } + newargv[i] = (char *)NULL; + execv(run_prog, newargv); + perror("exec"); + exit(1); + } + exit(0); +} diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index b471dcf784..f1185f7574 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -563,3 +563,12 @@ stop_apps(Apps) -> application:stop(App) end, Apps). +inet_port(Node) -> + {Port, Socket} = do_inet_port(Node), + rpc:call(Node, gen_tcp, close, [Socket]), + Port. + +do_inet_port(Node) -> + {ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]), + {ok, Port} = rpc:call(Node, inet, port, [Socket]), + {Port, Socket}. -- cgit v1.2.3 From 027726da70f31541bd3c4813bf464489a808ae91 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 10 Sep 2015 10:09:28 +0200 Subject: mnesia: Improve index updates There is no need to update the index table if a record is updated in non indexed field. This removes one timing glitch where dirty_index_read would return an empty list for records that where updated. There is still an issue with dirty_index_read when updates are made to the index field, it have been reduced but the real table updates are made after the index table references have been added. Originally reported by Nick Marino in erl-questions mailing list, thanks. --- lib/mnesia/src/mnesia_index.erl | 27 +++++++++++++++++---------- lib/mnesia/test/mnesia_dirty_access_test.erl | 19 ++++++++++++++++++- 2 files changed, 35 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl index 81ed5a8f1a..0c882c0df6 100644 --- a/lib/mnesia/src/mnesia_index.erl +++ b/lib/mnesia/src/mnesia_index.erl @@ -70,17 +70,24 @@ add_index(Index, Tab, Key, Obj, Old) -> add_index2([{Pos, Ixt} |Tail], bag, Tab, K, Obj, OldRecs) -> db_put(Ixt, {element(Pos, Obj), K}), add_index2(Tail, bag, Tab, K, Obj, OldRecs); -add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs) -> +add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs0) -> %% Remove old tuples in index if Tab is updated - case OldRecs of - undefined -> - Old = mnesia_lib:db_get(Tab, K), - del_ixes(Ixt, Old, Pos, K); - Old -> - del_ixes(Ixt, Old, Pos, K) - end, - db_put(Ixt, {element(Pos, Obj), K}), - add_index2(Tail, Type, Tab, K, Obj, OldRecs); + OldRecs1 = case OldRecs0 of + undefined -> mnesia_lib:db_get(Tab, K); + _ -> OldRecs0 + end, + IdxVal = element(Pos, Obj), + case [Old || Old <- OldRecs1, element(Pos, Old) =/= IdxVal] of + [] when OldRecs1 =:= [] -> %% Write + db_put(Ixt, {element(Pos, Obj), K}), + add_index2(Tail, Type, Tab, K, Obj, OldRecs0); + [] -> %% when OldRecs1 =/= [] Update without modifying index field + add_index2(Tail, Type, Tab, K, Obj, OldRecs0); + OldRecs -> %% Update + db_put(Ixt, {element(Pos, Obj), K}), + del_ixes(Ixt, OldRecs, Pos, K), + add_index2(Tail, Type, Tab, K, Obj, OldRecs0) + end; add_index2([], _, _Tab, _K, _Obj, _) -> ok. delete_index(Index, Tab, K) -> diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl index 89aff2b3b8..0d57e5a1b1 100644 --- a/lib/mnesia/test/mnesia_dirty_access_test.erl +++ b/lib/mnesia/test/mnesia_dirty_access_test.erl @@ -401,9 +401,26 @@ dirty_index_read(Config, Storage) -> ?match({'EXIT', _}, mnesia:dirty_index_read(Tab, 2, BadValPos)), ?match({'EXIT', _}, mnesia:dirty_index_read(foo, 2, ValPos)), ?match({'EXIT', _}, mnesia:dirty_index_read([], 2, ValPos)), - + + mnesia:dirty_write({Tab, 5, 1}), + ?match(ok, index_read_loop(Tab, 0)), + ?verify_mnesia(Nodes, []). + +index_read_loop(Tab, N) when N =< 1000 -> + spawn_link(fun() -> + mnesia:transaction(fun() -> mnesia:write({Tab, 5, 1}) end) + end), + case mnesia:dirty_match_object({Tab, '_', 1}) of + [{Tab, 5, 1}] -> + index_read_loop(Tab, N+1); + Other -> {N, Other} + end; +index_read_loop(_, _) -> + ok. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From 60a6858785f49357757691956295dbcb304c0508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 31 Aug 2015 12:36:36 +0200 Subject: compile_SUITE: Add test of warnings Make sure that all warnings produced when compiling the test suite contains filenames and line numbers. --- lib/compiler/test/compile_SUITE.erl | 44 +++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index df401ccc2b..cbdd9ce8cd 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -31,7 +31,9 @@ other_output/1, encrypted_abstr/1, bad_record_use1/1, bad_record_use2/1, strict_record/1, missing_testheap/1, cover/1, env/1, core/1, asm/1, - sys_pre_attributes/1, dialyzer/1]). + sys_pre_attributes/1, dialyzer/1, + warnings/1 + ]). -export([init/3]). @@ -48,7 +50,7 @@ all() -> other_output, encrypted_abstr, {group, bad_record_use}, strict_record, missing_testheap, cover, env, core, asm, - sys_pre_attributes, dialyzer]. + sys_pre_attributes, dialyzer, warnings]. groups() -> [{bad_record_use, [], @@ -895,6 +897,44 @@ dialyzer(Config) -> [{a,b,c}] = M:M(), ok. + +%% Test that warnings contain filenames and line numbers. +warnings(_Config) -> + TestDir = filename:dirname(code:which(?MODULE)), + Files = filelib:wildcard(filename:join(TestDir, "*.erl")), + test_lib:p_run(fun do_warnings/1, Files). + +do_warnings(F) -> + {ok,_,_,Ws} = compile:file(F, [binary,bin_opt_info,return]), + do_warnings_1(Ws, F). + +do_warnings_1([{"no_file",Ws}|_], F) -> + io:format("~s:\nMissing file for warnings: ~p\n", + [F,Ws]), + error; +do_warnings_1([{Name,Ws}|T], F) -> + case filename:extension(Name) of + ".erl" -> + do_warnings_2(Ws, T, F); + _ -> + io:format("~s:\nNo .erl extension\n", [F]), + error + end; +do_warnings_1([], _) -> ok. + +do_warnings_2([{Int,_,_}=W|T], Next, F) -> + if + is_integer(Int) -> + do_warnings_2(T, Next, F); + true -> + io:format("~s:\nMissing line number: ~p\n", + [F,W]), + error + end; +do_warnings_2([], Next, F) -> + do_warnings_1(Next, F). + + %%% %%% Utilities. %%% -- cgit v1.2.3 From 05a9fe4e1176388c761ca7be9321608c3ba48810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 1 Sep 2015 08:31:25 +0200 Subject: io_SUITE: Eliminate warnings for unused variables --- lib/stdlib/test/io_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 5df09b6a79..9147ec4548 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -2225,7 +2225,7 @@ compile_file(File, Text, Config) -> after ok %file:delete(Fname) end. -io_lib_width_too_small(Config) -> +io_lib_width_too_small(_Config) -> "**" = lists:flatten(io_lib:format("~2.3w", [3.14])), "**" = lists:flatten(io_lib:format("~2.5w", [3.14])), ok. @@ -2271,7 +2271,7 @@ writes(N, F1) -> file:write(F1, "hello\n"), writes(N - 1, F1). -format_string(Config) -> +format_string(_Config) -> %% All but padding is tested by fmt/2. "xxxxxxsssx" = fmt("~10.4.xs", ["sss"]), "xxxxxxsssx" = fmt("~10.4.*s", [$x, "sss"]), -- cgit v1.2.3 From 3a9a34e581494451cc798911477f3b7bc81e3492 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 9 Sep 2015 14:51:11 +0200 Subject: Add test for "Fix cover output file" If a module includes eunit.hrl, a parse transform adds the function test/0 on line 0 in the module. A bug in OTP-18.0 caused cover:analyse_to_file/1 to fail to insert cover data in the output file when line 0 existed in the cover data table. The bug is corrected by the commit "Fix cover output file". This commit adds a test which checks that the bug is not introduced again. --- lib/tools/test/cover_SUITE.erl | 24 ++++++++++++++++++++-- .../include_eunit_hrl/cover_inc_eunit.erl | 6 ++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 lib/tools/test/cover_SUITE_data/include_eunit_hrl/cover_inc_eunit.erl (limited to 'lib') diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl index 931e3e2cfa..25c9317608 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.erl @@ -31,7 +31,7 @@ otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1, otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1, otp_10979_hanging_node/1, compile_beam_opts/1, eep37/1, - analyse_no_beam/1]). + analyse_no_beam/1, line_0/1]). -export([do_coverage/1]). @@ -55,7 +55,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273, otp_8340,otp_8188,compile_beam_opts,eep37, - analyse_no_beam], + analyse_no_beam, line_0], StartStop = [start, compile, analyse, misc, stop, distribution, reconnect, die_and_reconnect, dont_reconnect_after_stop, stop_node_after_disconnect, @@ -1727,6 +1727,26 @@ analyse_no_beam(Config) when is_list(Config) -> ok = file:set_cwd(Cwd), ok. +%% When including eunit.hrl, a parse transform adds the function +%% test/0 to line 0 in your module. A bug in OTP-18.0 caused +%% cover:analyse_to_file/1 to fail to insert cover data in the output +%% file in this situation. The test below tests that this bug is +%% corrected. +line_0(Config) -> + ok = file:set_cwd(filename:join(?config(data_dir, Config), + "include_eunit_hrl")), + {ok, cover_inc_eunit} = compile:file(cover_inc_eunit,[debug_info]), + {ok, cover_inc_eunit} = cover:compile_beam(cover_inc_eunit), + {ok, CovOut} = cover:analyse_to_file(cover_inc_eunit), + + {ok,Bin} = file:read_file(CovOut), + Match = <<"0..| ok.\n">>, % "0.." is missing when bug is there + S = byte_size(Bin)-byte_size(Match), + <<_:S/binary,Match/binary>> = Bin, + ok. + + + %%--Auxiliary------------------------------------------------------------ analyse_expr(Expr, Config) -> diff --git a/lib/tools/test/cover_SUITE_data/include_eunit_hrl/cover_inc_eunit.erl b/lib/tools/test/cover_SUITE_data/include_eunit_hrl/cover_inc_eunit.erl new file mode 100644 index 0000000000..c1fe7939d2 --- /dev/null +++ b/lib/tools/test/cover_SUITE_data/include_eunit_hrl/cover_inc_eunit.erl @@ -0,0 +1,6 @@ +-module(cover_inc_eunit). +-compile(export_all). +-include_lib("eunit/include/eunit.hrl"). + +func() -> + ok. -- cgit v1.2.3 From 33b2cc1996883569b8afbc7cab8a535aa168ae1b Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 10 Sep 2015 10:56:30 +0200 Subject: Fix doc for return value of gen_fsm:reply/2 --- lib/stdlib/doc/src/gen_fsm.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index 5f7b5a3437..a8d7fadeb4 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -339,11 +339,12 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 - reply(Caller, Reply) -> true + reply(Caller, Reply) -> Result Send a reply to a caller. Caller - see below Reply = term() + Result = term()

This function can be used by a gen_fsm to explicitly send a @@ -358,6 +359,8 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 which will be given back to the client as the return value of sync_send_event/2,3 or sync_send_all_state_event/2,3.

+

The return value Result is not further defined, and + should always be ignored.

-- cgit v1.2.3 From ae57bf9b81a996889676c01656445824cd4b3fa7 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Thu, 10 Sep 2015 14:56:22 +0200 Subject: Update appup for 18.1 OTP-12947 strict_mbit service_opt() OTP-12969 diameter_watchdog function_clause No load order requirements. --- lib/diameter/src/diameter.appup.src | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index 788ea790fa..b77043d983 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -52,8 +52,10 @@ {load_module, diameter_lib}, {load_module, diameter_peer}, {load_module, diameter_reg}, + {load_module, diameter_traffic}, {load_module, diameter_service}, {load_module, diameter_sync}, + {load_module, diameter}, {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, @@ -89,8 +91,10 @@ {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc6733}, + {load_module, diameter}, {load_module, diameter_sync}, {load_module, diameter_service}, + {load_module, diameter_traffic}, {load_module, diameter_reg}, {load_module, diameter_peer}, {load_module, diameter_lib}, -- cgit v1.2.3 From 52595d8da8bc43da6848075f869111e0de1dceb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Sep 2015 15:44:45 +0200 Subject: core_lib: Remove previously deprecated functions --- lib/compiler/src/core_lib.erl | 38 +------------------------------------- lib/stdlib/src/otp_internal.erl | 10 +++++----- 2 files changed, 6 insertions(+), 42 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/core_lib.erl b/lib/compiler/src/core_lib.erl index 3abb520485..839c736ff2 100644 --- a/lib/compiler/src/core_lib.erl +++ b/lib/compiler/src/core_lib.erl @@ -21,52 +21,16 @@ -module(core_lib). --deprecated({get_anno,1,next_major_release}). --deprecated({set_anno,2,next_major_release}). --deprecated({is_literal,1,next_major_release}). --deprecated({is_literal_list,1,next_major_release}). --deprecated({literal_value,1,next_major_release}). - --export([get_anno/1,set_anno/2]). --export([is_literal/1,is_literal_list/1]). --export([literal_value/1]). -export([make_values/1]). -export([is_var_used/2]). -include("core_parse.hrl"). -%% -%% Generic get/set annotation that should be used only with cerl() structures. -%% --spec get_anno(cerl:cerl()) -> term(). - -get_anno(C) -> cerl:get_ann(C). - --spec set_anno(cerl:cerl(), term()) -> cerl:cerl(). - -set_anno(C, A) -> cerl:set_ann(C, A). - --spec is_literal(cerl:cerl()) -> boolean(). - -is_literal(Cerl) -> - cerl:is_literal(cerl:fold_literal(Cerl)). - --spec is_literal_list([cerl:cerl()]) -> boolean(). - -is_literal_list(Es) -> lists:all(fun is_literal/1, Es). - -%% Return the value of LitExpr. --spec literal_value(cerl:c_literal() | cerl:c_binary() | - cerl:c_map() | cerl:c_cons() | cerl:c_tuple()) -> term(). - -literal_value(Cerl) -> - cerl:concrete(cerl:fold_literal(Cerl)). - %% Make a suitable values structure, expr or values, depending on Expr. -spec make_values([cerl:cerl()] | cerl:cerl()) -> cerl:cerl(). make_values([E]) -> E; -make_values([H|_]=Es) -> #c_values{anno=get_anno(H),es=Es}; +make_values([H|_]=Es) -> #c_values{anno=cerl:get_ann(H),es=Es}; make_values([]) -> #c_values{es=[]}; make_values(E) -> E. diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 2d77888512..e8faecb41f 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -586,16 +586,16 @@ obsolete_1(asn1rt, utf8_list_to_binary, 1) -> %% Added in OTP 18. obsolete_1(core_lib, get_anno, 1) -> - {deprecated,{cerl,get_ann,1}}; + {removed,{cerl,get_ann,1},"19"}; obsolete_1(core_lib, set_anno, 2) -> - {deprecated,{cerl,set_ann,2}}; + {removed,{cerl,set_ann,2},"19"}; obsolete_1(core_lib, is_literal, 1) -> - {deprecated,{cerl,is_literal,1}}; + {removed,{cerl,is_literal,1},"19"}; obsolete_1(core_lib, is_literal_list, 1) -> - {deprecated,"deprecated; use lists:all(fun cerl:is_literal/1, L)" + {removed,"removed; use lists:all(fun cerl:is_literal/1, L)" " instead"}; obsolete_1(core_lib, literal_value, 1) -> - {deprecated,{core_lib,concrete,1}}; + {removed,{core_lib,concrete,1},"19"}; obsolete_1(erl_scan, set_attribute, 3) -> {deprecated, "deprecated (will be removed in OTP 19); use erl_anno:set_line/2 instead"}; -- cgit v1.2.3 From 16b0a43accfa24d623b341876a9c27ff33235914 Mon Sep 17 00:00:00 2001 From: Yuki Ito Date: Fri, 24 Jul 2015 13:51:12 +0900 Subject: Fix public_key doc --- lib/public_key/doc/src/public_key.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 209de2bdf7..b247618efc 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -498,13 +498,13 @@ pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} Performs a basic path validation according to RFC 5280. - TrustedCert = #'OTPCertificate'{} | der_encode() | atom() + TrustedCert = #'OTPCertificate'{} | der_encoded() | atom() Normally a trusted certificate, but it can also be a path-validation error that can be discovered while constructing the input to this function and that is to be run through the verify_fun. Examples are unknown_ca and selfsigned_peer. - CertChain = [der_encode()] + CertChain = [der_encoded()] A list of DER-encoded certificates in trust order ending with the peer certificate. Options = proplists:proplist() PublicKeyInfo = {?'rsaEncryption' | ?'id-dsa', -- cgit v1.2.3 From e889cb0381be081891c530bbf04c72797042455b Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 11 Sep 2015 12:07:21 +0200 Subject: ssh: increased max number of algorithms --- lib/ssh/src/ssh_transport.hrl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index d962b1111f..96ab1bb668 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -30,7 +30,7 @@ -define(DEFAULT_CLIENT_VERSION, {2, 0}). -define(DEFAULT_SERVER_VERSION, {2, 0}). --define(MAX_NUM_ALGORITHMS, 100). +-define(MAX_NUM_ALGORITHMS, 200). -define(DEFAULT_DH_GROUP_MIN, 1024). -define(DEFAULT_DH_GROUP_NBITS, 6144). -- cgit v1.2.3 From 9ca2503cbbc7247108278ff2f5b9fe2b37450833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 1 Sep 2015 08:45:28 +0200 Subject: io_SUITE: Add test for printing of maps --- lib/stdlib/test/io_SUITE.erl | 99 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 9147ec4548..a290674524 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -32,7 +32,8 @@ printable_range/1, io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1, otp_10836/1, io_lib_width_too_small/1, - io_with_huge_message_queue/1, format_string/1]). + io_with_huge_message_queue/1, format_string/1, + maps/1]). -export([pretty/2]). @@ -73,7 +74,7 @@ all() -> printable_range, io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836, io_lib_width_too_small, io_with_huge_message_queue, - format_string]. + format_string, maps]. groups() -> []. @@ -2276,3 +2277,97 @@ format_string(_Config) -> "xxxxxxsssx" = fmt("~10.4.xs", ["sss"]), "xxxxxxsssx" = fmt("~10.4.*s", [$x, "sss"]), ok. + +maps(_Config) -> + %% Note that order in which a map is printed is arbitrary. In + %% practice, small maps (non-HAMT) are printed in key order, but + %% the breakpoint for creating big maps (HAMT) is lower in the + %% debug-compiled run-time system than in the optimized run-time + %% system. + %% + %% Therefore, play it completely safe by not assuming any order + %% in a map with more than one element. + + "#{}" = fmt("~w", [#{}]), + "#{a=>b}" = fmt("~w", [#{a=>b}]), + re_fmt(<<"#\\{(a=>b|c=>d),[.][.][.]=>[.][.][.]\\}">>, + "~W", [#{a=>b,c=>d},2]), + re_fmt(<<"#\\{(a=>b|c=>d|e=>f),[.][.][.]=>[.][.][.],[.][.][.]\\}">>, + "~W", [#{a=>b,c=>d,e=>f},2]), + + "#{}" = fmt("~p", [#{}]), + "#{a => b}" = fmt("~p", [#{a=>b}]), + "#{...}" = fmt("~P", [#{a=>b},1]), + re_fmt(<<"#\\{(a => b|c => d),[.][.][.]\\}">>, + "~P", [#{a=>b,c=>d},2]), + re_fmt(<<"#\\{(a => b|c => d|e => f),[.][.][.]\\}">>, + "~P", [#{a=>b,c=>d,e=>f},2]), + + List = [{I,I*I} || I <- lists:seq(1, 20)], + Map = maps:from_list(List), + + "#{...}" = fmt("~P", [Map,1]), + + %% Print a map and parse it back to a map. + S = fmt("~p\n", [Map]), + io:format("~p\n", [S]), + Map = parse_map(S), + + %% Smoke test of a map as key. + MapAsKey = #{Map => "value"}, + io:format("~s\n", [fmt("~p", [MapAsKey])]), + ok. + +re_fmt(Pattern, Format, Args) -> + S = list_to_binary(fmt(Format, Args)), + case re:run(S, Pattern, [{capture,none}]) of + nomatch -> + io:format("Pattern: ~s", [Pattern]), + io:format("Result: ~s", [S]), + ?t:fail(); + match -> + ok + end. + +%% Parse a map consisting of integer keys and values. +parse_map(S0) -> + S1 = parse_expect(S0, "#{"), + {M,S2} = parse_map_1(S1), + S = parse_expect(S2, "}"), + S = "", + M. + +parse_map_1(S0) -> + {Key,S1} = parse_number(S0), + S2 = parse_expect(S1, "=>"), + {Val,S3} = parse_number(S2), + case S3 of + ","++S4 -> + S5 = parse_skip_ws(S4), + {Map,S} = parse_map_1(S5), + {Map#{Key=>Val},S}; + S -> + {#{Key=>Val},S} + end. + +parse_number(S) -> + parse_number(S, none). + +parse_number([C|S], Acc0) when $0 =< C, C =< $9 -> + Acc = case Acc0 of + none -> 0; + _ when is_integer(Acc0) -> Acc0 + end, + parse_number(S, Acc*10+C-$0); +parse_number(S, Acc) -> + {Acc,parse_skip_ws(S)}. + +parse_expect([H|T1], [H|T2]) -> + parse_expect(T1, T2); +parse_expect(S, []) -> + parse_skip_ws(S). + +parse_skip_ws([C|S]) when C =< $\s -> + parse_skip_ws(S); +parse_skip_ws(S) -> + S. -- cgit v1.2.3 From 9d0f9ed8b6a055e069e26f77622985cd434378f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 1 Sep 2015 09:52:07 +0200 Subject: io_SUITE: Speed up test for bad +pc option Move the test for a bad +pc option to its own test case for cleanliness. Use the os:cmd/1 function to avoid the annyoying 30 seconds time-out in test_server:start_node/3. --- lib/stdlib/test/io_SUITE.erl | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index a290674524..8a6b2725af 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -29,7 +29,7 @@ manpage/1, otp_6708/1, otp_7084/1, otp_7421/1, io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1, io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1, - printable_range/1, + printable_range/1, bad_printable_range/1, io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1, otp_10836/1, io_lib_width_too_small/1, io_with_huge_message_queue/1, format_string/1, @@ -71,7 +71,7 @@ all() -> manpage, otp_6708, otp_7084, otp_7421, io_lib_collect_line_3_wb, cr_whitespace_in_string, io_fread_newlines, otp_8989, io_lib_fread_literal, - printable_range, + printable_range, bad_printable_range, io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836, io_lib_width_too_small, io_with_huge_message_queue, format_string, maps]. @@ -2063,8 +2063,6 @@ printable_range(Suite) when is_list(Suite) -> [{args, " +pclatin1 -pa " ++ Pa}]), unicode = rpc:call(UNode,io,printable_range,[]), latin1 = rpc:call(LNode,io,printable_range,[]), - {error, _} = test_server:start_node(printable_range_unnicode, slave, - [{args, " +pcunnicode -pa " ++ Pa}]), PrettyOptions = [{column,1}, {line_length,109}, {depth,30}, @@ -2114,6 +2112,17 @@ printable_range(Suite) when is_list(Suite) -> test_server:stop_node(DNode), ok. +%% Make sure that a bad specification for a printable range is rejected. +bad_printable_range(Config) when is_list(Config) -> + Cmd = lists:concat([lib:progname()," +pcunnnnnicode -run erlang halt"]), + case os:cmd(Cmd) of + "bad range of printable characters" ++ _ -> + ok; + String -> + io:format("~s\n", [String]), + ?t:fail() + end. + io_lib_print_binary_depth_one(doc) -> "Test binaries printed with a depth of one behave correctly"; io_lib_print_binary_depth_one(Suite) when is_list(Suite) -> -- cgit v1.2.3 From 3213c682e47f151283697a7a00f38bf2fbee670f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 1 Sep 2015 11:00:42 +0200 Subject: io_SUITE: Extend coverage of code for testing printable chars --- lib/stdlib/test/io_SUITE.erl | 82 +++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 36 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 8a6b2725af..6e7e1584d9 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -2070,48 +2070,58 @@ printable_range(Suite) when is_list(Suite) -> {record_print_fun, fun(_,_) -> no end}, {encoding,unicode}], - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print, - [{hello, [1024,1025]}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print, - [{hello, [1024,1025]}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print, - [{hello, [1024,1025]}, - PrettyOptions]))), - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print, - [{hello, <<1024/utf8,1025/utf8>>}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print, - [{hello, <<1024/utf8,1025/utf8>>}, - PrettyOptions]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print, - [{hello, <<1024/utf8,1025/utf8>>}, - PrettyOptions]))), + PrintableControls = "\t\v\b\f\e\r\n", + + 1025 = print_max(UNode, [{hello, [1024,1025]}, + PrettyOptions]), + 125 = print_max(LNode, [{hello, [1024,1025]}, + PrettyOptions]), + 125 = print_max(DNode, [{hello, [1024,1025]}, + PrettyOptions]), + 1025 = print_max(UNode, [{hello, <<1024/utf8,1025/utf8>>}, + PrettyOptions]), + 125 = print_max(LNode, [{hello, <<1024/utf8,1025/utf8>>}, + PrettyOptions]), + 125 = print_max(DNode, [{hello, <<1024/utf8,1025/utf8>>}, + PrettyOptions]), + $v = print_max(UNode, [PrintableControls,PrettyOptions]), + $v = print_max(LNode, [PrintableControls,PrettyOptions]), + $v = print_max(DNode, [PrintableControls,PrettyOptions]), + 16#10FFFF = print_max(UNode, + [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>, + PrettyOptions]), + $> = print_max(LNode, + [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>, + PrettyOptions]), + $> = print_max(DNode, + [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>, + PrettyOptions]), - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format, - ["~tp",[{hello, [1024,1025]}]]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format, - ["~tp",[{hello, [1024,1025]}]]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format, - ["~tp",[{hello, [1024,1025]}]]))), - 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format, - ["~tp", - [{hello, - <<1024/utf8,1025/utf8>>}]]))), - 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format, - ["~tp", - [{hello, - <<1024/utf8,1025/utf8>>}]]))), - 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format, - ["~tp", - [{hello, - <<1024/utf8,1025/utf8>>}]]))), + 1025 = format_max(UNode, ["~tp", [{hello, [1024,1025]}]]), + 125 = format_max(LNode, ["~tp", [{hello, [1024,1025]}]]), + 125 = format_max(DNode, ["~tp", [{hello, [1024,1025]}]]), + 1025 = format_max(UNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]), + 125 = format_max(LNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]), + 125 = format_max(DNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]), + + $\e = format_max(UNode, ["~ts", [PrintableControls]]), + $\e = format_max(LNode, ["~ts", [PrintableControls]]), + $\e = format_max(DNode, ["~ts", [PrintableControls]]), + test_server:stop_node(UNode), test_server:stop_node(LNode), test_server:stop_node(DNode), ok. +print_max(Node, Args) -> + rpc_call_max(Node, io_lib_pretty, print, Args). + +format_max(Node, Args) -> + rpc_call_max(Node, io_lib, format, Args). + +rpc_call_max(Node, M, F, Args) -> + lists:max(lists:flatten(rpc:call(Node, M, F, Args))). + %% Make sure that a bad specification for a printable range is rejected. bad_printable_range(Config) when is_list(Config) -> Cmd = lists:concat([lib:progname()," +pcunnnnnicode -run erlang halt"]), -- cgit v1.2.3 From 25e79a057a6839287271fc7a04a03f7e6f04652d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 08:43:04 +0200 Subject: io_SUITE: Add coverage/1 to completely cover io_lib_pretty --- lib/stdlib/test/io_SUITE.erl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 6e7e1584d9..0e897631ff 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -33,7 +33,7 @@ io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1, otp_10836/1, io_lib_width_too_small/1, io_with_huge_message_queue/1, format_string/1, - maps/1]). + maps/1, coverage/1]). -export([pretty/2]). @@ -74,7 +74,7 @@ all() -> printable_range, bad_printable_range, io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836, io_lib_width_too_small, io_with_huge_message_queue, - format_string, maps]. + format_string, maps, coverage]. groups() -> []. @@ -2390,3 +2390,14 @@ parse_skip_ws([C|S]) when C =< $\s -> parse_skip_ws(S); parse_skip_ws(S) -> S. + +%% Cover the last uncovered lines for completeness. +coverage(_Config) -> + S1 = io_lib_pretty:print({a,term}, fun(_, _) -> no end), + io:format("~s\n", [S1]), + + %% The tuple of arity three will be ignored. + S2 = io_lib_pretty:print(lists:seq(1, 100), [{depth,1,1}]), + io:format("~s\n", [S2]), + + ok. -- cgit v1.2.3 From bd0b4805862c722807765396711d3e1e7ccbbd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 2 Sep 2015 15:58:33 +0200 Subject: proc_lib_SUITE: Eliminate compiler warnings Use error/1 instead of forcing a badmatch. --- lib/stdlib/test/proc_lib_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl index 3a8fa74d36..857cd3f88d 100644 --- a/lib/stdlib/test/proc_lib_SUITE.erl +++ b/lib/stdlib/test/proc_lib_SUITE.erl @@ -369,7 +369,7 @@ init_dont_hang(Config) when is_list(Config) -> end. init_dont_hang_init(_Parent) -> - 1 = 2. + error(bad_init). %% Test proc_lib:stop/1,3 stop(_Config) -> @@ -453,7 +453,7 @@ stop(_Config) -> ok. system_terminate(crash,_Parent,_Deb,_State) -> - 1 = 2; + error({badmatch,2}); system_terminate(Reason,_Parent,_Deb,_State) -> exit(Reason). -- cgit v1.2.3 From ee12ac8b4134fad989a8fa3cfb58e8ec90002665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 2 Sep 2015 16:29:46 +0200 Subject: proc_lib: Improve coverage for crash/1 First refactor the entire test case using helper functions to facilitate further maintenance. Then test that proc_lib can handle that the process dictionary has been erased (that will cover more code in proc_lib). We can also shave off 2 seconds of the execution time by testing the 'shutdown' exit reasons at beginning of the test case instead of doing it at the end. --- lib/stdlib/test/proc_lib_SUITE.erl | 174 +++++++++++++++++++++++-------------- 1 file changed, 108 insertions(+), 66 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl index 857cd3f88d..f7a6a38138 100644 --- a/lib/stdlib/test/proc_lib_SUITE.erl +++ b/lib/stdlib/test/proc_lib_SUITE.erl @@ -80,81 +80,123 @@ end_per_group(_GroupName, Config) -> crash(Config) when is_list(Config) -> error_logger:add_report_handler(?MODULE, self()), - Pid = proc_lib:spawn(?MODULE, sp1, []), - Pid ! die, - ?line Report = receive - {crash_report, Pid, Report0} -> Report0 - after 2000 -> test_server:fail(no_crash_report) - end, - ?line proc_lib:format(Report), - ?line [PidRep, []] = Report, - ?line {value, {initial_call,{?MODULE,sp1,[]}}} = - lists:keysearch(initial_call, 1, PidRep), - Self = self(), - ?line {value, {ancestors,[Self]}} = - lists:keysearch(ancestors, 1, PidRep), - ?line {value, {error_info,{exit,die,_StackTrace1}}} = - lists:keysearch(error_info, 1, PidRep), - - F = fun sp1/0, - Pid1 = proc_lib:spawn(node(), F), - Pid1 ! die, - ?line [PidRep1, []] = receive - {crash_report, Pid1, Report1} -> Report1 - after 2000 -> test_server:fail(no_crash_report) - end, - ?line {value, {initial_call,{Fmod,Fname,[]}}} = - lists:keysearch(initial_call, 1, PidRep1), - ?line {module,Fmod} = erlang:fun_info(F, module), - ?line {name,Fname} = erlang:fun_info(F, name), - ?line {value, {ancestors,[Self]}} = - lists:keysearch(ancestors, 1, PidRep1), - ?line {value, {error_info,{exit,die,_StackTrace2}}} = - lists:keysearch(error_info, 1, PidRep1), - - Pid2 = proc_lib:spawn(?MODULE, sp2, []), - test_server:sleep(100), - ?line {?MODULE,sp2,[]} = proc_lib:initial_call(Pid2), - ?line {?MODULE,sp2,0} = proc_lib:translate_initial_call(Pid2), - Pid2 ! die, - ?line [Pid2Rep, [{neighbour, LinkRep}]] = - receive - {crash_report, Pid2, Report2} -> Report2 - after 2000 -> test_server:fail(no_crash_report) - end, - ?line {value, {initial_call,{?MODULE,sp2,[]}}} = - lists:keysearch(initial_call, 1, Pid2Rep), - ?line {value, {ancestors,[Self]}} = - lists:keysearch(ancestors, 1, Pid2Rep), - ?line {value, {error_info,{exit,die,_StackTrace3}}} = - lists:keysearch(error_info, 1, Pid2Rep), - ?line {value, {initial_call,{?MODULE,sp1,[]}}} = - lists:keysearch(initial_call, 1, LinkRep), - %% Make sure that we don't get a crash report if a process %% terminates with reason 'shutdown' or reason {shutdown,Reason}. - ?line process_flag(trap_exit, true), - ?line Pid3 = proc_lib:spawn_link(erlang, apply, - [fun() -> exit(shutdown) end,[]]), - - ?line Pid4 = proc_lib:spawn_link(erlang, apply, - [fun() -> exit({shutdown,{a,b,c}}) end,[]]), + process_flag(trap_exit, true), + Pid0 = proc_lib:spawn_link(erlang, apply, + [fun() -> exit(shutdown) end,[]]), + Pid1 = proc_lib:spawn_link(erlang, apply, + [fun() -> exit({shutdown,{a,b,c}}) end,[]]), + + receive {'EXIT',Pid0,shutdown} -> ok end, + receive {'EXIT',Pid1,{shutdown,{a,b,c}}} -> ok end, + process_flag(trap_exit, false), + %% We expect any unexpected messages to be caught below, + %% so we don't have explicitly wait some time to be sure. + + %% Spawn export function. + Pid2 = proc_lib:spawn(?MODULE, sp1, []), + Pid2 ! die, + Exp2 = [{initial_call,{?MODULE,sp1,[]}}, + {ancestors,[self()]}, + {error_info,{exit,die,{stacktrace}}}], + analyse_crash(Pid2, Exp2, []), - ?line receive {'EXIT',Pid3,shutdown} -> ok end, - ?line receive {'EXIT',Pid4,{shutdown,{a,b,c}}} -> ok end, - ?line process_flag(trap_exit, false), + %% Spawn fun. + F = fun sp1/0, + Pid3 = proc_lib:spawn(node(), F), + Pid3 ! die, + {module,?MODULE} = erlang:fun_info(F, module), + {name,Fname} = erlang:fun_info(F, name), + Exp3 = [{initial_call,{?MODULE,Fname,[]}}, + {ancestors,[self()]}, + {error_info,{exit,die,{stacktrace}}}], + analyse_crash(Pid3, Exp3, []), - receive - Any -> - ?line ?t:fail({unexpected_message,Any}) - after 2000 -> - ok - end, + %% Spawn function with neighbour. + Pid4 = proc_lib:spawn(?MODULE, sp2, []), + test_server:sleep(100), + {?MODULE,sp2,[]} = proc_lib:initial_call(Pid4), + {?MODULE,sp2,0} = proc_lib:translate_initial_call(Pid4), + Pid4 ! die, + Exp4 = [{initial_call,{?MODULE,sp2,[]}}, + {ancestors,[self()]}, + {error_info,{exit,die,{stacktrace}}}], + Links4 = [[{initial_call,{?MODULE,sp1,[]}}, + {ancestors,[Pid4,self()]}]], + analyse_crash(Pid4, Exp4, Links4), + + %% Make sure that we still get a crash report if the + %% process dictionary have been tampered with. + + Pid5 = proc_lib:spawn(erlang, apply, + [fun() -> + erase(), + exit(abnormal) + end,[]]), + Exp5 = [{initial_call,absent}, + {ancestors,[]}, + {error_info,{exit,abnormal,{stacktrace}}}], + analyse_crash(Pid5, Exp5, []), error_logger:delete_report_handler(?MODULE), ok. +analyse_crash(Pid, Expected0, ExpLinks) -> + Expected = [{pid,Pid}|Expected0], + receive + {crash_report, Pid, Report} -> + _ = proc_lib:format(Report), %Smoke test. + [Crash,Links] = Report, + analyse_crash_1(Expected, Crash), + analyse_links(ExpLinks, Links); + Unexpected -> + io:format("~p\n", [Unexpected]), + test_server:fail(unexpected_message) + after 5000 -> + test_server:fail(no_crash_report) + end. + +analyse_links([H|Es], [{neighbour,N}|Links]) -> + analyse_crash_1(H, N), + analyse_links(Es, Links); +analyse_links([], []) -> + ok. +analyse_crash_1([{Key,absent}|T], Report) -> + false = lists:keymember(Key, 1, Report), + analyse_crash_1(T, Report); +analyse_crash_1([{Key,Pattern}|T], Report) -> + case lists:keyfind(Key, 1, Report) of + false -> + io:format("~p", [Report]), + test_server:fail({missing_key,Key}); + {Key,Info} -> + try + match_info(Pattern, Info) + catch + no_match -> + io:format("key: ~p", [Key]), + io:format("pattern: ~p", [Pattern]), + io:format("actual: ~p", [Report]), + test_server:fail(no_match) + end, + analyse_crash_1(T, Report) + end; +analyse_crash_1([], _Report) -> + []. + +match_info(T, T) -> + ok; +match_info({stacktrace}, Stk) when is_list(Stk) -> + ok; +match_info([H1|T1], [H2|T2]) -> + match_info(H1, H2), + match_info(T1, T2); +match_info(Tuple1, Tuple2) when tuple_size(Tuple1) =:= tuple_size(Tuple2) -> + match_info(tuple_to_list(Tuple1), tuple_to_list(Tuple2)); +match_info(_, _) -> + throw(no_match). sync_start_nolink(Config) when is_list(Config) -> _Pid = spawn_link(?MODULE, sp5, [self()]), -- cgit v1.2.3 From 72bfa81400ee24f38ac4044420b080e66a5da37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 3 Sep 2015 15:39:02 +0200 Subject: gen_event_SUITE: Remove unnecessary sleep calls The calls to test_server:sleep/1 are unnecessary as the swapping of handlers happens in a single process. Even though the {swap_info,...} message is sent asynchronously, the gen_event:which_handlers/1 call will not have a chance to execute until the handlers have been swapped. --- lib/stdlib/test/gen_event_SUITE.erl | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl index 7a6fcba4e5..b019f98b69 100644 --- a/lib/stdlib/test/gen_event_SUITE.erl +++ b/lib/stdlib/test/gen_event_SUITE.erl @@ -412,7 +412,6 @@ notify(Config) when is_list(Config) -> ok end, ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, Event), ?line receive @@ -445,7 +444,6 @@ notify(Config) when is_list(Config) -> end, ?line ok = gen_event:notify(my_dummy_handler, {swap_event, {dummy1_h, 9}, swap}), - ?t:sleep(1000), ?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, Event), ?line receive @@ -485,7 +483,6 @@ notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, do_crash), @@ -496,7 +493,6 @@ notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:notify(my_dummy_handler, delete_event), @@ -529,7 +525,6 @@ sync_notify(Config) when is_list(Config) -> end, ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event, dummy1_h, swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, Event), ?line receive @@ -562,7 +557,6 @@ sync_notify(Config) when is_list(Config) -> end, ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event, {dummy1_h, 9}, swap}), - ?t:sleep(1000), ?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, Event), ?line receive @@ -603,7 +597,6 @@ sync_notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, do_crash), @@ -615,7 +608,6 @@ sync_notify(Config) when is_list(Config) -> ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), ?line ok = gen_event:sync_notify(my_dummy_handler, {swap_event,dummy1_h,swap}), - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line ok = gen_event:sync_notify(my_dummy_handler, delete_event), @@ -789,7 +781,6 @@ info(Config) when is_list(Config) -> ok end, ?line my_dummy_handler ! {swap_info,dummy1_h,swap}, - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line my_dummy_handler ! Info, ?line receive @@ -821,7 +812,6 @@ info(Config) when is_list(Config) -> ok end, ?line my_dummy_handler ! {swap_info,{dummy1_h,2},swap}, - ?t:sleep(1000), ?line [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler), ?line my_dummy_handler ! Info, ?line receive @@ -853,7 +843,6 @@ info(Config) when is_list(Config) -> ok end, ?line my_dummy_handler ! {swap_info,dummy1_h,swap}, - ?t:sleep(1000), ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler), ?line my_dummy_handler ! Info, ?line receive -- cgit v1.2.3 From 88d3f61e3724957f60c9e8a786e8533d8aa1f362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 4 Sep 2015 10:28:54 +0200 Subject: io_proto_SUITE: Refactor up rtnode() and friends Introduce a new {getline_pred, Fun, Msg} action that is useful in itself, but can also be used to share more code for {getline, Match} and {getline_re, Match}. Also get rid of the ?line macros in rtnode() so that we can somewhat reduce the ridculous indentation level. --- lib/stdlib/test/io_proto_SUITE.erl | 148 +++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 79 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl index 1337b7dde2..658c6442b1 100644 --- a/lib/stdlib/test/io_proto_SUITE.erl +++ b/lib/stdlib/test/io_proto_SUITE.erl @@ -1378,47 +1378,43 @@ rtnode(C,N) -> rtnode(Commands,Nodename,ErlPrefix) -> rtnode(Commands,Nodename,ErlPrefix,[]). rtnode(Commands,Nodename,ErlPrefix,Extra) -> - ?line case get_progs() of - {error,_Reason} -> - ?line {skip,"No runerl present"}; - {RunErl,ToErl,Erl} -> - ?line case create_tempdir() of - {error, Reason2} -> - ?line {skip, Reason2}; - Tempdir -> - ?line SPid = - start_runerl_node(RunErl,ErlPrefix++ - "\\\""++Erl++"\\\"", - Tempdir,Nodename, Extra), - ?line CPid = start_toerl_server(ToErl,Tempdir), - ?line erase(getline_skipped), - ?line Res = - (catch get_and_put(CPid, Commands,1)), - ?line case stop_runerl_node(CPid) of - {error,_} -> - ?line CPid2 = - start_toerl_server - (ToErl,Tempdir), - ?line erase(getline_skipped), - ?line ok = get_and_put - (CPid2, - [{putline,[7]}, - {sleep, - timeout(short)}, - {putline,""}, - {getline," -->"}, - {putline,"s"}, - {putline,"c"}, - {putline,""}],1), - ?line stop_runerl_node(CPid2); - _ -> - ?line ok - end, - ?line wait_for_runerl_server(SPid), - ?line ok = ?RM_RF(Tempdir), - ?line ok = Res - end - end. + case get_progs() of + {error,_Reason} -> + {skip,"No runerl present"}; + {RunErl,ToErl,Erl} -> + case create_tempdir() of + {error, Reason2} -> + {skip, Reason2}; + Tempdir -> + SPid = start_runerl_node(RunErl, ErlPrefix++ + "\\\""++Erl++"\\\"", + Tempdir, Nodename, Extra), + CPid = start_toerl_server(ToErl, Tempdir), + put(getline_skipped, []), + Res = (catch get_and_put(CPid, Commands, 1)), + case stop_runerl_node(CPid) of + {error,_} -> + CPid2 = start_toerl_server(ToErl, Tempdir), + put(getline_skipped, []), + ok = get_and_put + (CPid2, + [{putline,[7]}, + {sleep, + timeout(short)}, + {putline,""}, + {getline," -->"}, + {putline,"s"}, + {putline,"c"}, + {putline,""}], 1), + stop_runerl_node(CPid2); + _ -> + ok + end, + wait_for_runerl_server(SPid), + ok = ?RM_RF(Tempdir), + ok = Res + end + end. timeout(long) -> 2 * timeout(normal); @@ -1462,57 +1458,51 @@ get_and_put(CPid, [{sleep, X}|T],N) -> after X -> get_and_put(CPid,T,N+1) end; -get_and_put(CPid, [{getline, Match}|T],N) -> +get_and_put(CPid, [{getline_pred,Pred,Msg}|T]=T0, N) + when is_function(Pred) -> ?dbg({getline, Match}), CPid ! {self(), {get_line, timeout(normal)}}, receive {get_line, timeout} -> error_logger:error_msg("~p: getline timeout waiting for \"~s\" " "(command number ~p, skipped: ~p)~n", - [?MODULE, Match,N,get(getline_skipped)]), + [?MODULE,Msg,N,get(getline_skipped)]), {error, timeout}; {get_line, Data} -> ?dbg({data,Data}), - case lists:prefix(Match, Data) of - true -> - erase(getline_skipped), + case Pred(Data) of + yes -> + put(getline_skipped, []), get_and_put(CPid, T,N+1); - false -> - case get(getline_skipped) of - undefined -> - put(getline_skipped,[Data]); - List -> - put(getline_skipped,List ++ [Data]) - end, - get_and_put(CPid, [{getline, Match}|T],N) + no -> + error_logger:error_msg("~p: getline match failure " + "\"~s\" " + "(command number ~p)\n", + [?MODULE,Msg,N]), + {error, no_match}; + maybe -> + List = get(getline_skipped), + put(getline_skipped, List ++ [Data]), + get_and_put(CPid, T0, N) end end; +get_and_put(CPid, [{getline, Match}|T],N) -> + ?dbg({getline, Match}), + F = fun(Data) -> + case lists:prefix(Match, Data) of + true -> yes; + false -> maybe + end + end, + get_and_put(CPid, [{getline_pred,F,Match}|T], N); get_and_put(CPid, [{getline_re, Match}|T],N) -> - ?dbg({getline_re, Match}), - CPid ! {self(), {get_line, timeout(normal)}}, - receive - {get_line, timeout} -> - error_logger:error_msg("~p: getline_re timeout waiting for \"~s\" " - "(command number ~p, skipped: ~p)~n", - [?MODULE, Match,N,get(getline_skipped)]), - {error, timeout}; - {get_line, Data} -> - ?dbg({data,Data}), - case re:run(Data, Match,[{capture,none}]) of - match -> - erase(getline_skipped), - get_and_put(CPid, T,N+1); - _ -> - case get(getline_skipped) of - undefined -> - put(getline_skipped,[Data]); - List -> - put(getline_skipped,List ++ [Data]) - end, - get_and_put(CPid, [{getline_re, Match}|T],N) - end - end; - + F = fun(Data) -> + case re:run(Data, Match, [{capture,none}]) of + match -> yes; + _ -> maybe + end + end, + get_and_put(CPid, [{getline_pred,F,Match}|T], N); get_and_put(CPid, [{putline_raw, Line}|T],N) -> ?dbg({putline_raw, Line}), CPid ! {self(), {send_line, Line}}, -- cgit v1.2.3 From ccee216a6cc1bc619806007891e9d9d9c30e8826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 4 Sep 2015 10:32:07 +0200 Subject: io_proto_SUITE: Speed up determination of default shell Use getline_pred action that fails fast if the shell is not the oldshell, to avoid having to wait for the timeout. --- lib/stdlib/test/io_proto_SUITE.erl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl index 658c6442b1..811c7ed7bb 100644 --- a/lib/stdlib/test/io_proto_SUITE.erl +++ b/lib/stdlib/test/io_proto_SUITE.erl @@ -1791,10 +1791,22 @@ get_data_within(Port, Timeout, Acc) -> end. get_default_shell() -> + Match = fun(Data) -> + case lists:prefix("undefined", Data) of + true -> + yes; + false -> + case re:run(Data, "<\\d+[.]\\d+[.]\\d+>", + [{capture,none}]) of + match -> no; + _ -> maybe + end + end + end, try rtnode([{putline,""}, {putline, "whereis(user_drv)."}, - {getline, "undefined"}],[]), + {getline_pred, Match, "matching of user_drv pid"}], []), old catch _E:_R -> ?dbg({_E,_R}), -- cgit v1.2.3 From b322b7b3fb6765a6965726efa8afac572e60eec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 4 Sep 2015 15:20:27 +0200 Subject: id_transform_SUITE: Modernize test suite Remove handling of Clearcase; remove ?line macros. --- lib/stdlib/test/id_transform_SUITE.erl | 53 ++++++++++------------------------ 1 file changed, 16 insertions(+), 37 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl index 41de016f8d..1cff990697 100644 --- a/lib/stdlib/test/id_transform_SUITE.erl +++ b/lib/stdlib/test/id_transform_SUITE.erl @@ -56,47 +56,26 @@ end_per_group(_GroupName, Config) -> id_transform(doc) -> "Test erl_id_trans."; id_transform(Config) when is_list(Config) -> - ?line File=filename:join([code:lib_dir(stdlib),"examples", - "erl_id_trans.erl"]), - ?line {ok,erl_id_trans,Bin}=compile:file(File,[binary]), - ?line {module,erl_id_trans}=code:load_binary(erl_id_trans,File,Bin), - ?line case test_server:purify_is_running() of - false -> - Dog = ct:timetrap(?t:hours(1)), - ?line Res = run_in_test_suite(), - ?t:timetrap_cancel(Dog), - Res; - true -> - {skip,"Purify (too slow)"} - end. + File = filename:join([code:lib_dir(stdlib),"examples", + "erl_id_trans.erl"]), + {ok,erl_id_trans,Bin} = compile:file(File,[binary]), + {module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin), + case test_server:purify_is_running() of + false -> + Dog = ct:timetrap(?t:hours(1)), + Res = run_in_test_suite(), + ?t:timetrap_cancel(Dog), + Res; + true -> + {skip,"Valgrind (too slow)"} + end. run_in_test_suite() -> - LibDir = code:lib_dir(), SuperDir = filename:dirname(filename:dirname(code:which(?MODULE))), TestDirs = filelib:wildcard(filename:join([SuperDir,"*_test"])), - {All,Res} = case LibDir of - "/clearcase/otp/erts/lib" -> - %% Only test_suites 'cause clearcase is too slow... - {false,run_list(TestDirs)}; - _ -> - {true,run_codepath_and(TestDirs)} - end, - Comment0 = case All of - true -> []; - false -> "Only testsuite directories traversed" - end, - case Res of - {error,Reason} when Comment0 =/= [] -> - {failed,Comment0++"; "++Reason}; - {error,Reason} -> - {failed,Reason}; - ok -> - {comment,Comment0} - end. - -run_codepath_and(DirList) -> AbsDirs = [filename:absname(X) || X <- code:get_path()], - run_list(ordsets:from_list([X || X <- AbsDirs] ++ DirList)). + Dirs = ordsets:from_list(AbsDirs ++ TestDirs), + run_list(Dirs). run_list(PathL) -> io:format("Where to search for beam files:\n~p\n", [PathL]), @@ -123,7 +102,7 @@ run_list(PathL) -> end, case length(SevereFailures) of 0 -> ok; - Len -> {error,integer_to_list(Len)++" failures"} + Len -> {failed,integer_to_list(Len)++" failures"} end. -- cgit v1.2.3 From 1d00d0df6ff344e3a0ef58a5636ad32259ca31b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 08:53:22 +0200 Subject: lists_SUITE: Correct test of lists:flatten/2 The test that was supposed to call lists:flatten/2 called lists:flatten/1! --- lib/stdlib/test/lists_SUITE.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index e886a797f0..4a15bb9b81 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -2351,11 +2351,11 @@ flatten_1_e(Config) when is_list(Config) -> %%% clear-cut. Right now, I think that any term should be allowed. %%% But I also wish this function didn't exist at all. -flatten_2(doc) -> ["flatten/2"]; -flatten_2(suite) -> []; +%% Test lists:flatten/2. flatten_2(Config) when is_list(Config) -> - ?line [] = lists:flatten([]), - ?line [a] = lists:flatten([a]), + [] = lists:flatten([], []), + [a] = lists:flatten([a], []), + [a,b,c,[no,flatten]] = lists:flatten([[a,[b,c]]], [[no,flatten]]), ok. flatten_2_e(doc) -> ["flatten/2 error cases"]; -- cgit v1.2.3 From e882c376be9c62950ed84ae0ba7936cf4c827462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 09:00:22 +0200 Subject: lists_SUITE: Extend flatten/1 test to also test flatlength/1 --- lib/stdlib/test/lists_SUITE.erl | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index 4a15bb9b81..e0dd34e82d 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -2326,18 +2326,24 @@ sublist_3_e(Config) when is_list(Config) -> -define(flatten_error1(X), ?line {'EXIT', _} = (catch lists:flatten(X))). -define(flatten_error2(X,Y), ?line {'EXIT', _} = (catch lists:flatten(X,Y))). -flatten_1(doc) -> ["flatten/1"]; -flatten_1(suite) -> []; +%% Test lists:flatten/1,2 and lists:flatlength/1. flatten_1(Config) when is_list(Config) -> - ?line [] = lists:flatten([]), - ?line [1,2] = lists:flatten([1,2]), - ?line [1,2] = lists:flatten([1,[2]]), - ?line [1,2] = lists:flatten([[1],2]), - ?line [1,2] = lists:flatten([[1],[2]]), - ?line [1,2] = lists:flatten([[1,2]]), - ?line [a,b,c,d] = lists:flatten([[a],[b,c,[d]]]), - - ok. + [] = lists_flatten([]), + [1,2] = lists_flatten([1,2]), + [1,2] = lists_flatten([1,[2]]), + [1,2] = lists_flatten([[1],2]), + [1,2] = lists_flatten([[1],[2]]), + [1,2] = lists_flatten([[1,2]]), + [a,b,c,d] = lists_flatten([[a],[b,c,[d]]]), + + ok. + +lists_flatten(List) -> + Flat = lists:flatten(List), + Flat = lists:flatten(List, []), + Len = lists:flatlength(List), + Len = length(Flat), + Flat. flatten_1_e(doc) -> ["flatten/1 error cases"]; flatten_1_e(suite) -> []; -- cgit v1.2.3 From 358d73bb6432367823eda3636f9ce167c73750b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 09:10:13 +0200 Subject: lists_SUITE: Test lists:keyreplace/4 --- lib/stdlib/test/lists_SUITE.erl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index e0dd34e82d..cf42ac473d 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -38,7 +38,7 @@ % Test cases must be exported. -export([member/1, reverse/1, keymember/1, keysearch_keyfind/1, - keystore/1, keytake/1, + keystore/1, keytake/1, keyreplace/1, append_1/1, append_2/1, seq_loop/1, seq_2/1, seq_3/1, seq_2_e/1, seq_3_e/1, @@ -82,7 +82,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [{group, append}, reverse, member, keymember, - keysearch_keyfind, keystore, keytake, dropwhile, {group,sort}, + keysearch_keyfind, keystore, keytake, keyreplace, + dropwhile, {group,sort}, {group, usort}, {group, keysort}, {group, ukeysort}, {group, funsort}, {group, ufunsort}, {group, sublist}, {group, flatten}, {group, seq}, zip_unzip, zip_unzip3, @@ -382,6 +383,17 @@ keytake(Config) when is_list(Config) -> ?line false = lists:keytake(4, 2, L), ok. +%% Test lists:keyreplace/4. +keyreplace(Config) when is_list(Config) -> + [{new,42}] = lists:keyreplace(k, 1, [{k,1}], {new,42}), + [atom,{new,a,b}] = lists:keyreplace(k, 1, [atom,{k,1}], {new,a,b}), + [a,{x,y,z}] = lists:keyreplace(a, 5, [a,{x,y,z}], {no,use}), + + %% Error cases. + {'EXIT',_} = (catch lists:keyreplace(k, 1, [], not_tuple)), + {'EXIT',_} = (catch lists:keyreplace(k, 0, [], {a,b})), + ok. + merge(doc) -> ["merge functions"]; merge(suite) -> []; merge(Config) when is_list(Config) -> -- cgit v1.2.3 From c72d9efd26926768f1f02004d863feb7ac528a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 09:17:54 +0200 Subject: lists_SUITE: Run test cases in each group in parallel On my computer, this will shave off more than one second of the runnning time and about 4 seconds when cover is being run. --- lib/stdlib/test/lists_SUITE.erl | 50 +++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index cf42ac473d..14e6a12fda 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -81,38 +81,50 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [{group, append}, reverse, member, keymember, - keysearch_keyfind, keystore, keytake, keyreplace, - dropwhile, {group,sort}, - {group, usort}, {group, keysort}, {group, ukeysort}, - {group, funsort}, {group, ufunsort}, {group, sublist}, - {group, flatten}, {group, seq}, zip_unzip, zip_unzip3, - zipwith, zipwith3, filter_partition, {group, tickets}, - suffix, subtract]. + [{group, append}, + {group, key}, + {group,sort}, + {group, usort}, + {group, keysort}, + {group, ukeysort}, + {group, funsort}, + {group, ufunsort}, + {group, sublist}, + {group, flatten}, + {group, seq}, + {group, tickets}, + {group, zip}, + {group, misc}]. groups() -> - [{append, [], [append_1, append_2]}, - {usort, [], + [{append, [parallel], [append_1, append_2]}, + {usort, [parallel], [umerge, rumerge, usort_1, usort_rand, usort_stable]}, - {keysort, [], + {keysort, [parallel], [keymerge, rkeymerge, keysort_1, keysort_rand, keysort_i, keysort_stable, keysort_error]}, - {sort,[],[merge, rmerge, sort_1, sort_rand]}, - {ukeysort, [], + {key, [parallel], [keymember, keysearch_keyfind, keystore, + keytake, keyreplace]}, + {sort,[parallel],[merge, rmerge, sort_1, sort_rand]}, + {ukeysort, [parallel], [ukeymerge, rukeymerge, ukeysort_1, ukeysort_rand, ukeysort_i, ukeysort_stable, ukeysort_error]}, - {funsort, [], + {funsort, [parallel], [funmerge, rfunmerge, funsort_1, funsort_stable, funsort_error, funsort_rand]}, - {ufunsort, [], + {ufunsort, [parallel], [ufunmerge, rufunmerge, ufunsort_1, ufunsort_stable, ufunsort_error, ufunsort_rand]}, - {seq, [], [seq_loop, seq_2, seq_3, seq_2_e, seq_3_e]}, - {sublist, [], + {seq, [parallel], [seq_loop, seq_2, seq_3, seq_2_e, seq_3_e]}, + {sublist, [parallel], [sublist_2, sublist_3, sublist_2_e, sublist_3_e]}, - {flatten, [], + {flatten, [parallel], [flatten_1, flatten_2, flatten_1_e, flatten_2_e]}, - {tickets, [], [otp_5939, otp_6023, otp_6606, otp_7230]}]. + {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]}, + {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, + {misc, [parallel], [reverse, member, dropwhile, filter_partition, + suffix, subtract]} + ]. init_per_suite(Config) -> Config. -- cgit v1.2.3 From 02d26a9d7b28909edbc84b993b643a34325e90b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 10:39:52 +0200 Subject: lists_SUITE: Add test for lists:takewhile/1 --- lib/stdlib/test/lists_SUITE.erl | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index 14e6a12fda..6bed793028 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -44,7 +44,7 @@ sublist_2/1, sublist_3/1, sublist_2_e/1, sublist_3_e/1, flatten_1/1, flatten_2/1, flatten_1_e/1, flatten_2_e/1, - dropwhile/1, + dropwhile/1, takewhile/1, sort_1/1, sort_stable/1, merge/1, rmerge/1, sort_rand/1, usort_1/1, usort_stable/1, umerge/1, rumerge/1,usort_rand/1, keymerge/1, rkeymerge/1, @@ -122,8 +122,8 @@ groups() -> [flatten_1, flatten_2, flatten_1_e, flatten_2_e]}, {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]}, {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, - {misc, [parallel], [reverse, member, dropwhile, filter_partition, - suffix, subtract]} + {misc, [parallel], [reverse, member, dropwhile, takewhile, + filter_partition, suffix, subtract]} ]. init_per_suite(Config) -> @@ -358,6 +358,33 @@ dropwhile(Config) when is_list(Config) -> ok. +takewhile(Config) when is_list(Config) -> + F = fun(C) -> C =/= $@ end, + + [] = lists:takewhile(F, []), + [a] = lists:takewhile(F, [a]), + [a,b] = lists:takewhile(F, [a,b]), + [a,b,c] = lists:takewhile(F, [a,b,c]), + + [] = lists:takewhile(F, [$@]), + [] = lists:takewhile(F, [$@,$@]), + [a] = lists:takewhile(F, [a,$@]), + + [$k] = lists:takewhile(F, [$k,$@]), + [$k,$l] = lists:takewhile(F, [$k,$l,$@,$@]), + [a] = lists:takewhile(F, [a,$@,$@,$@]), + + [] = lists:takewhile(F, [$@,a,$@,b]), + [] = lists:takewhile(F, [$@,$@,a,$@,b]), + [] = lists:takewhile(F, [$@,$@,$@,a,$@,b]), + + Long = lists:seq(1, 1024), + Shorter = lists:seq(1, 400), + + Shorter = lists:takewhile(fun(E) -> E =< 400 end, Long), + + ok. + keystore(doc) -> ["OTP-XXX."]; keystore(suite) -> []; -- cgit v1.2.3 From 2ae8ec4507c090d51df41e21f7ad7786de040aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 10:25:55 +0200 Subject: lists_SUITE: Add hof/1 to test all high-order functions --- lib/stdlib/test/lists_SUITE.erl | 42 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index 6bed793028..a0f7fd2744 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -62,7 +62,7 @@ zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1, filter_partition/1, otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1, - suffix/1, subtract/1, droplast/1]). + suffix/1, subtract/1, droplast/1, hof/1]). %% Sort randomized lists until stopped. %% @@ -123,7 +123,8 @@ groups() -> {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]}, {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, {misc, [parallel], [reverse, member, dropwhile, takewhile, - filter_partition, suffix, subtract]} + filter_partition, suffix, subtract, + hof]} ]. init_per_suite(Config) -> @@ -2708,3 +2709,40 @@ droplast(Config) when is_list(Config) -> ?line {'EXIT', {function_clause, _}} = (catch lists:droplast(x)), ok. + +%% Briefly test the common high-order functions to ensure they +%% are covered. +hof(Config) when is_list(Config) -> + L = [1,2,3], + [1,4,9] = lists:map(fun(N) -> N*N end, L), + [1,4,5,6] = lists:flatmap(fun(1) -> [1]; + (2) -> []; + (3) -> [4,5,6] + end, L), + [{1,[a]},{2,[b]},{3,[c]}] = + lists:keymap(fun(A) -> [A] end, 2, [{1,a},{2,b},{3,c}]), + + [1,3] = lists:filter(fun(N) -> N rem 2 =:= 1 end, L), + FilterMapFun = fun(1) -> true; + (2) -> {true,42}; + (3) -> false + end, + [1,42] = lists:filtermap(FilterMapFun, L), + [1,42] = lists:zf(FilterMapFun, L), + + [3,2,1] = lists:foldl(fun(E, A) -> [E|A] end, [], L), + [1,2,3] = lists:foldr(fun(E, A) -> [E|A] end, [], L), + {[1,4,9],[3,2,1]} = lists:mapfoldl(fun(E, A) -> + {E*E,[E|A]} + end, [], L), + {[1,4,9],[1,2,3]} = lists:mapfoldr(fun(E, A) -> + {E*E,[E|A]} + end, [], L), + + true = lists:any(fun(N) -> N =:= 2 end, L), + false = lists:any(fun(N) -> N =:= 42 end, L), + + true = lists:all(fun(N) -> is_integer(N) end, L), + false = lists:all(fun(N) -> N rem 2 =:= 0 end, L), + + ok. -- cgit v1.2.3 From 6b39473811ed8b10f6ee08f2871b971e702317bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 13:46:56 +0200 Subject: lists_SUITE: Add a test case for lists:prefix/2 --- lib/stdlib/test/lists_SUITE.erl | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index a0f7fd2744..175eb29af9 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -62,7 +62,7 @@ zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1, filter_partition/1, otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1, - suffix/1, subtract/1, droplast/1, hof/1]). + prefix/1, suffix/1, subtract/1, droplast/1, hof/1]). %% Sort randomized lists until stopped. %% @@ -123,7 +123,7 @@ groups() -> {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]}, {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, {misc, [parallel], [reverse, member, dropwhile, takewhile, - filter_partition, suffix, subtract, + filter_partition, prefix, suffix, subtract, hof]} ]. @@ -2629,6 +2629,19 @@ otp_6606(Config) when is_list(Config) -> ?line L2 = lists:sort(L2), ok. +%% Test lists:prefix/2. +prefix(Config) when is_list(Config) -> + true = lists:prefix([], []), + true = lists:prefix([], lists:seq(1, 10)), + true = lists:prefix([a], [a,b]), + true = lists:prefix(lists:seq(1, 10), lists:seq(1, 100)), + + false = lists:prefix([a], []), + false = lists:prefix([a], [b]), + false = lists:prefix([a], [b,a]), + + ok. + %% Test lists:suffix/2. suffix(Config) when is_list(Config) -> ?line true = lists:suffix([], []), -- cgit v1.2.3 From 8cbbc7b8577b4aecf681c38cd03c3387f7e605ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 14:15:30 +0200 Subject: lists_SUITE: Test lists:split/2 --- lib/stdlib/test/lists_SUITE.erl | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index 175eb29af9..c84b4d9a5d 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -62,7 +62,8 @@ zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1, filter_partition/1, otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1, - prefix/1, suffix/1, subtract/1, droplast/1, hof/1]). + prefix/1, suffix/1, subtract/1, droplast/1, hof/1, + split/1]). %% Sort randomized lists until stopped. %% @@ -124,7 +125,7 @@ groups() -> {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, {misc, [parallel], [reverse, member, dropwhile, takewhile, filter_partition, prefix, suffix, subtract, - hof]} + hof, split]} ]. init_per_suite(Config) -> @@ -2759,3 +2760,31 @@ hof(Config) when is_list(Config) -> false = lists:all(fun(N) -> N rem 2 =:= 0 end, L), ok. + +%% Test lists:split/2 +split(Config) when is_list(Config) -> + Lens = lists:seq(0, 32), + do_split(Lens), + + %% Error cases. + {'EXIT',_} = (catch lists:split(a, [])), + {'EXIT',_} = (catch lists:split(-1, [])), + {'EXIT',_} = (catch lists:split(0, {a,b})), + ok. + +do_split([Len|Lens]) -> + List = [rand:uniform(1000) || _ <- lists:seq(1, Len)], + do_split_1(0, Len, List), + do_split(Lens); +do_split([]) -> + ok. + +do_split_1(N, Len, List) when N =:= Len + 1 -> + {'EXIT',_} = (catch lists:split(N, List)); +do_split_1(N, Len, List) -> + {A,B} = lists:split(N, List), + List = A ++ B, + N = length(A), + LenB = length(B), + LenB = Len - N, + do_split_1(N+1, Len, List). -- cgit v1.2.3 From c54430d8d47993ccc10651d2049961b4ab122a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 14:21:17 +0200 Subject: lists_SUITE: Test lists:concat/2 --- lib/stdlib/test/lists_SUITE.erl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index c84b4d9a5d..5a447d58a4 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -63,7 +63,7 @@ filter_partition/1, otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1, prefix/1, suffix/1, subtract/1, droplast/1, hof/1, - split/1]). + split/1, concat/1]). %% Sort randomized lists until stopped. %% @@ -125,7 +125,7 @@ groups() -> {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, {misc, [parallel], [reverse, member, dropwhile, takewhile, filter_partition, prefix, suffix, subtract, - hof, split]} + hof, split, concat]} ]. init_per_suite(Config) -> @@ -2788,3 +2788,9 @@ do_split_1(N, Len, List) -> LenB = length(B), LenB = Len - N, do_split_1(N+1, Len, List). + +%% Test lists:concat/1 mainly for coverage. +concat(Config) when is_list(Config) -> + S = integer_to_list(42) ++ "pi: " ++ float_to_list(math:pi()), + S = lists:concat([42,pi,": ",math:pi()]), + ok. -- cgit v1.2.3 From 78eb4a1ff9cafe394e338abb7297a1199c5eba85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 15:11:28 +0200 Subject: base64_SUITE: Speed up roundtrip/1 Refactor roundtrip/1 into 4 test cases that can be run in parallel. Assuming that there are 4 cores available, the group of 4 test cases will run at roughly one fourth of the time for the original test case. --- lib/stdlib/test/base64_SUITE.erl | 38 +++++++++++++++++++--------- lib/stdlib/test/lists_SUITE.erl | 54 +++------------------------------------- 2 files changed, 29 insertions(+), 63 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl index cca9b967d5..75eebba6c6 100644 --- a/lib/stdlib/test/base64_SUITE.erl +++ b/lib/stdlib/test/base64_SUITE.erl @@ -30,7 +30,8 @@ %% Test cases must be exported. -export([base64_encode/1, base64_decode/1, base64_otp_5635/1, base64_otp_6279/1, big/1, illegal/1, mime_decode/1, - mime_decode_to_string/1, roundtrip/1]). + mime_decode_to_string/1, + roundtrip_1/1, roundtrip_2/1, roundtrip_3/1, roundtrip_4/1]). init_per_testcase(_, Config) -> Dog = test_server:timetrap(?t:minutes(4)), @@ -50,10 +51,11 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [base64_encode, base64_decode, base64_otp_5635, base64_otp_6279, big, illegal, mime_decode, mime_decode_to_string, - roundtrip]. + {group, roundtrip}]. groups() -> - []. + [{roundtrip, [parallel], + [roundtrip_1, roundtrip_2, roundtrip_3, roundtrip_4]}]. init_per_suite(Config) -> Config. @@ -242,21 +244,33 @@ mime_decode_to_string(Config) when is_list(Config) -> %%------------------------------------------------------------------------- -roundtrip(Config) when is_list(Config) -> - Sizes = lists:seq(1, 255) ++ lists:seq(2400-5, 2440), - roundtrip_1(Sizes, []). +roundtrip_1(Config) when is_list(Config) -> + do_roundtrip(1). -roundtrip_1([NextSize|Sizes], Current) -> +roundtrip_2(Config) when is_list(Config) -> + do_roundtrip(2). + +roundtrip_3(Config) when is_list(Config) -> + do_roundtrip(3). + +roundtrip_4(Config) when is_list(Config) -> + do_roundtrip(4). + +do_roundtrip(Offset) -> + Sizes = lists:seq(Offset, 255, 4) ++ lists:seq(2400-6+Offset, 2440, 4), + do_roundtrip_1(Sizes, []). + +do_roundtrip_1([NextSize|Sizes], Current) -> Len = length(Current), io:format("~p", [Len]), - do_roundtrip(Current), + do_roundtrip_2(Current), Next = random_byte_list(NextSize - Len, Current), - roundtrip_1(Sizes, Next); -roundtrip_1([], Last) -> + do_roundtrip_1(Sizes, Next); +do_roundtrip_1([], Last) -> io:format("~p", [length(Last)]), - do_roundtrip(Last). + do_roundtrip_2(Last). -do_roundtrip(List) -> +do_roundtrip_2(List) -> Bin = list_to_binary(List), Base64Bin = base64:encode(List), Base64Bin = base64:encode(Bin), diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index 5a447d58a4..a0f7fd2744 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -62,8 +62,7 @@ zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1, filter_partition/1, otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1, - prefix/1, suffix/1, subtract/1, droplast/1, hof/1, - split/1, concat/1]). + suffix/1, subtract/1, droplast/1, hof/1]). %% Sort randomized lists until stopped. %% @@ -124,8 +123,8 @@ groups() -> {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]}, {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]}, {misc, [parallel], [reverse, member, dropwhile, takewhile, - filter_partition, prefix, suffix, subtract, - hof, split, concat]} + filter_partition, suffix, subtract, + hof]} ]. init_per_suite(Config) -> @@ -2630,19 +2629,6 @@ otp_6606(Config) when is_list(Config) -> ?line L2 = lists:sort(L2), ok. -%% Test lists:prefix/2. -prefix(Config) when is_list(Config) -> - true = lists:prefix([], []), - true = lists:prefix([], lists:seq(1, 10)), - true = lists:prefix([a], [a,b]), - true = lists:prefix(lists:seq(1, 10), lists:seq(1, 100)), - - false = lists:prefix([a], []), - false = lists:prefix([a], [b]), - false = lists:prefix([a], [b,a]), - - ok. - %% Test lists:suffix/2. suffix(Config) when is_list(Config) -> ?line true = lists:suffix([], []), @@ -2760,37 +2746,3 @@ hof(Config) when is_list(Config) -> false = lists:all(fun(N) -> N rem 2 =:= 0 end, L), ok. - -%% Test lists:split/2 -split(Config) when is_list(Config) -> - Lens = lists:seq(0, 32), - do_split(Lens), - - %% Error cases. - {'EXIT',_} = (catch lists:split(a, [])), - {'EXIT',_} = (catch lists:split(-1, [])), - {'EXIT',_} = (catch lists:split(0, {a,b})), - ok. - -do_split([Len|Lens]) -> - List = [rand:uniform(1000) || _ <- lists:seq(1, Len)], - do_split_1(0, Len, List), - do_split(Lens); -do_split([]) -> - ok. - -do_split_1(N, Len, List) when N =:= Len + 1 -> - {'EXIT',_} = (catch lists:split(N, List)); -do_split_1(N, Len, List) -> - {A,B} = lists:split(N, List), - List = A ++ B, - N = length(A), - LenB = length(B), - LenB = Len - N, - do_split_1(N+1, Len, List). - -%% Test lists:concat/1 mainly for coverage. -concat(Config) when is_list(Config) -> - S = integer_to_list(42) ++ "pi: " ++ float_to_list(math:pi()), - S = lists:concat([42,pi,": ",math:pi()]), - ok. -- cgit v1.2.3 From d9117a4ae9e35bd1917272460d0e8a52133046d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 8 Sep 2015 15:26:27 +0200 Subject: rand_SUITE: Speed up basic_stats/1 Refactor basic_stats/1 into three separate test cases that can be run in parallel. --- lib/stdlib/test/rand_SUITE.erl | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl index b03caebe91..111bf620de 100644 --- a/lib/stdlib/test/rand_SUITE.erl +++ b/lib/stdlib/test/rand_SUITE.erl @@ -25,7 +25,9 @@ ]). -export([interval_int/1, interval_float/1, seed/1, - api_eq/1, reference/1, basic_stats/1, + api_eq/1, reference/1, + basic_stats_uniform_1/1, basic_stats_uniform_2/1, + basic_stats_normal/1, plugin/1, measure/1 ]). @@ -51,11 +53,13 @@ all() -> [seed, interval_int, interval_float, api_eq, reference, - basic_stats, + {group, basic_stats}, plugin, measure ]. -groups() -> []. +groups() -> + [{basic_stats, [parallel], + [basic_stats_uniform_1, basic_stats_uniform_2, basic_stats_normal]}]. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. @@ -291,14 +295,19 @@ gen(_, _, Acc) -> lists:reverse(Acc). %% The algorithms must have good properties to begin with %% -basic_stats(doc) -> ["Check that the algorithms generate sound values."]; -basic_stats(suite) -> []; -basic_stats(Config) when is_list(Config) -> - io:format("Testing uniform~n",[]), +%% Check that the algorithms generate sound values. + +basic_stats_uniform_1(Config) when is_list(Config) -> [basic_uniform_1(?LOOP, rand:seed_s(Alg), 0.0, array:new([{default, 0}])) || Alg <- algs()], + ok. + +basic_stats_uniform_2(Config) when is_list(Config) -> [basic_uniform_2(?LOOP, rand:seed_s(Alg), 0, array:new([{default, 0}])) || Alg <- algs()], + ok. + +basic_stats_normal(Config) when is_list(Config) -> io:format("Testing normal~n",[]), [basic_normal_1(?LOOP, rand:seed_s(Alg), 0, 0) || Alg <- algs()], ok. -- cgit v1.2.3 From ff2025e7a31f3500182cf1b259eddf6b6e5c4e1b Mon Sep 17 00:00:00 2001 From: Steven Danna Date: Sat, 12 Sep 2015 00:14:03 +0100 Subject: Document eunit's default 5 second test timeout --- lib/eunit/doc/overview.edoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc index df716cdeea..2789a05792 100644 --- a/lib/eunit/doc/overview.edoc +++ b/lib/eunit/doc/overview.edoc @@ -885,7 +885,7 @@ the timeout is exceeded, the unfinished tests will be forced to terminate. Note that if a timeout is set around a fixture, it includes the time for setup and cleanup, and if the timeout is triggered, the entire fixture is abruptly terminated (without running the -cleanup). +cleanup). The default timeout for an individual test is 5 seconds.
`{inorder, Tests}'
Runs the specified tests in strict order. Also see `{inparallel, Tests}'. By default, tests are neither marked as `inorder' or -- cgit v1.2.3 From d9daff6d87c217ba7d3cba00642710e473e9b226 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 26 Jun 2015 14:09:43 +0200 Subject: stdlib: Remove deprecated functions in erl_parse and erl_scan The recently added module erl_anno can no longer handle negative line numbers. --- lib/dialyzer/test/r9c_SUITE_data/results/mnesia | 2 +- .../small_SUITE_data/src/big_external_type.erl | 6 +- .../test/small_SUITE_data/src/big_local_type.erl | 6 +- lib/stdlib/doc/src/erl_scan.xml | 185 +------------- lib/stdlib/src/erl_anno.erl | 96 ++----- lib/stdlib/src/erl_lint.erl | 22 +- lib/stdlib/src/erl_parse.yrl | 27 -- lib/stdlib/src/erl_scan.erl | 267 ++------------------ lib/stdlib/src/otp_internal.erl | 45 ++-- lib/stdlib/test/erl_anno_SUITE.erl | 72 +----- lib/stdlib/test/erl_lint_SUITE.erl | 38 +-- lib/stdlib/test/erl_scan_SUITE.erl | 279 ++++++++------------- 12 files changed, 192 insertions(+), 853 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia index b73943422a..1dc5a105bf 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia +++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia @@ -35,6 +35,6 @@ mnesia_schema.erl:1258: Guard test FromS::'disc_copies' | 'disc_only_copies' | ' mnesia_schema.erl:1639: The pattern {'false', 'mandatory'} can never match the type {'false','optional'} mnesia_schema.erl:2434: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_} mnesia_schema.erl:451: Guard test UseDirAnyway::'false' == 'true' can never succeed -mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{integer(),atom() | tuple(),_}} | {'ok',_} +mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{non_neg_integer(),atom() | tuple(),_}} | {'ok',_} mnesia_tm.erl:1522: Function commit_participant/5 has no local return mnesia_tm.erl:2169: Function system_terminate/4 has no local return diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl index ab84e94106..9ad4810a5e 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl @@ -36,7 +36,7 @@ %% Start of Abstract Format --type line() :: erl_scan:line(). +-type line() :: erl_anno:line(). -export_type([af_record_index/0, af_record_field/1, af_record_name/0, af_field_name/0, af_function_decl/0]). @@ -332,8 +332,8 @@ %% End of Abstract Format -type error_description() :: term(). --type error_info() :: {erl_scan:line(), module(), error_description()}. --type token() :: {Tag :: atom(), Line :: erl_scan:line()}. +-type error_info() :: {erl_anno:line(), module(), error_description()}. +-type token() :: {Tag :: atom(), Line :: erl_scan:anno()}. %% mkop(Op, Arg) -> {op,Line,Op,Arg}. %% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}. diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl index fc7c5241a8..fe567ff10d 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl @@ -36,7 +36,7 @@ %% Start of Abstract Format --type line() :: erl_scan:line(). +-type line() :: erl_anno:line(). -export_type([af_module/0, af_export/0, af_import/0, af_fa_list/0, af_compile/0, af_file/0, af_record_decl/0, @@ -329,8 +329,8 @@ %% End of Abstract Format -type error_description() :: term(). --type error_info() :: {erl_scan:line(), module(), error_description()}. --type token() :: {Tag :: atom(), Line :: erl_scan:line()}. +-type error_info() :: {erl_anno:line(), module(), error_description()}. +-type token() :: {Tag :: atom(), Line :: erl_anno:line()}. %% mkop(Op, Arg) -> {op,Line,Op,Arg}. %% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}. diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml index 18e988e286..01b845a039 100644 --- a/lib/stdlib/doc/src/erl_scan.xml +++ b/lib/stdlib/doc/src/erl_scan.xml @@ -39,39 +39,15 @@ Erlang tokens.

- - - - - - - - - - - - - - - - - - - - - - - - @@ -87,9 +63,6 @@ - - - @@ -122,25 +95,23 @@ StartLocation, []).

StartLocation indicates the initial location when scanning starts. If StartLocation is a line, - attributes() as well as EndLocation and + Anno as well as EndLocation and ErrorLocation will be lines. If StartLocation is a pair of a line and a column - attributes() takes the form of an opaque compound + Anno takes the form of an opaque compound data type, and EndLocation and ErrorLocation will be pairs of a line and a column. The token - attributes contain information about the column and the + annotations contain information about the column and the line where the token begins, as well as the text of the token (if the text option is given), all of which can - be accessed by calling token_info/1,2, attributes_info/1,2, + be accessed by calling column/1, line/1, location/1, and text/1.

A token is a tuple containing information about - syntactic category, the token attributes, and the actual + syntactic category, the token annotations, and the actual terminal symbol. For punctuation characters (e.g. ;, |) and reserved words, the category and the symbol coincide, and the token is represented by a two-tuple. @@ -172,7 +143,7 @@

Short for [return_comments, return_white_spaces].

text -

Include the token's text in the token attributes. The +

Include the token's text in the token annotation. The text is the part of the input corresponding to the token.

@@ -305,150 +276,6 @@

- - - Return information about a token - -

Returns a list containing information about the token - Token. The order of the - TokenInfoTuples is not - defined. See token_info/2 for - information about specific - TokenInfoTuples.

-

Note that if token_info(Token, TokenItem) returns - undefined for some TokenItem, the - item is not included in TokenInfo.

-
-
- - - - - - Return information about a token - -

Returns a list containing information about the token - Token. If one single - TokenItem is given the returned value is - the corresponding - TokenInfoTuple, or undefined if the - TokenItem has no value. If a list of - TokenItems is given the result is a list of - TokenInfoTuple. The - TokenInfoTuples will - appear with the corresponding TokenItems in - the same order as the TokenItems - appear in the list of TokenItems. - TokenItems with no value are not included - in the list of TokenInfoTuple.

-

The following TokenInfoTuples with corresponding - TokenItems are valid:

- - {category, - category()} -

The category of the token.

-
- {column, - column()} -

The column where the token begins.

-
- {length, integer() > 0} -

The length of the token's text.

-
- {line, - line()} -

The line where the token begins.

-
- {location, - location()} -

The line and column where the token begins, or - just the line if the column unknown.

-
- {symbol, - symbol()} -

The token's symbol.

-
- {text, string()} -

The token's text.

-
-
-
-
- - - Return information about token attributes - -

Returns a list containing information about the token - attributes Attributes. The order of the - AttributeInfoTuples is not defined. - See attributes_info/2 for - information about specific - AttributeInfoTuples.

-

Note that if attributes_info(Token, AttributeItem) - returns undefined for some AttributeItem in - the list above, the item is not included in - AttributesInfo.

-
-
- - - - Return information about a token attributes - - -

Returns a list containing information about the token - attributes Attributes. If one single - AttributeItem is given the returned value is the - corresponding AttributeInfoTuple, - or undefined if the AttributeItem - has no value. If a list of AttributeItem - is given the result is a list of - AttributeInfoTuple. - The AttributeInfoTuples - will appear with the corresponding AttributeItems - in the same order as the AttributeItems - appear in the list of AttributeItems. - AttributeItems with no - value are not included in the list of - AttributeInfoTuple.

-

The following AttributeInfoTuples with - corresponding AttributeItems are valid:

- - {column, - column()} -

The column where the token begins.

-
- {length, integer() > 0} -

The length of the token's text.

-
- {line, - line()} -

The line where the token begins.

-
- {location, - location()} -

The line and column where the token begins, or - just the line if the column unknown.

-
- {text, string()} -

The token's text.

-
-
-
-
- - - Set a token attribute value - -

Sets the value of the line attribute of the token - attributes Attributes.

-

The SetAttributeFun is called with the value of - the line attribute, and is to return the new value of - the line attribute.

-
-
Format an error descriptor diff --git a/lib/stdlib/src/erl_anno.erl b/lib/stdlib/src/erl_anno.erl index 143318aa55..d32c34dabd 100644 --- a/lib/stdlib/src/erl_anno.erl +++ b/lib/stdlib/src/erl_anno.erl @@ -33,7 +33,7 @@ -export_type([anno_term/0]). --define(LN(L), is_integer(L)). +-define(LN(L), is_integer(L), L >= 0). -define(COL(C), (is_integer(C) andalso C >= 1)). %% Location. @@ -52,13 +52,13 @@ | {'record', record()} | {'text', string()}. --type anno() :: location() | [annotation(), ...]. +-opaque anno() :: location() | [annotation(), ...]. -type anno_term() :: term(). -type column() :: pos_integer(). -type generated() :: boolean(). -type filename() :: file:filename_all(). --type line() :: integer(). +-type line() :: non_neg_integer(). -type location() :: line() | {line(), column()}. -type record() :: boolean(). -type text() :: string(). @@ -90,9 +90,13 @@ to_term(Anno) -> -ifdef(DEBUG). from_term(Term) when is_list(Term) -> Term; +from_term(Line) when is_integer(Line), Line < 0 -> % Before OTP 19 + set_generated(true, new(-Line)); from_term(Term) -> [{location, Term}]. -else. +from_term(Line) when is_integer(Line), Line < 0 -> % Before OTP 19 + set_generated(true, new(-Line)); from_term(Term) -> Term. -endif. @@ -198,18 +202,11 @@ file(Anno) -> Anno :: anno(). generated(Line) when ?ALINE(Line) -> - Line =< 0; + false; generated({Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column) -> - Line =< 0; + false; generated(Anno) -> - _ = anno_info(Anno, generated, false), - {location, Location} = lists:keyfind(location, 1, Anno), - case Location of - {Line, _Column} -> - Line =< 0; - Line -> - Line =< 0 - end. + anno_info(Anno, generated, false). -spec line(Anno) -> line() when Anno :: anno(). @@ -226,18 +223,11 @@ line(Anno) -> Anno :: anno(). location(Line) when ?ALINE(Line) -> - abs(Line); -location({Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column) -> - {abs(Line), Column}; + Line; +location({Line, Column}=Location) when ?ALINE(Line), ?ACOLUMN(Column) -> + Location; location(Anno) -> - case anno_info(Anno, location) of - Line when Line < 0 -> - -Line; - {Line, Column} when Line < 0 -> - {-Line, Column}; - Location -> - Location - end. + anno_info(Anno, location). -spec record(Anno) -> record() when Anno :: anno(). @@ -270,31 +260,8 @@ set_file(File, Anno) -> Generated :: generated(), Anno :: anno(). -set_generated(true, Line) when ?ALINE(Line) -> - -abs(Line); -set_generated(false, Line) when ?ALINE(Line) -> - abs(Line); -set_generated(true, {Line, Column}) when ?ALINE(Line), - ?ACOLUMN(Column) -> - {-abs(Line),Column}; -set_generated(false, {Line, Column}) when ?ALINE(Line), - ?ACOLUMN(Column) -> - {abs(Line),Column}; set_generated(Generated, Anno) -> - _ = set(generated, Generated, Anno), - {location, Location} = lists:keyfind(location, 1, Anno), - NewLocation = - case Location of - {Line, Column} when Generated -> - {-abs(Line), Column}; - {Line, Column} when not Generated -> - {abs(Line), Column}; - Line when Generated -> - -abs(Line); - Line when not Generated -> - abs(Line) - end, - lists:keyreplace(location, 1, Anno, {location, NewLocation}). + set(generated, Generated, Anno). -spec set_line(Line, Anno) -> Anno when Line :: line(), @@ -313,38 +280,17 @@ set_line(Line, Anno) -> Anno :: anno(). set_location(Line, L) when ?ALINE(L), ?LLINE(Line) -> - new_location(fix_line(Line, L)); + new_location(Line); set_location(Line, {L, Column}) when ?ALINE(L), ?ACOLUMN(Column), ?LLINE(Line) -> - new_location(fix_line(Line, L)); + new_location(Line); set_location({L, C}=Loc, Line) when ?ALINE(Line), ?LLINE(L), ?LCOLUMN(C) -> - new_location(fix_location(Loc, Line)); + new_location(Loc); set_location({L, C}=Loc, {Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column), ?LLINE(L), ?LCOLUMN(C) -> - new_location(fix_location(Loc, Line)); + new_location(Loc); set_location(Location, Anno) -> - _ = set(location, Location, Anno), - {location, OldLocation} = lists:keyfind(location, 1, Anno), - NewLocation = - case {Location, OldLocation} of - {{_Line, _Column}=Loc, {L, _C}} -> - fix_location(Loc, L); - {Line, {L, _C}} -> - fix_line(Line, L); - {{_Line, _Column}=Loc, L} -> - fix_location(Loc, L); - {Line, L} -> - fix_line(Line, L) - end, - lists:keyreplace(location, 1, Anno, {location, NewLocation}). - -fix_location({Line, Column}, OldLine) -> - {fix_line(Line, OldLine), Column}. - -fix_line(Line, OldLine) when OldLine < 0, Line > 0 -> - -Line; -fix_line(Line, _OldLine) -> - Line. + set(location, Location, Anno). -spec set_record(Record, Anno) -> Anno when Record :: record(), @@ -383,7 +329,7 @@ set_anno(Item, Value, Anno) -> _ -> lists:keyreplace(Item, 1, Anno, {Item, Value}) end, - simplify(R) + reset_simplify(R) end. reset(Anno, Item) -> diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index c4cb5fdc80..a5f0e7dbd3 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -31,12 +31,8 @@ -export([is_guard_expr/1]). -export([bool_option/4,value_option/3,value_option/7]). --export([modify_line/2]). - -import(lists, [member/2,map/2,foldl/3,foldr/3,mapfoldl/3,all/2,reverse/1]). --deprecated([{modify_line, 2, next_major_release}]). - %% bool_option(OnOpt, OffOpt, Default, Options) -> boolean(). %% value_option(Flag, Default, Options) -> Value. %% value_option(Flag, Default, OnOpt, OnVal, OffOpt, OffVal, Options) -> @@ -79,7 +75,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> %%-define(DEBUGF(X,Y), io:format(X, Y)). -define(DEBUGF(X,Y), void). --type line() :: erl_anno:line(). % a convenient alias +-type line() :: erl_anno:anno(). % a convenient alias -type fa() :: {atom(), arity()}. % function+arity -type ta() :: {atom(), arity()}. % type+arity @@ -238,6 +234,9 @@ format_error({removed, MFA, ReplacementMFA, Rel}) -> "use ~s", [format_mfa(MFA), Rel, format_mfa(ReplacementMFA)]); format_error({removed, MFA, String}) when is_list(String) -> io_lib:format("~s: ~s", [format_mfa(MFA), String]); +format_error({removed_type, MNA, ReplacementMNA, Rel}) -> + io_lib:format("the type ~s was removed in ~s; use ~s instead", + [format_mna(MNA), Rel, format_mna(ReplacementMNA)]); format_error({obsolete_guard, {F, A}}) -> io_lib:format("~p/~p obsolete", [F, A]); format_error({too_many_arguments,Arity}) -> @@ -413,6 +412,9 @@ format_mfa({M, F, A}) when is_integer(A) -> format_mf(M, F, ArityString) when is_atom(M), is_atom(F) -> atom_to_list(M) ++ ":" ++ atom_to_list(F) ++ "/" ++ ArityString. +format_mna({M, N, A}) when is_integer(A) -> + atom_to_list(M) ++ ":" ++ atom_to_list(N) ++ gen_type_paren(A). + format_where(L) when is_integer(L) -> io_lib:format("(line ~p)", [L]); format_where({L,C}) when is_integer(L), is_integer(C) -> @@ -3482,13 +3484,6 @@ vt_no_unused(Vt) -> [V || {_,{_,U,_L}}=V <- Vt, U =/= unused]. copy_expr(Expr, Anno) -> erl_parse:map_anno(fun(_A) -> Anno end, Expr). -%% modify_line(Form, Fun) -> Form -%% modify_line(Expression, Fun) -> Expression -%% Applies Fun to each line number occurrence. - -modify_line(T, F0) -> - erl_parse:map_anno(F0, T). - %% Check a record_info call. We have already checked that it is not %% shadowed by an import. @@ -3557,6 +3552,7 @@ deprecated_function(Line, M, F, As, St) -> St end. +-dialyzer({no_match, deprecated_type/5}). deprecated_type(L, M, N, As, St) -> NAs = length(As), case otp_internal:obsolete_type(M, N, NAs) of @@ -3567,6 +3563,8 @@ deprecated_type(L, M, N, As, St) -> false -> St end; + {removed, Replacement, Rel} -> + add_warning(L, {removed_type, {M,N,NAs}, Replacement, Rel}, St); no -> St end. diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index e82282421e..206b0c6e7b 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -525,11 +525,6 @@ Erlang code. -export([type_inop_prec/1,type_preop_prec/1]). -export([map_anno/2, fold_anno/3, mapfold_anno/3, new_anno/1, anno_to_term/1, anno_from_term/1]). --export([set_line/2,get_attribute/2,get_attributes/1]). - --deprecated([{set_line, 2, next_major_release}, - {get_attribute, 2, next_major_release}, - {get_attributes, 1, next_major_release}]). %% The following directive is needed for (significantly) faster compilation %% of the generated .erl file by the HiPE compiler. Please do not remove. @@ -1118,28 +1113,6 @@ type_preop_prec('-') -> {600,700}; type_preop_prec('bnot') -> {600,700}; type_preop_prec('#') -> {700,800}. -%%% [Experimental]. The parser just copies the attributes of the -%%% scanner tokens to the abstract format. This design decision has -%%% been hidden to some extent: use set_line() and get_attribute() to -%%% access the second element of (almost all) of the abstract format -%%% tuples. A typical use is to negate line numbers to prevent the -%%% compiler from emitting warnings and errors. The second element can -%%% (of course) be set to any value, but then these functions no -%%% longer apply. To get all present attributes as a property list -%%% get_attributes() should be used. - --compile({nowarn_deprecated_function,{erl_scan,set_attribute,3}}). -set_line(L, F) -> - erl_scan:set_attribute(line, L, F). - --compile({nowarn_deprecated_function,{erl_scan,attributes_info,2}}). -get_attribute(L, Name) -> - erl_scan:attributes_info(L, Name). - --compile({nowarn_deprecated_function,{erl_scan,attributes_info,1}}). -get_attributes(L) -> - erl_scan:attributes_info(L). - -spec map_anno(Fun, Abstr) -> NewAbstr when Fun :: fun((Anno) -> Anno), Anno :: erl_anno:anno(), diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index d2f53816b8..47223b129c 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -52,25 +52,15 @@ %%% External exports -export([string/1,string/2,string/3,tokens/3,tokens/4, - format_error/1,reserved_word/1, - token_info/1,token_info/2, - attributes_info/1,attributes_info/2,set_attribute/3]). + format_error/1,reserved_word/1]). -export([column/1,end_location/1,line/1,location/1,text/1, category/1,symbol/1]). --deprecated([{attributes_info, 1, next_major_release}, - {attributes_info, 2, next_major_release}, - {set_attribute, 3, next_major_release}, - {token_info, 1, next_major_release}, - {token_info, 2, next_major_release}]). - %%% Private -export([continuation_location/1]). -export_type([error_info/0, - line/0, - location/0, options/0, return_cont/0, token/0, @@ -85,29 +75,18 @@ -define(ALINE(L), is_integer(L)). -define(STRING(S), is_list(S)). -define(RESWORDFUN(F), is_function(F, 1)). --define(SETATTRFUN(F), is_function(F, 1)). -type category() :: atom(). --type column() :: pos_integer(). % Deprecated --type line() :: integer(). % Deprecated --type location() :: line() | {line(),column()}. % Deprecated -type resword_fun() :: fun((atom()) -> boolean()). -type option() :: 'return' | 'return_white_spaces' | 'return_comments' | 'text' | {'reserved_word_fun', resword_fun()}. -type options() :: option() | [option()]. -type symbol() :: atom() | float() | integer() | string(). --type info_line() :: integer() | term(). --type attributes_data() - :: [{'column', column()} | {'line', info_line()} | {'text', string()}] - | {line(), column()}. -%% The fact that {line(),column()} is a possible attributes() type -%% is hidden. --type attributes() :: line() | attributes_data(). --type token() :: {category(), attributes(), symbol()} - | {category(), attributes()}. +-type token() :: {category(), Anno :: erl_anno:anno(), symbol()} + | {category(), Anno :: erl_anno:anno()}. -type tokens() :: [token()]. -type error_description() :: term(). --type error_info() :: {location(), module(), error_description()}. +-type error_info() :: {erl_anno:location(), module(), error_description()}. %%% Local record. -record(erl_scan, @@ -136,8 +115,8 @@ format_error(Other) -> String :: string(), Return :: {'ok', Tokens :: tokens(), EndLocation} | {'error', ErrorInfo :: error_info(), ErrorLocation}, - EndLocation :: location(), - ErrorLocation :: location(). + EndLocation :: erl_anno:location(), + ErrorLocation :: erl_anno:location(). string(String) -> string(String, 1, []). @@ -145,9 +124,9 @@ string(String) -> String :: string(), Return :: {'ok', Tokens :: tokens(), EndLocation} | {'error', ErrorInfo :: error_info(), ErrorLocation}, - StartLocation :: location(), - EndLocation :: location(), - ErrorLocation :: location(). + StartLocation :: erl_anno:location(), + EndLocation :: erl_anno:location(), + ErrorLocation :: erl_anno:location(). string(String, StartLocation) -> string(String, StartLocation, []). @@ -156,9 +135,9 @@ string(String, StartLocation) -> Options :: options(), Return :: {'ok', Tokens :: tokens(), EndLocation} | {'error', ErrorInfo :: error_info(), ErrorLocation}, - StartLocation :: location(), - EndLocation :: location(), - ErrorLocation :: location(). + StartLocation :: erl_anno:location(), + EndLocation :: erl_anno:location(), + ErrorLocation :: erl_anno:location(). string(String, Line, Options) when ?STRING(String), ?ALINE(Line) -> string1(String, options(Options), Line, no_col, []); string(String, {Line,Column}, Options) when ?STRING(String), @@ -167,20 +146,23 @@ string(String, {Line,Column}, Options) when ?STRING(String), string1(String, options(Options), Line, Column, []). -type char_spec() :: string() | 'eof'. --type cont_fun() :: fun((char_spec(), #erl_scan{}, line(), column(), +-type cont_fun() :: fun((char_spec(), #erl_scan{}, + erl_anno:line(), erl_anno:column(), tokens(), any()) -> any()). -opaque return_cont() :: {erl_scan_continuation, - string(), column(), tokens(), line(), + string(), erl_anno:column(), tokens(), + erl_anno:line(), #erl_scan{}, any(), cont_fun()}. --type tokens_result() :: {'ok', Tokens :: tokens(), EndLocation :: location()} - | {'eof', EndLocation :: location()} +-type tokens_result() :: {'ok', Tokens :: tokens(), + EndLocation :: erl_anno:location()} + | {'eof', EndLocation :: erl_anno:location()} | {'error', ErrorInfo :: error_info(), - EndLocation :: location()}. + EndLocation :: erl_anno:location()}. -spec tokens(Continuation, CharSpec, StartLocation) -> Return when Continuation :: return_cont() | [], CharSpec :: char_spec(), - StartLocation :: location(), + StartLocation :: erl_anno:location(), Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()} | {'more', Continuation1 :: return_cont()}. tokens(Cont, CharSpec, StartLocation) -> @@ -189,7 +171,7 @@ tokens(Cont, CharSpec, StartLocation) -> -spec tokens(Continuation, CharSpec, StartLocation, Options) -> Return when Continuation :: return_cont() | [], CharSpec :: char_spec(), - StartLocation :: location(), + StartLocation :: erl_anno:location(), Options :: options(), Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()} | {'more', Continuation1 :: return_cont()}. @@ -257,155 +239,6 @@ symbol({_Category,_Anno,Symbol}) -> symbol(T) -> erlang:error(badarg, [T]). --type attribute_item() :: 'column' | 'length' | 'line' - | 'location' | 'text'. --type info_location() :: location() | term(). --type attribute_info() :: {'column', column()}| {'length', pos_integer()} - | {'line', info_line()} - | {'location', info_location()} - | {'text', string()}. --type token_item() :: 'category' | 'symbol' | attribute_item(). --type token_info() :: {'category', category()} | {'symbol', symbol()} - | attribute_info(). - --spec token_info(Token) -> TokenInfo when - Token :: token(), - TokenInfo :: [TokenInfoTuple :: token_info()]. -token_info(Token) -> - Items = [category,column,length,line,symbol,text], % undefined order - token_info(Token, Items). - --spec token_info(Token, TokenItem) -> TokenInfoTuple | 'undefined' when - Token :: token(), - TokenItem :: token_item(), - TokenInfoTuple :: token_info(); - (Token, TokenItems) -> TokenInfo when - Token :: token(), - TokenItems :: [TokenItem :: token_item()], - TokenInfo :: [TokenInfoTuple :: token_info()]. -token_info(_Token, []) -> - []; -token_info(Token, [Item|Items]) when is_atom(Item) -> - case token_info(Token, Item) of - undefined -> - token_info(Token, Items); - TokenInfo when is_tuple(TokenInfo) -> - [TokenInfo|token_info(Token, Items)] - end; -token_info({Category,_Attrs}, category=Item) -> - {Item,Category}; -token_info({Category,_Attrs,_Symbol}, category=Item) -> - {Item,Category}; -token_info({Category,_Attrs}, symbol=Item) -> - {Item,Category}; -token_info({_Category,_Attrs,Symbol}, symbol=Item) -> - {Item,Symbol}; -token_info({_Category,Attrs}, Item) -> - attributes_info(Attrs, Item); -token_info({_Category,Attrs,_Symbol}, Item) -> - attributes_info(Attrs, Item). - --spec attributes_info(Attributes) -> AttributesInfo when - Attributes :: attributes(), - AttributesInfo :: [AttributeInfoTuple :: attribute_info()]. -attributes_info(Attributes) -> - Items = [column,length,line,text], % undefined order - attributes_info(Attributes, Items). - --spec attributes_info - (Attributes, AttributeItem) -> AttributeInfoTuple | 'undefined' when - Attributes :: attributes(), - AttributeItem :: attribute_item(), - AttributeInfoTuple :: attribute_info(); - (Attributes, AttributeItems) -> AttributeInfo when - Attributes :: attributes(), - AttributeItems :: [AttributeItem :: attribute_item()], - AttributeInfo :: [AttributeInfoTuple :: attribute_info()]. -attributes_info(_Attrs, []) -> - []; -attributes_info(Attrs, [A|As]) when is_atom(A) -> - case attributes_info(Attrs, A) of - undefined -> - attributes_info(Attrs, As); - AttributeInfo when is_tuple(AttributeInfo) -> - [AttributeInfo|attributes_info(Attrs, As)] - end; -attributes_info({Line,Column}, column=Item) when ?ALINE(Line), - ?COLUMN(Column) -> - {Item,Column}; -attributes_info(Line, column) when ?ALINE(Line) -> - undefined; -attributes_info(Attrs, column=Item) -> - case attr_info(Attrs, Item) of - undefined -> - case erl_anno:column(Attrs) of - undefined -> - undefined; - Column -> - {Item,Column} - end; - T -> - T - end; -attributes_info(Attrs, length=Item) -> - case attributes_info(Attrs, text) of - undefined -> - undefined; - {text,Text} -> - {Item,length(Text)} - end; -attributes_info(Line, line=Item) when ?ALINE(Line) -> - {Item,Line}; -attributes_info({Line,Column}, line=Item) when ?ALINE(Line), - ?COLUMN(Column) -> - {Item,Line}; -attributes_info(Attrs, line=Item) -> - case attr_info(Attrs, Item) of - undefined -> - case attr_info(Attrs, location) of - {location,{Line,_Column}} -> - {Item,Line}; - {location,Line} -> - {Item,Line}; - undefined -> - undefined - end; - T -> - T - end; -attributes_info({Line,Column}=Location, location=Item) when ?ALINE(Line), - ?COLUMN(Column) -> - {Item,Location}; -attributes_info(Line, location=Item) when ?ALINE(Line) -> - {Item,Line}; -attributes_info(Attrs, location=Item) -> - {line,Line} = attributes_info(Attrs, line), - case attributes_info(Attrs, column) of - undefined -> - %% If set_attribute() has assigned a term such as {17,42} - %% to 'line', then Line will look like {Line,Column}. One - %% should not use 'location' but 'line' and 'column' in - %% such special cases. - {Item,Line}; - {column,Column} -> - {Item,{Line,Column}} - end; -attributes_info({Line,Column}, text) when ?ALINE(Line), ?COLUMN(Column) -> - undefined; -attributes_info(Line, text) when ?ALINE(Line) -> - undefined; -attributes_info(Attrs, text=Item) -> - attr_info(Attrs, Item); -attributes_info(T1, T2) -> - erlang:error(badarg, [T1,T2]). - --spec set_attribute(AttributeItem, Attributes, SetAttributeFun) -> Attributes when - AttributeItem :: 'line', - Attributes :: attributes(), - SetAttributeFun :: fun((info_line()) -> info_line()). -set_attribute(Tag, Attributes, Fun) when ?SETATTRFUN(Fun) -> - set_attr(Tag, Attributes, Fun). - %%% %%% Local functions %%% @@ -471,62 +304,6 @@ expand_opt(return, Os) -> expand_opt(O, Os) -> [O|Os]. -attr_info(Attrs, Item) -> - try lists:keyfind(Item, 1, Attrs) of - {_Item, _Value} = T -> - T; - false -> - undefined - catch - _:_ -> - erlang:error(badarg, [Attrs, Item]) - end. - --spec set_attr('line', attributes(), fun((line()) -> line())) -> attributes(). - -set_attr(line, Line, Fun) when ?ALINE(Line) -> - Ln = Fun(Line), - if - ?ALINE(Ln) -> - Ln; - true -> - [{line,Ln}] - end; -set_attr(line, {Line,Column}, Fun) when ?ALINE(Line), ?COLUMN(Column) -> - Ln = Fun(Line), - if - ?ALINE(Ln) -> - {Ln,Column}; - true -> - [{line,Ln},{column,Column}] - end; -set_attr(line=Tag, Attrs, Fun) when is_list(Attrs) -> - case lists:keyfind(Tag, 1, Attrs) of - {line,Line} -> - case lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)}) of - [{line,Ln}] when ?ALINE(Ln) -> - Ln; - As -> - As - end; - false -> - {location, Location} = lists:keyfind(location, 1, Attrs), - Ln = case Location of - {Line,Column} when ?ALINE(Line), ?COLUMN(Column) -> - {Fun(Line),Column}; - _ -> - Fun(Location) - end, - case lists:keyreplace(location, 1, Attrs, {location,Ln}) of - [{location,Ln}] when ?ALINE(Ln) -> - Ln; - As -> - As - end - end; -set_attr(T1, T2, T3) -> - erlang:error(badarg, [T1,T2,T3]). - tokens1(Cs, St, Line, Col, Toks, Fun, Any) when ?STRING(Cs); Cs =:= eof -> case Fun(Cs, St, Line, Col, Toks, Any) of {more,{Cs0,Ncol,Ntoks,Nline,Nany,Nfun}} -> diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 2d77888512..27e195e1f3 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -597,38 +597,29 @@ obsolete_1(core_lib, is_literal_list, 1) -> obsolete_1(core_lib, literal_value, 1) -> {deprecated,{core_lib,concrete,1}}; obsolete_1(erl_scan, set_attribute, 3) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:set_line/2 instead"}; + {removed,{erl_anno,set_line,2},"19.0"}; obsolete_1(erl_scan, attributes_info, 1) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_scan, attributes_info, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_scan, token_info, 1) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_scan:{category,column,line,location,symbol,text}/1 instead"}; obsolete_1(erl_scan, token_info, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_scan:{category,column,line,location,symbol,text}/1 instead"}; obsolete_1(erl_parse, set_line, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:set_line/2 instead"}; + {removed,{erl_anno,set_line,2},"19.0"}; obsolete_1(erl_parse, get_attributes, 1) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_parse, get_attribute, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use " + {removed,"removed in 19.0; use " "erl_anno:{column,line,location,text}/1 instead"}; obsolete_1(erl_lint, modify_line, 2) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_parse:map_anno/2 instead"}; + {removed,{erl_parse,map_anno,2},"19.0"}; obsolete_1(ssl, negotiated_next_protocol, 1) -> {deprecated,{ssl,negotiated_protocol,1}}; @@ -698,26 +689,24 @@ is_snmp_agent_function(_, _) -> false. -spec obsolete_type(module(), atom(), arity()) -> 'no' | {tag(), string()} | {tag(), mfas(), release()}. +-dialyzer({no_match, obsolete_type/3}). obsolete_type(Module, Name, NumberOfVariables) -> case obsolete_type_1(Module, Name, NumberOfVariables) of -%% {deprecated=Tag,{_,_,_}=Replacement} -> -%% {Tag,Replacement,"in a future release"}; + {deprecated=Tag,{_,_,_}=Replacement} -> + {Tag,Replacement,"in a future release"}; {_,String}=Ret when is_list(String) -> Ret; -%% {_,_,_}=Ret -> -%% Ret; + {_,_,_}=Ret -> + Ret; no -> no end. obsolete_type_1(erl_scan,column,0) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:column() instead"}; + {removed,{erl_anno,column,0},"19.0"}; obsolete_type_1(erl_scan,line,0) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:line() instead"}; + {removed,{erl_anno,line,0},"19.0"}; obsolete_type_1(erl_scan,location,0) -> - {deprecated, - "deprecated (will be removed in OTP 19); use erl_anno:location() instead"}; + {removed,{erl_anno,location,0},"19.0"}; obsolete_type_1(_,_,_) -> no. diff --git a/lib/stdlib/test/erl_anno_SUITE.erl b/lib/stdlib/test/erl_anno_SUITE.erl index 66b02151a0..0369455846 100644 --- a/lib/stdlib/test/erl_anno_SUITE.erl +++ b/lib/stdlib/test/erl_anno_SUITE.erl @@ -34,7 +34,7 @@ init_per_testcase/2, end_per_testcase/2]). -export([new/1, is_anno/1, generated/1, end_location/1, file/1, - line/1, location/1, record/1, text/1, bad/1, neg_line/1]). + line/1, location/1, record/1, text/1, bad/1]). -export([parse_abstract/1, mapfold_anno/1]). @@ -43,7 +43,7 @@ all() -> groups() -> [{anno, [], [new, is_anno, generated, end_location, file, - line, location, record, text, bad, neg_line]}, + line, location, record, text, bad]}, {parse, [], [parse_abstract, mapfold_anno]}]. suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -229,74 +229,6 @@ bad(_Config) -> (catch erl_anno:record(bad)), % 1st arg not opaque ok. -neg_line(doc) -> - ["Test negative line numbers (OTP 18)"]; -neg_line(_Config) -> - neg_line1(false), - neg_line1(true), - ok. - -neg_line1(TextToo) -> - Minus8_0 = erl_anno:new(-8), - Plus8_0 = erl_anno:new(8), - Minus8C_0 = erl_anno:new({-8, 17}), - Plus8C_0 = erl_anno:new({8, 17}), - - [Minus8, Plus8, Minus8C, Plus8C] = - [case TextToo of - true -> - erl_anno:set_text("foo", A); - false -> - A - end || A <- [Minus8_0, Plus8_0, Minus8C_0, Plus8C_0]], - - tst(-3, erl_anno:set_location(3, Minus8)), - tst(-3, erl_anno:set_location(-3, Plus8)), - tst(-3, erl_anno:set_location(-3, Minus8)), - tst({-3,9}, erl_anno:set_location({3, 9}, Minus8)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8)), - tst(-3, erl_anno:set_location(3, Minus8C)), - tst(-3, erl_anno:set_location(-3, Plus8C)), - tst(-3, erl_anno:set_location(-3, Minus8C)), - tst({-3,9}, erl_anno:set_location({3, 9}, Minus8C)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8C)), - tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8C)), - - tst(-8, erl_anno:set_generated(true, Plus8)), - tst(-8, erl_anno:set_generated(true, Minus8)), - tst({-8,17}, erl_anno:set_generated(true, Plus8C)), - tst({-8,17}, erl_anno:set_generated(true, Minus8C)), - tst(8, erl_anno:set_generated(false, Plus8)), - tst(8, erl_anno:set_generated(false, Minus8)), - tst({8,17}, erl_anno:set_generated(false, Plus8C)), - tst({8,17}, erl_anno:set_generated(false, Minus8C)), - - tst(-3, erl_anno:set_line(3, Minus8)), - tst(-3, erl_anno:set_line(-3, Plus8)), - tst(-3, erl_anno:set_line(-3, Minus8)), - tst({-3,17}, erl_anno:set_line(3, Minus8C)), - tst({-3,17}, erl_anno:set_line(-3, Plus8C)), - tst({-3,17}, erl_anno:set_line(-3, Minus8C)), - ok. - -tst(Term, Anno) -> - ?format("Term: ~p\n", [Term]), - ?format("Anno: ~p\n", [Anno]), - case anno_to_term(Anno) of - Term -> - ok; - Else -> - case lists:keyfind(location, 1, Else) of - {location, Term} -> - ok; - _Else2 -> - ?format("Else2 ~p\n", [_Else2]), - io:format("expected ~p\n got ~p\n", [Term, Else]), - exit({Term, Else}) - end - end. - parse_abstract(doc) -> ["Test erl_parse:new_anno/1, erl_parse:anno_to_term/1" ", and erl_parse:anno_from_term/1"]; diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 0424e2b967..6c07dc1ec6 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -65,7 +65,7 @@ too_many_arguments/1, basic_errors/1,bin_syntax_errors/1, predef/1, - maps/1,maps_type/1,otp_11851/1,otp_12195/1 + maps/1,maps_type/1,otp_11851/1 ]). % Default timetrap timeout (set in init_per_testcase). @@ -94,7 +94,7 @@ all() -> bif_clash, behaviour_basic, behaviour_multiple, otp_11861, otp_7550, otp_8051, format_warn, {group, on_load}, too_many_arguments, basic_errors, bin_syntax_errors, predef, - maps, maps_type, otp_11851, otp_12195]. + maps, maps_type, otp_11851]. groups() -> [{unused_vars_warn, [], @@ -3835,40 +3835,6 @@ otp_11851(Config) when is_list(Config) -> [] = run(Config, Ts), ok. -otp_12195(doc) -> - "OTP-12195: Check obsolete types (tailor made for OTP 18)."; -otp_12195(Config) when is_list(Config) -> - Ts = [{otp_12195_1, - <<"-export_type([r1/0]). - -type r1() :: erl_scan:line() - | erl_scan:column() - | erl_scan:location() - | erl_anno:line().">>, - [], - {warnings,[{2,erl_lint, - {deprecated_type,{erl_scan,line,0}, - "deprecated (will be removed in OTP 19); " - "use erl_anno:line() instead"}}, - {3,erl_lint, - {deprecated_type,{erl_scan,column,0}, - "deprecated (will be removed in OTP 19); use " - "erl_anno:column() instead"}}, - {4,erl_lint, - {deprecated_type,{erl_scan,location,0}, - "deprecated (will be removed in OTP 19); " - "use erl_anno:location() instead"}}]}}, - {otp_12195_2, - <<"-export_type([r1/0]). - -compile(nowarn_deprecated_type). - -type r1() :: erl_scan:line() - | erl_scan:column() - | erl_scan:location() - | erl_anno:line().">>, - [], - []}], - [] = run(Config, Ts), - ok. - run(Config, Tests) -> F = fun({N,P,Ws,E}, BadL) -> case catch run_test(Config, P, Ws) of diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl index 12ea3d128c..db669aae99 100644 --- a/lib/stdlib/test/erl_scan_SUITE.erl +++ b/lib/stdlib/test/erl_scan_SUITE.erl @@ -191,8 +191,7 @@ otp_7810(Config) when is_list(Config) -> ?line ok = more_chars(), ?line ok = more_options(), - ?line ok = attributes_info(), - ?line ok = set_attribute(), + ?line ok = anno_info(), ok. @@ -269,7 +268,7 @@ punctuations() -> comments() -> ?line test("a %%\n b"), - {ok,[],1} = erl_scan_string("%"), + ?line {ok,[],1} = erl_scan_string("%"), ?line test("a %%\n b"), {ok,[{atom,{1,1},a},{atom,{2,2},b}],{2,3}} = erl_scan_string("a %%\n b", {1,1}), @@ -338,7 +337,7 @@ base_integers() -> erl_scan:string(Str) end || {BS,S} <- [{"3","3"},{"15","f"}, {"12","c"}] ], - {ok,[{integer,1,239},{'@',1}],1} = erl_scan_string("16#ef@"), + ?line {ok,[{integer,1,239},{'@',1}],1} = erl_scan_string("16#ef@"), {ok,[{integer,{1,1},239},{'@',{1,6}}],{1,7}} = erl_scan_string("16#ef@", {1,1}, []), {ok,[{integer,{1,1},14},{atom,{1,5},g@}],{1,7}} = @@ -387,20 +386,15 @@ dots() -> R2 = erl_scan_string(S, {1,1}, []) end || {S, R, R2} <- Dot], - ?line {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text), - ?line [{column,1},{length,1},{line,1},{text,"."}] = - erl_scan:token_info(T1, [column, length, line, text]), - ?line {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text), - ?line [{column,1},{length,1},{line,1},{text,"."}] = - erl_scan:token_info(T2, [column, length, line, text]), - ?line {ok,[{dot,_}=T3],{1,6}} = + {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text), + [1, 1, "."] = token_info(T1), + {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text), + [1, 1, "."] = token_info(T2), + {ok,[{dot,_}=T3],{1,6}} = erl_scan:string(".% öh", {1,1}, text), - ?line [{column,1},{length,1},{line,1},{text,"."}] = - erl_scan:token_info(T3, [column, length, line, text]), - ?line {error,{{1,2},erl_scan,char},{1,3}} = - erl_scan:string(".$", {1,1}), - ?line {error,{{1,2},erl_scan,char},{1,4}} = - erl_scan:string(".$\\", {1,1}), + [1, 1, "."] = token_info(T3), + {error,{{1,2},erl_scan,char},{1,3}} = erl_scan:string(".$", {1,1}), + {error,{{1,2},erl_scan,char},{1,4}} = erl_scan:string(".$\\", {1,1}), test_string(". ", [{dot,{1,1}}]), test_string(". ", [{dot,{1,1}}]), @@ -413,18 +407,18 @@ dots() -> test_string(".a", [{'.',{1,1}},{atom,{1,2},a}]), test_string("%. \n. ", [{dot,{2,1}}]), - ?line {more,C} = erl_scan:tokens([], "%. ",{1,1}, return), + {more,C} = erl_scan:tokens([], "%. ",{1,1}, return), {done,{ok,[{comment,{1,1},"%. "}, {white_space,{1,4},"\n"}, {dot,{2,1}}], {2,3}}, ""} = erl_scan_tokens(C, "\n. ", {1,1}, return), % any loc, any options - ?line [test_string(S, R) || - {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]}, - {"$\\\n", [{char,{1,1},$\n}]}, - {"'\\\n'", [{atom,{1,1},'\n'}]}, - {"$\n", [{char,{1,1},$\n}]}] ], + [test_string(S, R) || + {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]}, + {"$\\\n", [{char,{1,1},$\n}]}, + {"'\\\n'", [{atom,{1,1},'\n'}]}, + {"$\n", [{char,{1,1},$\n}]}] ], ok. chars() -> @@ -540,8 +534,8 @@ eof() -> %% A dot followed by eof is special: ?line {more, C} = erl_scan:tokens([], "a.", 1), - {done,{ok,[{atom,1,a},{dot,1}],1},eof} = erl_scan_tokens(C,eof,1), - {ok,[{atom,1,foo},{dot,1}],1} = erl_scan_string("foo."), + ?line {done,{ok,[{atom,1,a},{dot,1}],1},eof} = erl_scan_tokens(C,eof,1), + ?line {ok,[{atom,1,foo},{dot,1}],1} = erl_scan_string("foo."), %% With column. {more, CCol} = erl_scan:tokens([], "a.", {1,1}), @@ -655,145 +649,72 @@ options() -> ok. more_options() -> - ?line {ok,[{atom,A1,foo}],{19,20}} = + {ok,[{atom,_,foo}=T1],{19,20}} = erl_scan:string("foo", {19,17},[]), - ?line [{column,17},{line,19}] = erl_scan:attributes_info(A1), - ?line {done,{ok,[{atom,A2,foo},{dot,_}],{19,22}},[]} = + {19,17} = erl_scan:location(T1), + {done,{ok,[{atom,_,foo}=T2,{dot,_}],{19,22}},[]} = erl_scan:tokens([], "foo. ", {19,17}, [bad_opt]), % type error - ?line [{column,17},{line,19}] = erl_scan:attributes_info(A2), - ?line {ok,[{atom,A3,foo}],{19,20}} = + {19,17} = erl_scan:location(T2), + {ok,[{atom,_,foo}=T3],{19,20}} = erl_scan:string("foo", {19,17},[text]), - ?line [{column,17},{length,3},{line,19},{text,"foo"}] = - erl_scan:attributes_info(A3), + {19,17} = erl_scan:location(T3), + "foo" = erl_scan:text(T3), - ?line {ok,[{atom,A4,foo}],1} = erl_scan:string("foo", 1, [text]), - ?line [{length,3},{line,1},{text,"foo"}] = erl_scan:attributes_info(A4), + {ok,[{atom,_,foo}=T4],1} = erl_scan:string("foo", 1, [text]), + 1 = erl_scan:line(T4), + 1 = erl_scan:location(T4), + "foo" = erl_scan:text(T4), ok. token_info() -> - ?line {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]), + {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]), {'EXIT',{badarg,_}} = - (catch {foo, erl_scan:token_info(T1, foo)}), % type error - ?line {line,1} = erl_scan:token_info(T1, line), - ?line {column,18} = erl_scan:token_info(T1, column), - ?line {length,3} = erl_scan:token_info(T1, length), - ?line {text,"foo"} = erl_scan:token_info(T1, text), - ?line [{category,atom},{column,18},{length,3},{line,1}, - {symbol,foo},{text,"foo"}] = - erl_scan:token_info(T1), - ?line [{length,3},{column,18}] = - erl_scan:token_info(T1, [length, column]), - ?line [{location,{1,18}}] = - erl_scan:token_info(T1, [location]), - ?line {category,atom} = erl_scan:token_info(T1, category), - ?line [{symbol,foo}] = erl_scan:token_info(T1, [symbol]), - - ?line {ok,[T2],_} = erl_scan:string("foo", 1, []), - ?line {line,1} = erl_scan:token_info(T2, line), - ?line undefined = erl_scan:token_info(T2, column), - ?line undefined = erl_scan:token_info(T2, length), - ?line undefined = erl_scan:token_info(T2, text), - ?line {location,1} = erl_scan:token_info(T2, location), - ?line [{category,atom},{line,1},{symbol,foo}] = erl_scan:token_info(T2), - ?line [{line,1}] = erl_scan:token_info(T2, [length, line]), - - ?line {ok,[T3],_} = erl_scan:string("=", 1, []), - ?line [{line,1}] = erl_scan:token_info(T3, [column, line]), - ?line {category,'='} = erl_scan:token_info(T3, category), - ?line [{symbol,'='}] = erl_scan:token_info(T3, [symbol]), + (catch {foo, erl_scan:category(foo)}), % type error + {'EXIT',{badarg,_}} = + (catch {foo, erl_scan:symbol(foo)}), % type error + atom = erl_scan:category(T1), + foo = erl_scan:symbol(T1), + + {ok,[T2],_} = erl_scan:string("foo", 1, []), + 1 = erl_scan:line(T2), + undefined = erl_scan:column(T2), + undefined = erl_scan:text(T2), + 1 = erl_scan:location(T2), + + {ok,[T3],_} = erl_scan:string("=", 1, []), + '=' = erl_scan:category(T3), + '=' = erl_scan:symbol(T3), ok. -attributes_info() -> - ?line {'EXIT',_} = - (catch {foo,erl_scan:attributes_info(foo)}), % type error - [{line,18}] = erl_scan:attributes_info(erl_anno:new(18)), - {location,19} = - erl_scan:attributes_info(erl_anno:new(19), location), - ?line {ok,[{atom,A0,foo}],_} = erl_scan:string("foo", 19, [text]), - ?line {location,19} = erl_scan:attributes_info(A0, location), - - ?line {ok,[{atom,A3,foo}],_} = erl_scan:string("foo", {1,3}, [text]), - ?line {line,1} = erl_scan:attributes_info(A3, line), - ?line {column,3} = erl_scan:attributes_info(A3, column), - ?line {location,{1,3}} = erl_scan:attributes_info(A3, location), - ?line {text,"foo"} = erl_scan:attributes_info(A3, text), - - ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", 2, [text]), - ?line {line,2} = erl_scan:attributes_info(A4, line), - ?line undefined = erl_scan:attributes_info(A4, column), - ?line {location,2} = erl_scan:attributes_info(A4, location), - ?line {text,"foo"} = erl_scan:attributes_info(A4, text), - - ?line {ok,[{atom,A5,foo}],_} = erl_scan:string("foo", {1,3}, []), - ?line {line,1} = erl_scan:attributes_info(A5, line), - ?line {column,3} = erl_scan:attributes_info(A5, column), - ?line {location,{1,3}} = erl_scan:attributes_info(A5, location), - ?line undefined = erl_scan:attributes_info(A5, text), - - ?line undefined = erl_scan:attributes_info([], line), % type error +anno_info() -> + {'EXIT',_} = + (catch {foo,erl_scan:line(foo)}), % type error + {ok,[{atom,_,foo}=T0],_} = erl_scan:string("foo", 19, [text]), + 19 = erl_scan:location(T0), + 19 = erl_scan:end_location(T0), + + {ok,[{atom,_,foo}=T3],_} = erl_scan:string("foo", {1,3}, [text]), + 1 = erl_scan:line(T3), + 3 = erl_scan:column(T3), + {1,3} = erl_scan:location(T3), + {1,6} = erl_scan:end_location(T3), + "foo" = erl_scan:text(T3), + + {ok,[{atom,_,foo}=T4],_} = erl_scan:string("foo", 2, [text]), + 2 = erl_scan:line(T4), + undefined = erl_scan:column(T4), + 2 = erl_scan:location(T4), + "foo" = erl_scan:text(T4), + + {ok,[{atom,_,foo}=T5],_} = erl_scan:string("foo", {1,3}, []), + 1 = erl_scan:line(T5), + 3 = erl_scan:column(T5), + {1,3} = erl_scan:location(T5), + undefined = erl_scan:text(T5), ok. -set_attribute() -> - F = fun(Line) -> -Line end, - Anno2 = erl_anno:new(2), - A0 = erl_scan:set_attribute(line, Anno2, F), - {line, -2} = erl_scan:attributes_info(A0, line), - ?line {ok,[{atom,A1,foo}],_} = erl_scan:string("foo", {9,17}), - ?line A2 = erl_scan:set_attribute(line, A1, F), - ?line {line,-9} = erl_scan:attributes_info(A2, line), - ?line {location,{-9,17}} = erl_scan:attributes_info(A2, location), - ?line [{line,-9},{column,17}] = - erl_scan:attributes_info(A2, [line,column,text]), - - F2 = fun(Line) -> {17,Line} end, - ?line Attr1 = erl_scan:set_attribute(line, 2, F2), - ?line {line,{17,2}} = erl_scan:attributes_info(Attr1, line), - ?line undefined = erl_scan:attributes_info(Attr1, column), - ?line {location,{17,2}} = % a bit mixed up - erl_scan:attributes_info(Attr1, location), - - ?line A3 = erl_scan:set_attribute(line, A1, F2), - ?line {line,{17,9}} = erl_scan:attributes_info(A3, line), - ?line {location,{{17,9},17}} = erl_scan:attributes_info(A3, location), - ?line [{line,{17,9}},{column,17}] = - erl_scan:attributes_info(A3, [line,column,text]), - - ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", {9,17}, [text]), - ?line A5 = erl_scan:set_attribute(line, A4, F), - ?line {line,-9} = erl_scan:attributes_info(A5, line), - ?line {location,{-9,17}} = erl_scan:attributes_info(A5, location), - ?line [{line,-9},{column,17},{text,"foo"}] = - erl_scan:attributes_info(A5, [line,column,text]), - - ?line {ok,[{atom,A6,foo}],_} = erl_scan:string("foo", 11, [text]), - ?line A7 = erl_scan:set_attribute(line, A6, F2), - %% Incompatible with pre 18: - %% {line,{17,11}} = erl_scan:attributes_info(A7, line), - {line,17} = erl_scan:attributes_info(A7, line), - ?line {location,{17,11}} = % mixed up - erl_scan:attributes_info(A7, location), - %% Incompatible with pre 18: - %% [{line,{17,11}},{text,"foo"}] = - %% erl_scan:attributes_info(A7, [line,column,text]), - [{line,17},{column,11},{text,"foo"}] = - erl_scan:attributes_info(A7, [line,column,text]), - - ?line {'EXIT',_} = - (catch {foo, erl_scan:set_attribute(line, [], F2)}), % type error - ?line {'EXIT',{badarg,_}} = - (catch {foo, erl_scan:set_attribute(column, [], F2)}), % type error - - Attr10 = erl_anno:new(8), - Attr20 = erl_scan:set_attribute(line, Attr10, - fun(L) -> {nos,'X',L} end), - %% OTP-9412 - Attr30 = erl_scan:set_attribute(line, Attr20, - fun({nos,_V,VL}) -> VL end), - 8 = erl_anno:to_term(Attr30), - ok. - column_errors() -> ?line {error,{{1,1},erl_scan,{string,$',""}},{1,3}} = % $' erl_scan:string("'\\",{1,1}), @@ -892,14 +813,13 @@ unicode() -> erl_scan_string(Qs, 1), {ok,[Q2],{1,9}} = erl_scan:string("$\\x{aaa}", {1,1}, [text]), - [{category,char},{column,1},{length,8}, - {line,1},{symbol,16#aaa},{text,Qs}] = - erl_scan:token_info(Q2), + [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] = + token_info_long(Q2), U1 = "\"\\x{aaa}\"", - {ok,[{string,A1,[2730]}],{1,10}} = erl_scan:string(U1, {1,1}, [text]), - [{line,1},{column,1},{text,"\"\\x{aaa}\""}] = - erl_scan:attributes_info(A1, [line, column, text]), + {ok,[{string,_,[2730]}=T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]), + {1,1} = erl_scan:location(T1), + "\"\\x{aaa}\"" = erl_scan:text(T1), {ok,[{string,1,[2730]}],1} = erl_scan_string(U1, 1), U2 = "\"\\x41\\x{fff}\\x42\"", @@ -1012,16 +932,13 @@ otp_10302(Config) when is_list(Config) -> Qs = "$\\x{aaa}", {ok,[{char,1,2730}],1} = erl_scan_string(Qs, 1), {ok,[Q2],{1,9}} = erl_scan:string(Qs,{1,1},[text]), - [{category,char},{column,1},{length,8}, - {line,1},{symbol,16#aaa},{text,Qs}] = - erl_scan:token_info(Q2), - - Tags = [category, column, length, line, symbol, text], + [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] = + token_info_long(Q2), U1 = "\"\\x{aaa}\"", {ok,[T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]), - [{category,string},{column,1},{length,9},{line,1}, - {symbol,[16#aaa]},{text,U1}] = erl_scan:token_info(T1, Tags), + [{category,string},{column,1},{line,1},{symbol,[16#aaa]},{text,U1}] = + token_info_long(T1), U2 = "\"\\x41\\x{fff}\\x42\"", {ok,[{string,1,[65,4095,66]}],1} = erl_scan_string(U2, 1), @@ -1353,9 +1270,7 @@ test_wsc([], []) -> ok; test_wsc([Token|Tokens], [Token2|Tokens2]) -> [Text, Text2] = [Text || - {text, Text} <- - [erl_scan:token_info(T, text) || - T <- [Token, Token2]]], + Text <- [erl_scan:text(T) || T <- [Token, Token2]]], Sz = erts_debug:size(Text), Sz2 = erts_debug:size({Text, Text2}), IsCompacted = Sz2 < 2*Sz+erts_debug:size({a,a}), @@ -1394,7 +1309,7 @@ all_same(L, Char) -> newlines_first([]) -> ok; newlines_first([Token|Tokens]) -> - {text,Text} = erl_scan:token_info(Token, text), + Text = erl_scan:text(Token), Nnls = length([C || C <- Text, C =:= $\n]), OK = case Text of [$\n|_] -> @@ -1414,7 +1329,7 @@ select_tokens(Tokens, Tags) -> lists:filter(fun(T) -> lists:member(element(1, T), Tags) end, Tokens). simplify([Token|Tokens]) -> - {line,Line} = erl_scan:token_info(Token, line), + Line = erl_scan:line(Token), [setelement(2, Token, erl_anno:new(Line)) | simplify(Tokens)]; simplify([]) -> []. @@ -1423,17 +1338,31 @@ get_text(Tokens) -> lists:flatten( [T || Token <- Tokens, - ({text,T} = erl_scan:token_info(Token, text)) =/= []]). + (T = erl_scan:text(Token)) =/= []]). test_decorated_tokens(String, Tokens) -> ToksAttrs = token_attrs(Tokens), test_strings(ToksAttrs, String, 1, 1). token_attrs(Tokens) -> - [{L,C,Len,T} || + [{L,C,length(T),T} || Token <- Tokens, - ([{line,L},{column,C},{length,Len},{text,T}] = - erl_scan:token_info(Token, [line,column,length,text])) =/= []]. + ([C,L,T] = token_info(Token)) =/= []]. + +token_info(T) -> + Column = erl_scan:column(T), + Line = erl_scan:line(T), + Text = erl_scan:text(T), + [Column, Line, Text]. + +token_info_long(T) -> + Column = erl_scan:column(T), + Line = erl_scan:line(T), + Text = erl_scan:text(T), + Category = erl_scan:category(T), + Symbol = erl_scan:symbol(T), + [{category,Category},{column,Column},{line,Line}, + {symbol,Symbol},{text,Text}]. test_strings([], _S, Line, Column) -> {Line,Column}; @@ -1514,8 +1443,7 @@ consistent_attributes([Ts | TsL]) -> L = [T || T <- Ts, is_integer(element(2, T))], case L of [] -> - TagsL = [[Tag || {Tag,_} <- - erl_scan:attributes_info(element(2, T))] || + TagsL = [[Tag || {Tag,_} <- defined(token_info_long(T))] || T <- Ts], case lists:usort(TagsL) of [_] -> @@ -1531,6 +1459,9 @@ consistent_attributes([Ts | TsL]) -> Ts end. +defined(L) -> + [{T,V} || {T,V} <- L, V =/= undefined]. + family_list(L) -> sofs:to_external(family(L)). -- cgit v1.2.3 From 7fd49429e85a1fe2c24b76bd5d3d8dfddc908822 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 30 Jun 2015 16:25:49 +0200 Subject: debugger: Fix a bug related to the use of the erl_anno module The (harmless) bug was introduced in 541e87f. --- lib/debugger/src/dbg_iload.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl index 2a8bcd32d8..7746a06fcb 100644 --- a/lib/debugger/src/dbg_iload.erl +++ b/lib/debugger/src/dbg_iload.erl @@ -541,7 +541,7 @@ fun_clauses([]) -> []. new_map(Fs0, Anno, F) -> Line = ln(Anno), Fs1 = map_fields(Fs0, F), - Fs2 = [{ln(A),K,V} || {map_field_assoc,A,K,V} <- Fs1], + Fs2 = [{L,K,V} || {map_field_assoc,L,K,V} <- Fs1], try {value,Line,map_literal(Fs2, #{})} catch -- cgit v1.2.3 From 5ba36a3857eb2673d28fd33ec4655da41ee78d3d Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 30 Jun 2015 16:43:02 +0200 Subject: test_server: Fix a bug related to the use of the erl_anno module The (harmless) bug was introduced in 42cf8b8. --- lib/test_server/src/erl2html2.erl | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl index 2c63103264..e281c9de1b 100644 --- a/lib/test_server/src/erl2html2.erl +++ b/lib/test_server/src/erl2html2.erl @@ -170,23 +170,32 @@ get_line(Anno) -> %%%----------------------------------------------------------------- %%% Find the line number of the last expression in the function find_clause_lines([{clause,CL,_Params,_Op,Exprs}], CLs) -> % last clause - try tuple_to_list(lists:last(Exprs)) of - [_Type,ExprLine | _] when is_integer(ExprLine) -> - {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)}; - [tree,_ | Exprs1] -> + case classify_exprs(Exprs) of + {anno, Anno} -> + {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(Anno)}; + {tree, Exprs1} -> find_clause_lines([{clause,CL,undefined,undefined,Exprs1}], CLs); - [macro,{_var,ExprLine,_MACRO} | _] when is_integer(ExprLine) -> - {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)}; - _ -> - {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)} - catch - _:_ -> + unknown -> {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)} end; - find_clause_lines([{clause,CL,_Params,_Op,_Exprs} | Cs], CLs) -> find_clause_lines(Cs, [{clause,get_line(CL)}|CLs]). +classify_exprs(Exprs) -> + case tuple_to_list(lists:last(Exprs)) of + [macro,{_var,Anno,_MACRO} | _] -> + {anno, Anno}; + [T,ExprAnno | Exprs1] -> + case erl_anno:is_anno(ExprAnno) of + true -> + {anno, ExprAnno}; + false when T =:= tree -> + {tree, Exprs1}; + false -> + unknown + end + end. + %%%----------------------------------------------------------------- %%% Add a link target for each line and one for each function definition. build_html(SFd,DFd,Encoding,FuncsAndCs) -> -- cgit v1.2.3 From d16c327bd35493a3687f7e07e2b332d2d18c5bc8 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 2 Jul 2015 13:28:46 +0200 Subject: syntax_tools: Use the erl_anno module a bit more --- lib/syntax_tools/src/erl_syntax.erl | 2 +- lib/syntax_tools/src/merl.erl | 22 ++++++++++++++++------ lib/syntax_tools/src/merl_transform.erl | 16 ++++++++++++---- 3 files changed, 29 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 3f2a3e05dd..97b5797b06 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -355,7 +355,7 @@ %% where `Pos' `Ann' and `Comments' are the corresponding values of a %% `tree' or `wrapper' record. --record(attr, {pos = 0 :: term(), +-record(attr, {pos = erl_anno:new(0) :: term(), ann = [] :: [term()], com = none :: 'none' | #com{}}). -type syntaxTreeAttributes() :: #attr{}. diff --git a/lib/syntax_tools/src/merl.erl b/lib/syntax_tools/src/merl.erl index 690306c17b..163ce48bbc 100644 --- a/lib/syntax_tools/src/merl.erl +++ b/lib/syntax_tools/src/merl.erl @@ -514,15 +514,17 @@ parse_forms([]) -> parse_2(Ts) -> %% one or more comma-separated expressions? %% (recall that Ts has no dot tokens if we get to this stage) - case erl_parse:parse_exprs(Ts ++ [{dot,0}]) of + A = a0(), + case erl_parse:parse_exprs(Ts ++ [{dot,A}]) of {ok, Exprs} -> Exprs; {error, E} -> - parse_3(Ts ++ [{'end',0}, {dot,0}], [E]) + parse_3(Ts ++ [{'end',A}, {dot,A}], [E]) end. parse_3(Ts, Es) -> %% try-clause or clauses? - case erl_parse:parse_exprs([{'try',0}, {atom,0,true}, {'catch',0} | Ts]) of + A = a0(), + case erl_parse:parse_exprs([{'try',A}, {atom,A,true}, {'catch',A} | Ts]) of {ok, [{'try',_,_,_,_,_}=X]} -> %% get the right kind of qualifiers in the clause patterns erl_syntax:try_expr_handlers(X); @@ -533,7 +535,8 @@ parse_3(Ts, Es) -> parse_4(Ts, Es) -> %% fun-clause or clauses? (`(a)' is also a pattern, but `(a,b)' isn't, %% so fun-clauses must be tried before normal case-clauses - case erl_parse:parse_exprs([{'fun',0} | Ts]) of + A = a0(), + case erl_parse:parse_exprs([{'fun',A} | Ts]) of {ok, [{'fun',_,{clauses,Cs}}]} -> Cs; {error, E} -> parse_5(Ts, [E|Es]) @@ -541,7 +544,8 @@ parse_4(Ts, Es) -> parse_5(Ts, Es) -> %% case-clause or clauses? - case erl_parse:parse_exprs([{'case',0}, {atom,0,true}, {'of',0} | Ts]) of + A = a0(), + case erl_parse:parse_exprs([{'case',A}, {atom,A,true}, {'of',A} | Ts]) of {ok, [{'case',_,_,Cs}]} -> Cs; {error, E} -> %% select the best error to report @@ -1210,7 +1214,7 @@ merge_comments(StartLine, Cs, [], Acc) -> merge_comments(StartLine, [], [], [erl_syntax:set_pos( erl_syntax:comment(Indent, Text), - StartLine + Line - 1) + anno(StartLine + Line - 1)) || {Line, _, Indent, Text} <- Cs] ++ Acc); merge_comments(StartLine, [C|Cs], [T|Ts], Acc) -> {Line, _Col, Indent, Text} = C, @@ -1228,3 +1232,9 @@ merge_comments(StartLine, [C|Cs], [T|Ts], Acc) -> [erl_syntax:comment(Indent, Text)], T), merge_comments(StartLine, Cs, [Tc|Ts], Acc) end. + +a0() -> + anno(0). + +anno(Location) -> + erl_anno:new(Location). diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl index 66b06c8137..fe58b6a122 100644 --- a/lib/syntax_tools/src/merl_transform.erl +++ b/lib/syntax_tools/src/merl_transform.erl @@ -68,8 +68,7 @@ case_guard([{expr,_}, {text,Text}]) -> erl_syntax:is_literal(Text). case_body([{expr,Expr}, {text,_Text}], T) -> - pre_expand_case(Expr, erl_syntax:case_expr_clauses(T), - erl_syntax:get_pos(T)). + pre_expand_case(Expr, erl_syntax:case_expr_clauses(T), get_location(T)). post(T) -> merl:switch( @@ -79,7 +78,7 @@ post(T) -> lists:all(fun erl_syntax:is_literal/1, [F|As]) end, fun ([{args, As}, {function, F}]) -> - Line = erl_syntax:get_pos(F), + Line = get_location(F), [F1|As1] = lists:map(fun erl_syntax:concrete/1, [F|As]), eval_call(Line, F1, As1, T) end}, @@ -118,7 +117,7 @@ expand_qquote(_As, T, _StartPos) -> expand_template(F, [Pattern | Args], T) -> case erl_syntax:is_literal(Pattern) of true -> - Line = erl_syntax:get_pos(Pattern), + Line = get_location(Pattern), As = [erl_syntax:concrete(Pattern)], merl:qquote(Line, "merl:_@function(_@pattern, _@args)", [{function, F}, @@ -260,3 +259,12 @@ is_erlang_var([C|_]) when C >= $A, C =< $Z ; C >= $À, C =< $Þ, C /= $× -> true; is_erlang_var(_) -> false. + +get_location(T) -> + Pos = erl_syntax:get_pos(T), + case erl_anno:is_anno(Pos) of + true -> + erl_anno:location(Pos); + false -> + Pos + end. -- cgit v1.2.3 From b2c0bef3cff85784b2ccb3b91bbea997acab6187 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 4 Sep 2015 16:13:08 +0200 Subject: ssl: Correct return value of default session callback module ssl_session_cache:select_session/2 returned [sesionid(), #session{}] instead of #session{} as the API demands. This was wrongly compensated for in the code in one place making it look like everything was good. But the client check for unique session would always fail, potentially making the client session table grow a lot and causing long setup times. --- lib/ssl/src/ssl_session.erl | 4 +- lib/ssl/src/ssl_session_cache.erl | 2 +- lib/ssl/test/ssl_session_cache_SUITE.erl | 71 +++++++++++++++++++++++++++----- lib/ssl/test/ssl_test_lib.erl | 18 +++++++- 4 files changed, 80 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index 1770faf1ff..0d6cc93a20 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -100,14 +100,14 @@ select_session([], _, _) -> no_session; select_session(Sessions, #ssl_options{ciphers = Ciphers}, OwnCert) -> IsNotResumable = - fun([_Id, Session]) -> + fun(Session) -> not (resumable(Session#session.is_resumable) andalso lists:member(Session#session.cipher_suite, Ciphers) andalso (OwnCert == Session#session.own_certificate)) end, case lists:dropwhile(IsNotResumable, Sessions) of [] -> no_session; - [[Id, _]|_] -> Id + [Session | _] -> Session#session.session_id end. is_resumable(_, _, #ssl_options{reuse_sessions = false}, _, _, _, _) -> diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl index 11ed310477..cfc48cd935 100644 --- a/lib/ssl/src/ssl_session_cache.erl +++ b/lib/ssl/src/ssl_session_cache.erl @@ -83,7 +83,7 @@ foldl(Fun, Acc0, Cache) -> %%-------------------------------------------------------------------- select_session(Cache, PartialKey) -> ets:select(Cache, - [{{{PartialKey,'$1'}, '$2'},[],['$$']}]). + [{{{PartialKey,'_'}, '$1'},[],['$1']}]). %%-------------------------------------------------------------------- %%% Internal functions diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl index 8ddc5db4b2..0738869f2b 100644 --- a/lib/ssl/test/ssl_session_cache_SUITE.erl +++ b/lib/ssl/test/ssl_session_cache_SUITE.erl @@ -45,7 +45,8 @@ all() -> [session_cleanup, session_cache_process_list, - session_cache_process_mnesia]. + session_cache_process_mnesia, + client_unique_session]. groups() -> []. @@ -90,8 +91,8 @@ init_per_testcase(session_cleanup, Config) -> ct:timetrap({seconds, 20}), Config; -init_per_testcase(_TestCase, Config) -> - ct:timetrap({seconds, 5}), +init_per_testcase(client_unique_session, Config) -> + ct:timetrap({seconds, 20}), Config. init_customized_session_cache(Type, Config) -> @@ -131,10 +132,40 @@ end_per_testcase(_, Config) -> %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- +client_unique_session() -> + [{doc, "Test session table does not grow when client " + "sets up many connections"}]. +client_unique_session(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + LastClient = clients_start(Server, + ClientNode, Hostname, Port, ClientOpts, 20), + receive + {LastClient, {ok, _}} -> + ok + end, + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = ssl_test_lib:state(Prop), + ClientCache = element(2, State), + 1 = ets:info(ClientCache, size), + + ssl_test_lib:close(Server, 500), + ssl_test_lib:close(LastClient). + session_cleanup() -> [{doc, "Test that sessions are cleand up eventually, so that the session table " "does not grow and grow ..."}]. -session_cleanup(Config)when is_list(Config) -> +session_cleanup(Config) when is_list(Config) -> process_flag(trap_exit, true), ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -148,9 +179,9 @@ session_cleanup(Config)when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, - {port, Port}, {host, Hostname}, + {port, Port}, {host, Hostname}, {mfa, {ssl_test_lib, no_result, []}}, - {from, self()}, {options, ClientOpts}]), + {from, self()}, {options, ClientOpts}]), SessionInfo = receive {Server, Info} -> @@ -325,8 +356,8 @@ select_session(Cache, PartialKey) -> mnesia -> Sel = fun() -> mnesia:select(Cache, - [{{Cache,{PartialKey,'$1'}, '$2'}, - [],['$$']}]) + [{{Cache,{PartialKey,'_'}, '$1'}, + [],['$1']}]) end, {atomic, Res} = mnesia:transaction(Sel), Res @@ -354,8 +385,8 @@ session_loop(Sess) -> Pid ! {self(), Res}, session_loop(Sess); {Pid,select_session,PKey} -> - Sel = fun({{PKey0, Id},Session}, Acc) when PKey == PKey0 -> - [[Id, Session]|Acc]; + Sel = fun({{PKey0, _Id},Session}, Acc) when PKey == PKey0 -> + [Session | Acc]; (_,Acc) -> Acc end, @@ -370,3 +401,23 @@ session_loop(Sess) -> session_cache_process(_Type,Config) when is_list(Config) -> ssl_basic_SUITE:reuse_session(Config). + + +clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, 0) -> + %% Make sure session is registered + ct:sleep(?SLEEP * 2), + ssl_test_lib:start_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {?MODULE, connection_info_result, []}}, + {from, self()}, {options, ClientOpts}]); +clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N) -> + spawn_link(ssl_test_lib, start_client, + [[{node, ClientNode}, + {port, Port}, {host, Hostname}, + {mfa, {ssl_test_lib, no_result, []}}, + {from, self()}, {options, ClientOpts}]]), + Server ! listen, + clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N-1). + +connection_info_result(Socket) -> + ssl:connection_information(Socket, [protocol, cipher_suite]). diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 8317148aa5..ba8588f2f9 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -241,7 +241,21 @@ close(Pid) -> receive {'DOWN', Monitor, process, Pid, Reason} -> erlang:demonitor(Monitor), - ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason]) + ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason]) + + end. + +close(Pid, Timeout) -> + ct:log("~p:~p~n Close ~p ~n", [?MODULE,?LINE, Pid]), + Monitor = erlang:monitor(process, Pid), + Pid ! close, + receive + {'DOWN', Monitor, process, Pid, Reason} -> + erlang:demonitor(Monitor), + ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason]) + after + Timeout -> + exit(Pid, kill) end. check_result(Server, ServerMsg, Client, ClientMsg) -> @@ -360,7 +374,7 @@ cert_options(Config) -> SNIServerAKeyFile = filename:join([?config(priv_dir, Config), "a.server", "key.pem"]), SNIServerBCertFile = filename:join([?config(priv_dir, Config), "b.server", "cert.pem"]), SNIServerBKeyFile = filename:join([?config(priv_dir, Config), "b.server", "key.pem"]), - [{client_opts, [{ssl_imp, new},{reuseaddr, true}]}, + [{client_opts, []}, {client_verification_opts, [{cacertfile, ClientCaCertFile}, {certfile, ClientCertFile}, {keyfile, ClientKeyFile}, -- cgit v1.2.3 From 3e8de426873759d6e9f6b2f82b55ad4256d6a39f Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Tue, 15 Sep 2015 16:34:08 +0100 Subject: Don't add newline after arrow on -callback lines In the Emacs Erlang mode, typing "->" will usually automatically add a newline, which is usually what you want when writing a function, but not when writing a type spec. Therefore, there is a check for not adding the newline when the current line starts with -spec or -type. This change adds -callback to that check, since it is usually written the same way as type specs. --- lib/tools/emacs/erlang.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index 4aa1ab7d38..466bf139b9 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -4236,7 +4236,7 @@ This function is designed to be a member of a criteria list." This function is designed to be a member of a criteria list." (save-excursion (beginning-of-line) - (when (save-match-data (looking-at "-\\(spec\\|type\\)")) + (when (save-match-data (looking-at "-\\(spec\\|type\\|callback\\)")) 'stop))) -- cgit v1.2.3 From 1b06210c16465bcb995b0a54ba1b24ef1de3c5a4 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 25 Aug 2015 18:19:38 +0200 Subject: ssl: Improve shutdown logic Add possibility to downgrade an SSL/TLS connection to a tcp connection, and give back the socket control to a user process. Add application setting to be able to change fatal alert shutdown timeout, also shorten the default timeout. The fatal alert timeout is the number of milliseconds between sending of a fatal alert and closing the connection. Waiting a little while improves the peers chances to properly receiving the alert so it may shutdown gracefully. --- lib/ssl/doc/src/ssl.xml | 15 +++++++ lib/ssl/doc/src/ssl_app.xml | 11 +++++ lib/ssl/src/ssl.erl | 20 ++++++++- lib/ssl/src/ssl_connection.erl | 95 +++++++++++++++++++--------------------- lib/ssl/src/tls_connection.erl | 55 ++++++++++++++++++----- lib/ssl/test/ssl_basic_SUITE.erl | 76 +++++++++++++++++++++++++++++++- 6 files changed, 208 insertions(+), 64 deletions(-) (limited to 'lib') diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 6c977bdb74..22ac98c24e 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -765,6 +765,21 @@ fun(srp, Username :: string(), UserState :: term()) -> + + close(SslSocket, How) -> ok | {ok, port()} | {error, Reason} + Closes an SSL connection. + + SslSocket = sslsocket() + How = timeout() | {NewController::pid(), timeout()} + Reason = term() + +

Closes or downgrades an SSL connection, in the later case the transport + connection will be handed over to the NewController process after reciving + the TLS close alert from the peer. The retuned transport socket will have + the following options set [{active, false}, {packet, 0}, {mode, binary}].

+
+
+ connection_info(SslSocket) -> {ok, {ProtocolVersion, CipherSuite}} | {error, Reason} diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index 2b6dc7e8be..51ce0cedf1 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -87,6 +87,17 @@ marker="ssl#clear_pem_cache-0">ssl:clear_pem_cache/0 + ]]> + +

+ Number of milliseconds between sending of a fatal alert and + closing the connection. Waiting a little while improves the + peers chances to properly receiving the alert so it may + shutdown gracefully. Defaults to 5000 milliseconds. +

+
+ +
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 120e8b59ed..f611079912 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -34,7 +34,7 @@ listen/2, transport_accept/1, transport_accept/2, ssl_accept/1, ssl_accept/2, ssl_accept/3, controlling_process/2, peername/1, peercert/1, sockname/1, - close/1, shutdown/2, recv/2, recv/3, send/2, getopts/2, setopts/2 + close/1, close/2, shutdown/2, recv/2, recv/3, send/2, getopts/2, setopts/2 ]). %% SSL/TLS protocol handling -export([cipher_suites/0, cipher_suites/1, suite_definition/1, @@ -247,10 +247,26 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) -> %% Description: Close an ssl connection %%-------------------------------------------------------------------- close(#sslsocket{pid = Pid}) when is_pid(Pid) -> - ssl_connection:close(Pid); + ssl_connection:close(Pid, {close, ?DEFAULT_TIMEOUT}); close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}) -> Transport:close(ListenSocket). +%%-------------------------------------------------------------------- +-spec close(#sslsocket{}, integer() | {pid(), integer()}) -> term(). +%% +%% Description: Close an ssl connection +%%-------------------------------------------------------------------- +close(#sslsocket{pid = TLSPid}, + {Pid, Timeout} = DownGrade) when is_pid(TLSPid), + is_pid(Pid), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> + ssl_connection:close(TLSPid, {close, DownGrade}); +close(#sslsocket{pid = TLSPid}, Timeout) when is_pid(TLSPid), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> + ssl_connection:close(TLSPid, {close, Timeout}); +close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}, _) -> + Transport:close(ListenSocket). + %%-------------------------------------------------------------------- -spec send(#sslsocket{}, iodata()) -> ok | {error, reason()}. %% diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 5b754c16bc..f8afbdb41d 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -41,7 +41,7 @@ socket_control/4, socket_control/5]). %% User Events --export([send/2, recv/3, close/1, shutdown/2, +-export([send/2, recv/3, close/2, shutdown/2, new_user/2, get_opts/2, set_opts/2, session_info/1, peer_certificate/1, renegotiation/1, negotiated_protocol/1, prf/5, connection_information/1 @@ -171,18 +171,19 @@ connection_information(Pid) when is_pid(Pid) -> sync_send_all_state_event(Pid, connection_information). %%-------------------------------------------------------------------- --spec close(pid()) -> ok | {error, reason()}. +-spec close(pid(), {close, Timeout::integer() | + {NewController::pid(), Timeout::integer()}}) -> + ok | {ok, port()} | {error, reason()}. %% %% Description: Close an ssl connection %%-------------------------------------------------------------------- -close(ConnectionPid) -> - case sync_send_all_state_event(ConnectionPid, close) of +close(ConnectionPid, How) -> + case sync_send_all_state_event(ConnectionPid, How) of {error, closed} -> ok; Other -> Other end. - %%-------------------------------------------------------------------- -spec shutdown(pid(), atom()) -> ok | {error, reason()}. %% @@ -706,12 +707,12 @@ handle_sync_event({start, Timeout}, StartFrom, StateName, #state{role = Role, s {stop, normal, {error, Error}, State0} end; -handle_sync_event(close, _, StateName, #state{protocol_cb = Connection} = State) -> - %% Run terminate before returning - %% so that the reuseaddr inet-option will work - %% as intended. - (catch Connection:terminate(user_close, StateName, State)), - {stop, normal, ok, State#state{terminated = true}}; +handle_sync_event({close, _} = Close, _, StateName, #state{protocol_cb = Connection} = State) -> + %% Run terminate before returning so that the reuseaddr + %% inet-option and possible downgrade will work as intended. + Result = Connection:terminate(Close, StateName, State), + {stop, normal, Result, State#state{terminated = true}}; + handle_sync_event({shutdown, How0}, _, StateName, #state{transport_cb = Transport, negotiated_version = Version, @@ -901,41 +902,46 @@ terminate(_, _, #state{terminated = true}) -> %% we want to guarantee that Transport:close has been called %% when ssl:close/1 returns. ok; -terminate({shutdown, transport_closed}, StateName, #state{send_queue = SendQueue, - renegotiation = Renegotiate} = State) -> - handle_unrecv_data(StateName, State), +terminate({shutdown, transport_closed} = Reason, + _StateName, #state{send_queue = SendQueue, protocol_cb = Connection, + socket = Socket, transport_cb = Transport, + renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), - notify_renegotiater(Renegotiate); - -terminate({shutdown, own_alert}, _StateName, #state{send_queue = SendQueue, - renegotiation = Renegotiate} = State) -> + notify_renegotiater(Renegotiate), + Connection:close(Reason, Socket, Transport, undefined, undefined); +terminate({shutdown, own_alert}, _StateName, #state{send_queue = SendQueue, protocol_cb = Connection, + socket = Socket, transport_cb = Transport, + renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), - notify_renegotiater(Renegotiate); + notify_renegotiater(Renegotiate), + case application:get_env(ssl, alert_timeout) of + {ok, Timeout} when is_integer(Timeout) -> + Connection:close({timeout, Timeout}, Socket, Transport, undefined, undefined); + _ -> + Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, undefined, undefined) + end; terminate(Reason, connection, #state{negotiated_version = Version, protocol_cb = Connection, - connection_states = ConnectionStates, + connection_states = ConnectionStates0, + ssl_options = #ssl_options{padding_check = Check}, transport_cb = Transport, socket = Socket, send_queue = SendQueue, renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), notify_renegotiater(Renegotiate), - BinAlert = terminate_alert(Reason, Version, ConnectionStates), + {BinAlert, ConnectionStates} = terminate_alert(Reason, Version, ConnectionStates0), Transport:send(Socket, BinAlert), - case Connection of - tls_connection -> - tls_connection:workaround_transport_delivery_problems(Socket, Transport); - _ -> - ok - end; -terminate(_Reason, _StateName, #state{transport_cb = Transport, + Connection:close(Reason, Socket, Transport, ConnectionStates, Check); + +terminate(Reason, _StateName, #state{transport_cb = Transport, protocol_cb = Connection, socket = Socket, send_queue = SendQueue, renegotiation = Renegotiate} = State) -> handle_trusted_certs_db(State), notify_senders(SendQueue), notify_renegotiater(Renegotiate), - Transport:close(Socket). + Connection:close(Reason, Socket, Transport, undefined, undefined). format_status(normal, [_, State]) -> [{data, [{"StateData", State}]}]; @@ -1758,30 +1764,17 @@ get_timeout(#state{ssl_options=#ssl_options{hibernate_after = undefined}}) -> get_timeout(#state{ssl_options=#ssl_options{hibernate_after = HibernateAfter}}) -> HibernateAfter. -terminate_alert(Reason, Version, ConnectionStates) when Reason == normal; - Reason == user_close -> - {BinAlert, _} = ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), - Version, ConnectionStates), - BinAlert; -terminate_alert({shutdown, _}, Version, ConnectionStates) -> - {BinAlert, _} = ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), - Version, ConnectionStates), - BinAlert; +terminate_alert(normal, Version, ConnectionStates) -> + ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), + Version, ConnectionStates); +terminate_alert({Reason, _}, Version, ConnectionStates) when Reason == close; + Reason == shutdown -> + ssl_alert:encode(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), + Version, ConnectionStates); terminate_alert(_, Version, ConnectionStates) -> - {BinAlert, _} = ssl_alert:encode(?ALERT_REC(?FATAL, ?INTERNAL_ERROR), - Version, ConnectionStates), - BinAlert. - -handle_unrecv_data(StateName, #state{socket = Socket, transport_cb = Transport, - protocol_cb = Connection} = State) -> - ssl_socket:setopts(Transport, Socket, [{active, false}]), - case Transport:recv(Socket, 0, 0) of - {error, closed} -> - ok; - {ok, Data} -> - Connection:handle_close_alert(Data, StateName, State) - end. + ssl_alert:encode(?ALERT_REC(?FATAL, ?INTERNAL_ERROR), + Version, ConnectionStates). handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>, cacerts = []}}) -> %% No trusted certs specified diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 7fda2377ee..3093508f61 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -54,7 +54,7 @@ %% Alert and close handling -export([send_alert/2, handle_own_alert/4, handle_close_alert/3, handle_normal_shutdown/3, handle_unexpected_message/3, - workaround_transport_delivery_problems/2, alert_user/6, alert_user/9 + close/5, alert_user/6, alert_user/9 ]). %% Data handling @@ -924,8 +924,7 @@ handle_own_alert(Alert, Version, StateName, try %% Try to tell the other side {BinMsg, _} = ssl_alert:encode(Alert, Version, ConnectionStates), - Transport:send(Socket, BinMsg), - workaround_transport_delivery_problems(Socket, Transport) + Transport:send(Socket, BinMsg) catch _:_ -> %% Can crash if we are in a uninitialized state ignore end, @@ -977,21 +976,57 @@ invalidate_session(client, Host, Port, Session) -> invalidate_session(server, _, Port, Session) -> ssl_manager:invalidate_session(Port, Session). -workaround_transport_delivery_problems(Socket, gen_tcp = Transport) -> +%% User downgrades connection +%% When downgrading an TLS connection to a transport connection +%% we must recive the close message before releasing the +%% transport socket. +close({close, {Pid, Timeout}}, Socket, Transport, ConnectionStates, Check) when is_pid(Pid) -> + ssl_socket:setopts(Transport, Socket, [{active, false}, {packet, ssl_tls}]), + case Transport:recv(Socket, 0, Timeout) of + {ok, {ssl_tls, Socket, ?ALERT, Version, Fragment}} -> + case tls_record:decode_cipher_text(#ssl_tls{type = ?ALERT, + version = Version, + fragment = Fragment + }, ConnectionStates, Check) of + {#ssl_tls{fragment = Plain}, _} -> + [Alert| _] = decode_alerts(Plain), + downgrade(Alert, Transport, Socket, Pid) + end; + {error, timeout} -> + {error, timeout}; + _ -> + {error, no_tls_close} + end; +%% User closes or recursive call! +close({close, Timeout}, Socket, Transport = gen_tcp, _,_) -> + ssl_socket:setopts(Transport, Socket, [{active, false}]), + Transport:shutdown(Socket, write), + _ = Transport:recv(Socket, 0, Timeout), + ok; +%% Peer closed socket +close({shutdown, transport_closed}, Socket, Transport = gen_tcp, ConnectionStates, Check) -> + close({close, 0}, Socket, Transport, ConnectionStates, Check); +%% We generate fatal alert +close({shutdown, own_alert}, Socket, Transport = gen_tcp, ConnectionStates, Check) -> %% Standard trick to try to make sure all %% data sent to the tcp port is really delivered to the %% peer application before tcp port is closed so that the peer will %% get the correct TLS alert message and not only a transport close. - ssl_socket:setopts(Transport, Socket, [{active, false}]), - Transport:shutdown(Socket, write), - %% Will return when other side has closed or after 30 s + %% Will return when other side has closed or after timout millisec %% e.g. we do not want to hang if something goes wrong %% with the network but we want to maximise the odds that %% peer application gets all data sent on the tcp connection. - Transport:recv(Socket, 0, 30000); -workaround_transport_delivery_problems(Socket, Transport) -> + close({close, ?DEFAULT_TIMEOUT}, Socket, Transport, ConnectionStates, Check); +%% Other +close(_, Socket, Transport, _,_) -> Transport:close(Socket). - +downgrade(#alert{description = ?CLOSE_NOTIFY}, Transport, Socket, Pid) -> + ssl_socket:setopts(Transport, Socket, [{active, false}, {packet, 0}, {mode, binary}]), + Transport:controlling_process(Socket, Pid), + {ok, Socket}; +downgrade(_, _,_,_) -> + {error, no_tls_close}. + convert_state(#state{ssl_options = Options} = State, up, "5.3.5", "5.3.6") -> State#state{ssl_options = convert_options_partial_chain(Options, up)}; convert_state(#state{ssl_options = Options} = State, down, "5.3.6", "5.3.5") -> diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 378f42c2ee..82c3c4ac74 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -129,6 +129,8 @@ api_tests() -> controlling_process, upgrade, upgrade_with_timeout, + downgrade, + close_with_timeout, shutdown, shutdown_write, shutdown_both, @@ -320,7 +322,8 @@ init_per_testcase(rizzo, Config) -> Config; init_per_testcase(TestCase, Config) when TestCase == ssl_accept_timeout; - TestCase == client_closes_socket -> + TestCase == client_closes_socket; + TestCase == downgrade -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), ct:timetrap({seconds, 15}), Config; @@ -1407,6 +1410,53 @@ upgrade_with_timeout(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- +downgrade() -> + [{doc,"Test that you can downgarde an ssl connection to an tcp connection"}]. +downgrade(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, tls_downgrade, []}}, + {options, [{active, false} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, tls_downgrade, []}}, + {options, [{active, false} |ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +close_with_timeout() -> + [{doc,"Test normal (not downgrade) ssl:close/2"}]. +close_with_timeout(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, tls_close, []}}, + {options,[{active, false} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, tls_close, []}}, + {options, [{active, false} |ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok). + + %%-------------------------------------------------------------------- tcp_connect() -> [{doc,"Test what happens when a tcp tries to connect, i,e. a bad (ssl) packet is sent first"}]. @@ -3931,6 +3981,30 @@ connect_dist_c(S) -> {ok, Test} = ssl:recv(S, 0, 10000), ok. +tls_downgrade(Socket) -> + ok = ssl_test_lib:send_recv_result(Socket), + case ssl:close(Socket, {self(), 5000}) of + {ok, TCPSocket} -> + inet:setopts(TCPSocket, [{active, true}]), + gen_tcp:send(TCPSocket, "Downgraded"), + receive + {tcp, TCPSocket, <<"Downgraded">>} -> + ok; + Other -> + {error, Other} + end; + {error, timeout} -> + ct:pal("Timed out, downgrade aborted"), + ok; + Fail -> + {error, Fail} + end. + +tls_close(Socket) -> + ok = ssl_test_lib:send_recv_result(Socket), + ok = ssl:close(Socket, 5000). + + %% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast treashold(N, {3,0}) -> (N div 2) + 1; -- cgit v1.2.3 From 82aafa295a4004bcbd549c5bb888907e3ffc0c97 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 31 Aug 2015 16:44:16 +0200 Subject: ssl: Better timeout gaurds --- lib/ssl/src/ssl.erl | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index f611079912..03495cfd90 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -99,7 +99,8 @@ stop() -> connect(Socket, SslOptions) when is_port(Socket) -> connect(Socket, SslOptions, infinity). -connect(Socket, SslOptions0, Timeout) when is_port(Socket) -> +connect(Socket, SslOptions0, Timeout) when is_port(Socket), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> {Transport,_,_,_} = proplists:get_value(cb_info, SslOptions0, {gen_tcp, tcp, tcp_closed, tcp_error}), EmulatedOptions = ssl_socket:emulated_options(), @@ -125,7 +126,7 @@ connect(Socket, SslOptions0, Timeout) when is_port(Socket) -> connect(Host, Port, Options) -> connect(Host, Port, Options, infinity). -connect(Host, Port, Options, Timeout) -> +connect(Host, Port, Options, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> try handle_options(Options) of {ok, Config} -> do_connect(Host,Port,Config,Timeout) @@ -175,7 +176,7 @@ transport_accept(#sslsocket{pid = {ListenSocket, #config{transport_info = {Transport,_,_, _} =CbInfo, connection_cb = ConnectionCb, ssl = SslOpts, - emulated = Tracker}}}, Timeout) -> + emulated = Tracker}}}, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> case Transport:accept(ListenSocket, Timeout) of {ok, Socket} -> {ok, EmOpts} = ssl_socket:get_emulated_opts(Tracker), @@ -208,15 +209,16 @@ transport_accept(#sslsocket{pid = {ListenSocket, ssl_accept(ListenSocket) -> ssl_accept(ListenSocket, infinity). -ssl_accept(#sslsocket{} = Socket, Timeout) -> +ssl_accept(#sslsocket{} = Socket, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> ssl_connection:handshake(Socket, Timeout); ssl_accept(ListenSocket, SslOptions) when is_port(ListenSocket) -> ssl_accept(ListenSocket, SslOptions, infinity). -ssl_accept(#sslsocket{} = Socket, [], Timeout) -> +ssl_accept(#sslsocket{} = Socket, [], Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)-> ssl_accept(#sslsocket{} = Socket, Timeout); -ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) -> +ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) when + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)-> try {ok, EmOpts, InheritedSslOpts} = ssl_socket:get_all_opts(Tracker), SslOpts = handle_options(SslOpts0, InheritedSslOpts), @@ -224,7 +226,8 @@ ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) -> catch Error = {error, _Reason} -> Error end; -ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) -> +ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> {Transport,_,_,_} = proplists:get_value(cb_info, SslOptions, {gen_tcp, tcp, tcp_closed, tcp_error}), EmulatedOptions = ssl_socket:emulated_options(), @@ -285,7 +288,8 @@ send(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport, _, _, _} %%-------------------------------------------------------------------- recv(Socket, Length) -> recv(Socket, Length, infinity). -recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid) -> +recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid), + (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)-> ssl_connection:recv(Pid, Length, Timeout); recv(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}, _,_) when is_port(Listen)-> -- cgit v1.2.3 From fcfffa3eba6adba9d1cf2c78aca5788025f0f5df Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 26 Jun 2015 13:11:57 +0200 Subject: ssl: Prepare for release We do not want ssl_soft_upgrade_SUITE to fail, but for now we do not know the details of these changes so we use a general fallback for now. --- lib/ssl/src/ssl.appup.src | 12 ++++++++++++ lib/ssl/vsn.mk | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index 1476336039..c95326941c 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,12 +1,24 @@ %% -*- erlang -*- {"%VSN%", [ + {<<"7.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, + {load_module, ssl_connection, soft_purge, soft_purge, []}, + {load_module, tls_connection, soft_purge, soft_purge, []}, + {load_module, ssl_session, soft_purge, soft_purge, []}, + {load_module, ssl_session_cache, soft_purge, soft_purge, []} + ]}, {<<"6\\..*">>, [{restart_application, ssl}]}, {<<"5\\..*">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, {<<"3\\..*">>, [{restart_application, ssl}]} ], [ + {<<"7.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, + {load_module, ssl_connection, soft_purge, soft_purge, []}, + {load_module, tls_connection, soft_purge, soft_purge, []}, + {load_module, ssl_session, soft_purge, soft_purge, []}, + {load_module, ssl_session_cache, soft_purge, soft_purge, []} + ]}, {<<"6\\..*">>, [{restart_application, ssl}]}, {<<"5\\..*">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 171147adf2..4587c448f6 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 7.0 +SSL_VSN = 7.1 -- cgit v1.2.3 From 6bb3c0f4a5e2ed84a4c534361cfbeaead9eec110 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 16 Sep 2015 12:45:46 +0200 Subject: public_key: Document enhancements OTP-12986 --- lib/public_key/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index 7f752529f0..f762473a58 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.0 +PUBLIC_KEY_VSN = 1.0.1 -- cgit v1.2.3 From 6609ada66ccb4dc92cd3d4a9b4bf3951b91b8777 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 16 Sep 2015 14:02:26 +0200 Subject: odbc: Prepare for release --- lib/odbc/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk index d4dc6bbe1d..c7c84560d1 100644 --- a/lib/odbc/vsn.mk +++ b/lib/odbc/vsn.mk @@ -1 +1 @@ -ODBC_VSN = 2.11 +ODBC_VSN = 2.11.1 -- cgit v1.2.3 From 5e9b9dbb8edd237abde65ce7c921c5ed026f740e Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 16 Sep 2015 14:59:42 +0200 Subject: Update application versions --- lib/dialyzer/vsn.mk | 2 +- lib/hipe/vsn.mk | 2 +- lib/sasl/vsn.mk | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 48e0830109..e57caa9ad3 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.8 +DIALYZER_VSN = 2.8.1 diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index e507ae933f..3ec9d7ee45 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.12 +HIPE_VSN = 3.13 diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index e07b36f4ba..9e69ddab65 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 2.5 +SASL_VSN = 2.5.1 -- cgit v1.2.3 From e791c726e741ec67b6dada44d628151bb3900070 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 17 Sep 2015 09:06:04 +0200 Subject: stdlib: Update application version --- lib/stdlib/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index a1f2a946b1..dbe5e04d60 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 2.5 +STDLIB_VSN = 2.5.1 -- cgit v1.2.3 From ad7bb40d88acd0de5bdad9b64f8d8dd5c303fa48 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 17 Sep 2015 09:40:04 +0200 Subject: stdlib: Fix leaking files after error_logger:logfile(close) Introduced when changing state from tuple to record. --- lib/stdlib/src/error_logger_file_h.erl | 10 ++-------- lib/stdlib/test/error_logger_h_SUITE.erl | 6 ++++++ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl index 48c471924e..fea1656051 100644 --- a/lib/stdlib/src/error_logger_file_h.erl +++ b/lib/stdlib/src/error_logger_file_h.erl @@ -94,14 +94,8 @@ handle_call(filename, #st{filename=File}=State) -> handle_call(_Query, State) -> {ok, {error, bad_query}, State}. -terminate(_Reason, State) -> - case State of - {Fd, _File, _Prev} -> - ok = file:close(Fd); - _ -> - ok - end, - []. +terminate(_Reason, #st{fd=Fd}) -> + file:close(Fd). code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl index b0b9c717a1..c82b1b62ef 100644 --- a/lib/stdlib/test/error_logger_h_SUITE.erl +++ b/lib/stdlib/test/error_logger_h_SUITE.erl @@ -65,6 +65,12 @@ logfile(Config) -> error_logger:logfile(close), analyse_events(Log, Ev, [AtNode], unlimited), + [] = [{X, file:pid2name(X)} || X <- processes(), Data <- [process_info(X, [current_function])], + Data =/= undefined, + element(1, element(2, lists:keyfind(current_function, 1, Data))) + =:= file_io_server, + file:pid2name(X) =:= {ok, Log}], + test_server:stop_node(Node), cleanup(Log), -- cgit v1.2.3 From ffa4f7bfc1d06f295c2d2b4a9f529abe009040e2 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 16 Sep 2015 11:42:46 +0200 Subject: inets: Prepare for release --- lib/inets/src/inets_app/inets.appup.src | 2 ++ lib/inets/vsn.mk | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index d3da76d789..a9fbb1c3f7 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -18,9 +18,11 @@ %% %CopyrightEnd% {"%VSN%", [ + {<<"6\\..*">>,[{restart_application, inets}]}, {<<"5\\..*">>,[{restart_application, inets}]} ], [ + {<<"6\\..*">>,[{restart_application, inets}]}, {<<"5\\..*">>,[{restart_application, inets}]} ] }. diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 5395df1d07..a6aeedfe12 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 6.0 +INETS_VSN = 6.0.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" -- cgit v1.2.3 From 3524231c8142165f4c468de2b76b3cb5a5139c2c Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 17 Sep 2015 12:36:51 +0200 Subject: Update sasl vsn to 2.6 --- lib/sasl/src/sasl.appup.src | 6 ++++-- lib/sasl/vsn.mk | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src index eddb5a3fd0..2c8812f566 100644 --- a/lib/sasl/src/sasl.appup.src +++ b/lib/sasl/src/sasl.appup.src @@ -18,7 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index 9e69ddab65..959d9c88d5 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 2.5.1 +SASL_VSN = 2.6 -- cgit v1.2.3 From f3cf61cd87465f9424e23223b8b3d2f4aacc3ace Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Thu, 17 Sep 2015 13:35:23 +0200 Subject: Remove 1.11 release notes These were added manually in merge commit 8c5d719a, but that was wrong: the notes will be generated. Note that OTP-12791 in the comment for commit 5a339bcb is wrong: it's OTP-12891. --- lib/diameter/doc/src/notes.xml | 61 ------------------------------------------ 1 file changed, 61 deletions(-) (limited to 'lib') diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index c5f0d66f10..afe9117a9d 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -43,67 +43,6 @@ first.

-
diameter 1.11 - -
Fixed Bugs and Malfunctions - - -

- Don't report 5005 (DIAMETER_AVP_MISSING) errors - unnecessarily.

-

- An AVP whose decode failed was reported as missing, - despite having been reported with another error as a - consequence of the failure.

-

- Own Id: OTP-12871

-
- -

- Fix relay encode of nested, Grouped AVPs.

-

- A fault in OTP-12475 caused encode to fail if the first - AVP in a Grouped AVP was itself Grouped.

-

- Own Id: OTP-12879 Aux Id: OTP-12475

-
- -

- Improve decode performance.

-

- The time required to decode a message increased - quadratically with the number of AVPs in the worst case, - leading to extremely long execution times.

-

- Own Id: OTP-12891

-
- -

- Match acceptable peer addresses case insensitively.

-

- Regular expressions passed in an 'accept' tuple to - diameter_tcp or diameter_sctp inappropriately matched - case.

-

- Own Id: OTP-12902

-
- -

- Improve watchdog and statistics performance.

-

- Inefficient use of timers contributed to poor performance - at high load, as did ordering of the table statistics are - written to.

-

- Own Id: OTP-12912

-
-
-
- -
- - -
diameter 1.10
Fixed Bugs and Malfunctions -- cgit v1.2.3 From 85276c69d9bf43ac85b4de3aacfc5f9baf15bcf0 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 17 Sep 2015 18:04:34 +0200 Subject: ssl: Timeout tuning --- lib/ssl/test/ssl_basic_SUITE.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 82c3c4ac74..6f6107de2c 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -3983,13 +3983,16 @@ connect_dist_c(S) -> tls_downgrade(Socket) -> ok = ssl_test_lib:send_recv_result(Socket), - case ssl:close(Socket, {self(), 5000}) of + case ssl:close(Socket, {self(), 10000}) of {ok, TCPSocket} -> inet:setopts(TCPSocket, [{active, true}]), gen_tcp:send(TCPSocket, "Downgraded"), receive {tcp, TCPSocket, <<"Downgraded">>} -> ok; + {tcp_closed, TCPSocket} -> + ct:pal("Peer timed out, downgrade aborted"), + ok; Other -> {error, Other} end; -- cgit v1.2.3 From 1d3e719905f29dfa6a87b0f65aa0120b3e6cfe2f Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 18 Sep 2015 10:48:10 +0200 Subject: Update application versions --- lib/kernel/src/kernel.app.src | 4 ++-- lib/kernel/src/kernel.appup.src | 6 ++++-- lib/kernel/vsn.mk | 2 +- lib/sasl/src/sasl.app.src | 4 ++-- lib/stdlib/src/stdlib.app.src | 2 +- lib/stdlib/src/stdlib.appup.src | 6 ++++-- lib/stdlib/vsn.mk | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index c9327e4f31..b5555ca1a5 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -116,6 +116,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-7.0", "stdlib-2.5", "sasl-2.4"]} + {runtime_dependencies, ["erts-7.0", "stdlib-2.6", "sasl-2.6"]} ] }. diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 701aafc717..3fda55d1a9 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,7 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 + [{<<"4\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 + [{<<"4\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index c912da0091..d549033302 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 4.0 +KERNEL_VSN = 4.1 diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src index 7864e84773..705bb73fc5 100644 --- a/lib/sasl/src/sasl.app.src +++ b/lib/sasl/src/sasl.app.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -46,6 +46,6 @@ {env, [{sasl_error_logger, tty}, {errlog_type, all}]}, {mod, {sasl, []}}, - {runtime_dependencies, ["tools-2.6.14","stdlib-2.0","kernel-3.0", + {runtime_dependencies, ["tools-2.6.14","stdlib-2.6","kernel-4.1", "erts-6.0"]}]}. diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src index 4400956943..7f9bbbf649 100644 --- a/lib/stdlib/src/stdlib.app.src +++ b/lib/stdlib/src/stdlib.app.src @@ -105,7 +105,7 @@ dets]}, {applications, [kernel]}, {env, []}, - {runtime_dependencies, ["sasl-2.4","kernel-4.0","erts-7.0","crypto-3.3", + {runtime_dependencies, ["sasl-2.6","kernel-4.1","erts-7.0","crypto-3.3", "compiler-5.0"]} ]}. diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 828e1d9aa4..5f61752655 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -18,7 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], %% 17.0-17.5 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, %% OTP-18.0.* + {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], %% 17.0-17.5 %% Down to - max one major revision back - [{<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] %% 17.0-17.5 + [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, %% OTP-18.0.* + {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] %% 17.0-17.5 }. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index dbe5e04d60..3387d74e57 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 2.5.1 +STDLIB_VSN = 2.6 -- cgit v1.2.3 From 4efe89d8e2ef1eca4ebccf7e753839e52b08daa4 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 17 Sep 2015 17:26:47 +0200 Subject: ssl: Correct soft upgrade test Soft upgrade test did not work as expected due to that the upgrade frame work keeps the control of the test case process to itself, so we need a proxy process to receive messages from ssl test framework. --- lib/ssl/src/ssl.appup.src | 4 +- lib/ssl/test/ssl_upgrade_SUITE.erl | 179 ++++++++++++++++++++++++++++++------- 2 files changed, 148 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index c95326941c..8d5bd6f8d8 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,7 +1,7 @@ %% -*- erlang -*- {"%VSN%", [ - {<<"7.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, + {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, {load_module, ssl_connection, soft_purge, soft_purge, []}, {load_module, tls_connection, soft_purge, soft_purge, []}, {load_module, ssl_session, soft_purge, soft_purge, []}, @@ -13,7 +13,7 @@ {<<"3\\..*">>, [{restart_application, ssl}]} ], [ - {<<"7.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, + {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, {load_module, ssl_connection, soft_purge, soft_purge, []}, {load_module, tls_connection, soft_purge, soft_purge, []}, {load_module, ssl_session, soft_purge, soft_purge, []}, diff --git a/lib/ssl/test/ssl_upgrade_SUITE.erl b/lib/ssl/test/ssl_upgrade_SUITE.erl index 17b0240fe8..d65bdf6983 100644 --- a/lib/ssl/test/ssl_upgrade_SUITE.erl +++ b/lib/ssl/test/ssl_upgrade_SUITE.erl @@ -28,7 +28,8 @@ config, server, client, - soft + soft, + result_proxy }). all() -> @@ -77,45 +78,58 @@ upgrade_init(CTData, #state{config = Config} = State) -> {ok, {_, _, Up, _Down}} = ct_release_test:get_appup(CTData, ssl), ct:pal("Up: ~p", [Up]), Soft = is_soft(Up), %% It is symmetrical, if upgrade is soft so is downgrade + Pid = spawn(?MODULE, result_proxy_init, [[]]), case Soft of true -> - {Server, Client} = soft_start_connection(Config), + {Server, Client} = soft_start_connection(Config, Pid), State#state{server = Server, client = Client, - soft = Soft}; + soft = Soft, + result_proxy = Pid}; false -> - State#state{soft = Soft} + State#state{soft = Soft, result_proxy = Pid} end. -upgrade_upgraded(_, #state{soft = false, config = Config} = State) -> - {Server, Client} = restart_start_connection(Config), - ssl_test_lib:check_result(Server, ok, Client, ok), +upgrade_upgraded(_, #state{soft = false, config = Config, result_proxy = Pid} = State) -> + ct:pal("Restart upgrade ~n", []), + {Server, Client} = restart_start_connection(Config, Pid), + Result = check_result(Pid, Server, Client), ssl_test_lib:close(Server), ssl_test_lib:close(Client), + ok = Result, State; upgrade_upgraded(_, #state{server = Server0, client = Client0, - config = Config, soft = true} = State) -> + config = Config, soft = true, + result_proxy = Pid} = State) -> + ct:pal("Soft upgrade: ~n", []), Server0 ! changed_version, Client0 ! changed_version, - ssl_test_lib:check_result(Server0, ok, Client0, ok), + Result = check_result(Pid, Server0, Client0), ssl_test_lib:close(Server0), ssl_test_lib:close(Client0), - {Server, Client} = soft_start_connection(Config), + ok = Result, + {Server, Client} = soft_start_connection(Config, Pid), State#state{server = Server, client = Client}. -upgrade_downgraded(_, #state{soft = false, config = Config} = State) -> - {Server, Client} = restart_start_connection(Config), - ssl_test_lib:check_result(Server, ok, Client, ok), +upgrade_downgraded(_, #state{soft = false, config = Config, result_proxy = Pid} = State) -> + ct:pal("Restart downgrade: ~n", []), + {Server, Client} = restart_start_connection(Config, Pid), + Result = check_result(Pid, Server, Client), ssl_test_lib:close(Server), ssl_test_lib:close(Client), + Pid ! stop, + ok = Result, State; -upgrade_downgraded(_, #state{server = Server, client = Client, soft = true} = State) -> +upgrade_downgraded(_, #state{server = Server, client = Client, soft = true, result_proxy = Pid} = State) -> + ct:pal("Soft downgrade: ~n", []), Server ! changed_version, Client ! changed_version, - ssl_test_lib:check_result(Server, ok, Client, ok), + Result = check_result(Pid, Server, Client), + Pid ! stop, ssl_test_lib:close(Server), ssl_test_lib:close(Client), + ok = Result, State. use_connection(Socket) -> @@ -125,36 +139,35 @@ use_connection(Socket) -> ssl_test_lib:send_recv_result_active(Socket) end. -soft_start_connection(Config) -> +soft_start_connection(Config, ResulProxy) -> ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_verification_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, use_connection, []}}, - {options, ServerOpts}]), + Server = start_server([{node, ServerNode}, {port, 0}, + {from, ResulProxy}, + {mfa, {?MODULE, use_connection, []}}, + {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, use_connection, []}}, - {options, ClientOpts}]), + Port = inet_port(ResulProxy, Server), + Client = start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, ResulProxy}, + {mfa, {?MODULE, use_connection, []}}, + {options, ClientOpts}]), {Server, Client}. -restart_start_connection(Config) -> +restart_start_connection(Config, ResulProxy) -> ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_verification_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server = start_server([{node, ServerNode}, {port, 0}, + {from, ResulProxy}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ServerOpts}]), - - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Port = inet_port(ResulProxy, Server), + Client = start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, ResulProxy}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ClientOpts}]), {Server, Client}. @@ -163,3 +176,103 @@ is_soft([{restart_application, ssl}]) -> false; is_soft(_) -> true. + +result_proxy_init(Args) -> + result_proxy_loop(Args). + +result_proxy_loop(Args) -> + receive + {Pid, {check_result, Server, Client}} -> + Result = do_check_result(Server, ok, Client, ok), + Pid ! {self(), Result}, + result_proxy_loop(Args); + {Pid, port, Server} -> + Port = recv_port(Server), + Pid ! Port, + result_proxy_loop(Args); + {Pid, listen} -> + recv_listen(), + Pid ! ok, + result_proxy_loop(Args); + {Pid, connected} -> + Connected = recv_connected(), + Pid ! Connected, + result_proxy_loop(Args) + end. + +check_result(Pid, Server, Client) -> + Pid ! {self(), {check_result, Server, Client}}, + receive + {Pid, Result} -> + Result + end. + +do_check_result(Server, ServerMsg, Client, ClientMsg) -> + receive + {Server, ServerMsg} -> + do_check_result(Client, ClientMsg); + + {Client, ClientMsg} -> + do_check_result(Server, ServerMsg); + Unexpected -> + {{expected, {Client, ClientMsg}}, + {expected, {Server, ServerMsg}}, {got, Unexpected}} + end. + +do_check_result(Pid, Msg) -> + receive + {Pid, Msg} -> + ok; + Unexpected -> + {{expected, {Pid, Msg}}, + {got, Unexpected}} + end. + +inet_port(Pid, Server) -> + Pid ! {self(), port, Server}, + receive + {port, Port} -> + Port + end. + +recv_port(Server) -> + receive + {Server, {port, Port}} -> + {port, Port} + end. + +recv_connected() -> + receive + {connected, _Socket} -> + ok; + {connect_failed, Reason} -> + {connect_failed, Reason} + end. + + +start_server(Args) -> + Pid = proplists:get_value(from, Args), + Result = spawn_link(ssl_test_lib, run_server, [Args]), + Pid ! {self(), listen}, + receive + ok -> + ok + end, + Result. + +start_client(Args) -> + Pid = proplists:get_value(from, Args), + Result = spawn_link(ssl_test_lib, run_client_init, [lists:delete(return_socket, Args)]), + Pid ! {self(), connected}, + receive + ok -> + Result; + Reason -> + exit(Reason) + end. + +recv_listen()-> + receive + {listen, up} -> + ok + end. -- cgit v1.2.3 From 9a1f7c4156093effddd555e88fd16a2ffd6ae75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 15 Sep 2015 17:23:19 +0200 Subject: Regain full coverage of beam_block d0784035ab fixed a problem with register corruption. Because of that, opt_moves/2 will never be asked to optimize instructions with more than two destination registers. Therefore, to regain full coverage of beam_block, remove the final clause in opt_moves/2. --- lib/compiler/src/beam_block.erl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 75202d9379..ebf9b5fec5 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -283,11 +283,7 @@ opt_moves([X0,Y0], Is0) -> not_possible -> {[X,Y0],Is2}; {X,_} -> {[X,Y0],Is2}; {Y,Is} -> {[X,Y],Is} - end; -opt_moves(Ds, Is) -> - %% multiple destinations -> pass through - {Ds,Is}. - + end. %% opt_move(Dest, [Instruction]) -> {UpdatedDest,[Instruction]} | not_possible %% If there is a {move,Dest,FinalDest} instruction -- cgit v1.2.3 From d3f16a3688d920622c988a3b49bb3f9ba37d9958 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 21 Sep 2015 15:23:06 +0200 Subject: ssl: listen socket should be set to active false --- lib/ssl/test/ssl_session_cache_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl index 0738869f2b..924898f6fa 100644 --- a/lib/ssl/test/ssl_session_cache_SUITE.erl +++ b/lib/ssl/test/ssl_session_cache_SUITE.erl @@ -143,8 +143,8 @@ client_unique_session(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {from, self()}, {mfa, {ssl_test_lib, no_result, []}}, + {tcp_options, [{active, false}]}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), LastClient = clients_start(Server, -- cgit v1.2.3 From 6738d356a279835222b951fd213ed4cf9897eb7e Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Mon, 21 Sep 2015 17:09:23 +0200 Subject: Prepare release --- lib/compiler/doc/src/notes.xml | 20 ++++++++ lib/compiler/vsn.mk | 2 +- lib/crypto/doc/src/notes.xml | 16 ++++++ lib/crypto/vsn.mk | 2 +- lib/debugger/doc/src/notes.xml | 16 ++++++ lib/debugger/vsn.mk | 2 +- lib/dialyzer/doc/src/notes.xml | 42 ++++++++++++++++ lib/diameter/doc/src/notes.xml | 88 +++++++++++++++++++++++++++++++++ lib/eunit/doc/src/notes.xml | 15 ++++++ lib/eunit/vsn.mk | 2 +- lib/hipe/doc/src/notes.xml | 44 +++++++++++++++++ lib/inets/doc/src/notes.xml | 59 +++++++++++++++++++++- lib/kernel/doc/src/notes.xml | 26 ++++++++++ lib/mnesia/doc/src/notes.xml | 18 ++++++- lib/mnesia/vsn.mk | 2 +- lib/odbc/doc/src/notes.xml | 26 +++++++++- lib/public_key/doc/src/notes.xml | 15 ++++++ lib/sasl/doc/src/notes.xml | 26 ++++++++++ lib/ssh/doc/src/notes.xml | 102 +++++++++++++++++++++++++++++++++++++++ lib/ssl/doc/src/notes.xml | 58 +++++++++++++++++++++- lib/stdlib/doc/src/notes.xml | 65 +++++++++++++++++++++++++ lib/tools/doc/src/notes.xml | 19 ++++++++ lib/tools/vsn.mk | 2 +- lib/wx/doc/src/notes.xml | 15 ++++++ lib/wx/vsn.mk | 2 +- 25 files changed, 673 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index 6db8d19b5a..bd85f22462 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,26 @@

This document describes the changes made to the Compiler application.

+
Compiler 6.0.1 + +
Fixed Bugs and Malfunctions + + +

+ Fix get_map_elements register corruption

+

+ Instruction get_map_elements might destroy target + registers when the fail-label is taken. Only seen for + patterns with two, and only two, target registers. + Specifically if we copy one register and then jump.

+

+ Own Id: OTP-12967

+
+
+
+ +
+
Compiler 6.0
Fixed Bugs and Malfunctions diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 69f71ba5dd..357b35e47b 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 6.0 +COMPILER_VSN = 6.0.1 diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index e2b90eca75..54dd8872eb 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the Crypto application.

+
Crypto 3.6.1 + +
Fixed Bugs and Malfunctions + + +

+ Make crypto:ec_curves/0 return empty list if + elliptic curve is not supported at all.

+

+ Own Id: OTP-12944

+
+
+
+ +
+
Crypto 3.6
Fixed Bugs and Malfunctions diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index 55b1b3e8c4..c2166a8e75 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 3.6 +CRYPTO_VSN = 3.6.1 diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml index 67cfe20d83..4a415a538f 100644 --- a/lib/debugger/doc/src/notes.xml +++ b/lib/debugger/doc/src/notes.xml @@ -33,6 +33,22 @@

This document describes the changes made to the Debugger application.

+
Debugger 4.1.1 + +
Fixed Bugs and Malfunctions + + +

+ Fix crash when starting a quick debugging session. Thanks + Alan Duffield.

+

+ Own Id: OTP-12911 Aux Id: seq12906

+
+
+
+ +
+
Debugger 4.1
Improvements and New Features diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk index b6fd4e8e44..e47ed98128 100644 --- a/lib/debugger/vsn.mk +++ b/lib/debugger/vsn.mk @@ -1 +1 @@ -DEBUGGER_VSN = 4.1 +DEBUGGER_VSN = 4.1.1 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index 93d3b09f07..9b3a7244f1 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,48 @@

This document describes the changes made to the Dialyzer application.

+
Dialyzer 2.8.1 + +
Fixed Bugs and Malfunctions + + +

Improve the translation of forms to types.

+

+ Own Id: OTP-12865

+
+ +

Fix a bug concerning parameterized opaque types.

+

+ Own Id: OTP-12866

+
+ +

Fix a bug concerning parameterized opaque types.

+

+ Own Id: OTP-12940

+
+ +

Fix bugs concerning erlang:abs/1.

+

+ Own Id: OTP-12948

+
+ +

Fix a bug concerning lists:keydelete/3 with + union and opaque types.

+

+ Own Id: OTP-12949

+
+ +

+ Use new function hipe:erts_checksum to get correct + runtime checksum for cached beam files.

+

+ Own Id: OTP-12964 Aux Id: OTP-12963, OTP-12962

+
+
+
+ +
+
Dialyzer 2.8
Fixed Bugs and Malfunctions diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index afe9117a9d..61bed37682 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -43,6 +43,94 @@ first.

+
diameter 1.11 + +
Fixed Bugs and Malfunctions + + +

+ Fix relay encode of nested, Grouped AVPs.

+

+ A fault in OTP-12475 caused encode to fail if the first + AVP in a Grouped AVP was itself Grouped.

+

+ Own Id: OTP-12879 Aux Id: OTP-12475

+
+ +

+ Match acceptable peer addresses case insensitively.

+

+ Regular expressions passed in an 'accept' tuple to + diameter_tcp or diameter_sctp inappropriately matched + case.

+

+ Own Id: OTP-12902

+
+ +

+ Fix diameter_watchdog function clause.

+

+ OTP-12912 introduced an error with accepting transports + setting {restrict_connections, false}, causing + processes to fail when peer connections were terminated.

+

+ Own Id: OTP-12969

+
+
+
+ + +
Improvements and New Features + + +

+ Don't report 5005 (DIAMETER_AVP_MISSING) errors + unnecessarily.

+

+ An AVP whose decode failed was reported as missing, + despite having been reported with another error as a + consequence of the failure.

+

+ Own Id: OTP-12871

+
+ +

+ Improve decode performance.

+

+ The time required to decode a message increased + quadratically with the number of AVPs in the worst case, + leading to extremely long execution times.

+

+ Own Id: OTP-12891

+
+ +

+ Improve watchdog and statistics performance.

+

+ Inefficient use of timers contributed to poor performance + at high load, as did ordering of the table statistics are + written to.

+

+ Own Id: OTP-12912

+
+ +

+ Add service_opt() strict_mbit.

+

+ There are differing opinions on whether or not reception + of an arbitrary AVP setting the M-bit is an error. The + default interpretation is strict: if a command grammar + doesn't explicitly allow an AVP setting the M-bit then + reception of such an AVP is regarded as an error. Setting + {strict_mbit, false} disables this check.

+

+ Own Id: OTP-12947

+
+
+
+ +
+
diameter 1.10
Fixed Bugs and Malfunctions diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml index d4ffb30967..3760e396ee 100644 --- a/lib/eunit/doc/src/notes.xml +++ b/lib/eunit/doc/src/notes.xml @@ -33,6 +33,21 @@

This document describes the changes made to the EUnit application.

+
Eunit 2.2.11 + +
Fixed Bugs and Malfunctions + + +

+ Improve success message when 2 tests have passed

+

+ Own Id: OTP-12952

+
+
+
+ +
+
Eunit 2.2.10
Fixed Bugs and Malfunctions diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk index 8b489bdc04..079520def2 100644 --- a/lib/eunit/vsn.mk +++ b/lib/eunit/vsn.mk @@ -1 +1 @@ -EUNIT_VSN = 2.2.10 +EUNIT_VSN = 2.2.11 diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index 33a18ff7ef..a463b421a8 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -31,6 +31,50 @@

This document describes the changes made to HiPE.

+
Hipe 3.13 + +
Fixed Bugs and Malfunctions + + +

Fix bugs concerning erlang:abs/1.

+

+ Own Id: OTP-12948

+
+ +

Fix a bug concerning lists:keydelete/3 with + union and opaque types.

+

+ Own Id: OTP-12949

+
+ +

+ A beam file compiled by hipe for an incompatible runtime + system was sometimes not rejected by the loader, which + could lead to vm crash. This fix will also allow the same + hipe compiler to be used by both normal and debug-built + vm.

+

+ Own Id: OTP-12962

+
+
+
+ + +
Improvements and New Features + + +

+ New function hipe:erts_checksum/0 which returns a + value identifying the target runtime system for the + compiler. Used by dialyzer for its beam cache directory.

+

+ Own Id: OTP-12963 Aux Id: OTP-12962, OTP-12964

+
+
+
+ +
+
Hipe 3.12
Fixed Bugs and Malfunctions diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 6a6b9c8b23..eb1027b028 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,64 @@ notes.xml -
Inets 6.0 +
Inets 6.0.1 + +
Fixed Bugs and Malfunctions + + +

+ Fix broken socket feature, that is on Linux systems a + socket may be opened before starting Erlang and then + passed to Erlang's httpd daemon. This is useful as the + wrap program can open a privileged port and Erlang does + not have to be run as root.

+

+ Own Id: OTP-12875 Aux Id: seq12878

+
+ +

+ Fix broken socket feature, that is on Linux systems a + socket may be opened before starting Erlang and then + passed to Erlangs tftp daemon. This is useful as the wrap + program can open a privileged port and Erlang does not + have to be run as root.

+

+ Own Id: OTP-12898 Aux Id: seq12900

+
+ +

+ httpc_handler should react properly to cancel requests + even when the request to be canceled was already finished + but httpc_manager did not get notified about that yet.

+

+ Own Id: OTP-12922

+
+
+
+ + +
Improvements and New Features + + +

+ Added format_status function to httpd process to avoid + sensitive information to be printed in supervisor logs.

+

+ Own Id: OTP-12976

+
+ +

+ Return meaningful error reason disregarding whether a + http proxy is used or not.

+

+ Own Id: OTP-12984

+
+
+
+ +
+ +
Inets 6.0
Fixed Bugs and Malfunctions diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index b8db22aba7..76db0c201f 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,32 @@

This document describes the changes made to the Kernel application.

+
Kernel 4.1 + +
Improvements and New Features + + +

A mechanism for limiting the amount of text that the + built-in error logger events will produce has been + introduced. It is useful for limiting both the size of + log files and the CPU time used to produce them.

+

This mechanism is experimental in the sense that it + may be changed if it turns out that it does not solve the + problem it is supposed to solve. In that case, there may + be backward incompatible improvements to this + mechanism.

+

See the documentation for the config parameter + error_logger_format_depth in the Kernel + application for information about how to turn on this + feature.

+

+ Own Id: OTP-12864

+
+
+
+ +
+
Kernel 4.0
Fixed Bugs and Malfunctions diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index c4f937f183..3b35a9879b 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,23 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.

-
Mnesia 4.13 +
Mnesia 4.13.1 + +
Fixed Bugs and Malfunctions + + +

+ Improved index updates to avoid a timing glitch in + dirty_index_read.

+

+ Own Id: OTP-12972

+
+
+
+ +
+ +
Mnesia 4.13
Fixed Bugs and Malfunctions diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 79dd495c4b..e27045e16f 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.13 +MNESIA_VSN = 4.13.1 diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml index add8229955..59d46de02a 100644 --- a/lib/odbc/doc/src/notes.xml +++ b/lib/odbc/doc/src/notes.xml @@ -32,7 +32,31 @@

This document describes the changes made to the odbc application.

-
ODBC 2.11 +
ODBC 2.11.1 + +
Improvements and New Features + + +

+ New application variable to set timeout of internal + communication setup between the erlang code and the + c-port program that interfaces the odbc driver. This can + be useful if you have an underlying system that is slow + due to heavy load at startup.

+

+ With this environment variable you can easily bypass and + tailor odbc to the needs of the underlying actual system + without changing the configuration. Which is a good thing + because this value is very system specific.

+

+ Own Id: OTP-12935

+
+
+
+ +
+ +
ODBC 2.11
Improvements and New Features diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index 87db5bd9f4..8034d7fade 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -35,6 +35,21 @@ notes.xml +
Public_Key 1.0.1 + +
Improvements and New Features + + +

+ Document enhancements

+

+ Own Id: OTP-12986

+
+
+
+ +
+
Public_Key 1.0
Improvements and New Features diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml index 36ea42762a..5945ef6490 100644 --- a/lib/sasl/doc/src/notes.xml +++ b/lib/sasl/doc/src/notes.xml @@ -31,6 +31,32 @@

This document describes the changes made to the SASL application.

+
SASL 2.6 + +
Improvements and New Features + + +

A mechanism for limiting the amount of text that the + built-in error logger events will produce has been + introduced. It is useful for limiting both the size of + log files and the CPU time used to produce them.

+

This mechanism is experimental in the sense that it + may be changed if it turns out that it does not solve the + problem it is supposed to solve. In that case, there may + be backward incompatible improvements to this + mechanism.

+

See the documentation for the config parameter + error_logger_format_depth in the Kernel + application for information about how to turn on this + feature.

+

+ Own Id: OTP-12864

+
+
+
+ +
+
SASL 2.5
Fixed Bugs and Malfunctions diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 9d498c0fdc..368bb0f552 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,108 @@ notes.xml +
Ssh 4.1 + +
Fixed Bugs and Malfunctions + + +

+ Send an understandable disconnect message when the key + exchange phase can't find a common algorithm. There are + also some test cases added.

+

+ Own Id: OTP-11531

+
+ +

+ The third parameter in ssh_sftp:write_file is now + accepting iolists again. Unicode handling adjusted.

+

+ Own Id: OTP-12853 Aux Id: seq12891

+
+
+
+ + +
Improvements and New Features + + +

+ First part of ssh test suite re-organization and + extension.

+

+ Own Id: OTP-12230

+
+ +

+ The key exchange algorithms 'ecdh-sha2-nistp256', + 'ecdh-sha2-nistp384' and 'ecdh-sha2-nistp521' are + implemented. See RFC 5656.

+

+ This raises the security level considerably.

+

+ Own Id: OTP-12622 Aux Id: OTP-12671, OTP-12672

+
+ +

+ The key exchange algorithm 'diffie-hellman-group14-sha1' + is implemented. See RFC 4253.

+

+ This raises the security level.

+

+ Own Id: OTP-12671 Aux Id: OTP-12672, OTP-12622

+
+ +

+ The key exchange algorithms + 'diffie-hellman-group-exchange-sha1' and + 'diffie-hellman-group-exchange-sha256' are implemented. + See RFC 4419.

+

+ This raises the security level.

+

+ Own Id: OTP-12672 Aux Id: OTP-12671, OTP-12622

+
+ +

+ Adding random length extra padding as recommended in RFC + 4253 section 6.

+

+ Own Id: OTP-12831

+
+ +

+ New test library for low-level protocol testing. There is + also a test suite using it for some preliminary tests. + The intention is to build on that for more testing of + individual ssh messages. See + lib/ssh/test/ssh_trpt_test_lib.erl and + ssh_protocol_SUITE.erl in the same directory.

+

+ Own Id: OTP-12858

+
+ +

+ Increased default values for + diffie-hellman-group-exchange-sha* to Min = 1024, N = + 6144, Max = 8192.

+

+ Added 6144 and 8192 bit default gex groups.

+

+ Own Id: OTP-12937

+
+ +

+ The mac algorithm 'hmac-sha2-512' is implemented. See RFC + 6668.

+

+ Own Id: OTP-12938

+
+
+
+ +
+
Ssh 4.0
Fixed Bugs and Malfunctions diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index b87b1b4fa7..6faa3d5f9a 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -26,7 +26,63 @@ notes.xml

This document describes the changes made to the SSL application.

-
SSL 7.0 +
SSL 7.1 + +
Fixed Bugs and Malfunctions + + +

+ Add DER encoded ECPrivateKey as valid input format for + key option.

+

+ Own Id: OTP-12974

+
+ +

+ Correct return value of default session callback module

+

+ This error had the symptom that the client check for + unique session would always fail, potentially making the + client session table grow a lot and causing long setup + times.

+

+ Own Id: OTP-12980

+
+
+
+ + +
Improvements and New Features + + +

+ Add possibility to downgrade an SSL/TLS connection to a + tcp connection, and give back the socket control to a + user process.

+

+ This also adds the possibility to specify a timeout to + the ssl:close function.

+

+ Own Id: OTP-11397

+
+ +

+ Add application setting to be able to change fatal alert + shutdown timeout, also shorten the default timeout. The + fatal alert timeout is the number of milliseconds between + sending of a fatal alert and closing the connection. + Waiting a little while improves the peers chances to + properly receiving the alert so it may shutdown + gracefully.

+

+ Own Id: OTP-12832

+
+
+
+ +
+ +
SSL 7.0
Fixed Bugs and Malfunctions diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 514ac37d90..bdd0680038 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,71 @@

This document describes the changes made to the STDLIB application.

+
STDLIB 2.6 + +
Fixed Bugs and Malfunctions + + +

In OTP 18.0, qlc does not handle syntax errors + well. This bug has been fixed.

+

+ Own Id: OTP-12946

+
+ +

+ Optimize zip:unzip/2 when uncompressing to memory.

+

+ Own Id: OTP-12950

+
+ +

+ The stdlib reference manual is updated to show + correct information about the return value of + gen_fsm:reply/2.

+

+ Own Id: OTP-12973

+
+ +

re:split2,3 and re:replace/3,4 now correctly handles + pre-compiled patterns that have been compiled using the + 'unicode' option.

+

+ Own Id: OTP-12977

+
+ +

+ Export shell:catch_exception/1 as documented.

+

+ Own Id: OTP-12990

+
+
+
+ + +
Improvements and New Features + + +

A mechanism for limiting the amount of text that the + built-in error logger events will produce has been + introduced. It is useful for limiting both the size of + log files and the CPU time used to produce them.

+

This mechanism is experimental in the sense that it + may be changed if it turns out that it does not solve the + problem it is supposed to solve. In that case, there may + be backward incompatible improvements to this + mechanism.

+

See the documentation for the config parameter + error_logger_format_depth in the Kernel + application for information about how to turn on this + feature.

+

+ Own Id: OTP-12864

+
+
+
+ +
+
STDLIB 2.5
Fixed Bugs and Malfunctions diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index e788814564..bf27d2a3e5 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -31,6 +31,25 @@

This document describes the changes made to the Tools application.

+
Tools 2.8.1 + +
Fixed Bugs and Malfunctions + + +

+ If a module includes eunit.hrl, a parse transform adds + the function test/0 on line 0 in the module. A bug in + OTP-18.0 caused cover:analyse_to_file/1 to fail to insert + cover data in the output file when line 0 existed in the + cover data table. This is now corrected.

+

+ Own Id: OTP-12981

+
+
+
+ +
+
Tools 2.8
Fixed Bugs and Malfunctions diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 68c3f6e29c..e4eda213ba 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 2.8 +TOOLS_VSN = 2.8.1 diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index 0f00309f1b..6a0dd898e3 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -32,6 +32,21 @@

This document describes the changes made to the wxErlang application.

+
Wx 1.5 + +
Improvements and New Features + + +

+ Extend AUI functionality.

+

+ Own Id: OTP-12961

+
+
+
+ +
+
Wx 1.4
Fixed Bugs and Malfunctions diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index 09fb9f384c..7608bb3014 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 1.4 +WX_VSN = 1.5 -- cgit v1.2.3 From 345e84991d7892eeb48ff63df3258d7581049d11 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 14 Sep 2015 19:44:11 +0200 Subject: ssh: new state - service_request --- lib/ssh/src/ssh_connection_handler.erl | 35 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index fcd66b80c0..b7a80ae5d4 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -49,7 +49,7 @@ -export([hello/2, kexinit/2, key_exchange/2, key_exchange_dh_gex_init/2, key_exchange_dh_gex_reply/2, new_keys/2, - userauth/2, connected/2, + userauth/2, service_request/2, connected/2, error/2]). -export([init/1, handle_event/3, @@ -82,7 +82,8 @@ recbuf }). --type state_name() :: hello | kexinit | key_exchange | new_keys | userauth | connection. +-type state_name() :: hello | kexinit | key_exchange | key_exchange_dh_gex_init | + key_exchange_dh_gex_reply | new_keys | service_request | userauth | connection. -type gen_fsm_state_return() :: {next_state, state_name(), term()} | {next_state, state_name(), term(), timeout()} | {stop, term(), term()}. @@ -474,28 +475,30 @@ new_keys(#ssh_msg_newkeys{} = Msg, #state{ssh_params = Ssh0} = State0) -> after_new_keys(next_packet(State0#state{ssh_params = Ssh})). %%-------------------------------------------------------------------- --spec userauth(#ssh_msg_service_request{} | #ssh_msg_service_accept{} | - #ssh_msg_userauth_request{} | #ssh_msg_userauth_info_request{} | - #ssh_msg_userauth_info_response{} | #ssh_msg_userauth_success{} | - #ssh_msg_userauth_failure{} | #ssh_msg_userauth_banner{}, - #state{}) -> gen_fsm_state_return(). +-spec service_request(#ssh_msg_service_request{} | #ssh_msg_service_accept{}, + #state{}) -> gen_fsm_state_return(). %%-------------------------------------------------------------------- - -userauth(#ssh_msg_service_request{name = "ssh-userauth"} = Msg, +service_request(#ssh_msg_service_request{name = "ssh-userauth"} = Msg, #state{ssh_params = #ssh{role = server, session_id = SessionId} = Ssh0} = State) -> {ok, {Reply, Ssh}} = ssh_auth:handle_userauth_request(Msg, SessionId, Ssh0), send_msg(Reply, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}; -userauth(#ssh_msg_service_accept{name = "ssh-userauth"}, - #state{ssh_params = #ssh{role = client, - service = "ssh-userauth"} = Ssh0} = - State) -> +service_request(#ssh_msg_service_accept{name = "ssh-userauth"}, + #state{ssh_params = #ssh{role = client, + service = "ssh-userauth"} = Ssh0} = + State) -> {Msg, Ssh} = ssh_auth:init_userauth_request_msg(Ssh0), send_msg(Msg, State), - {next_state, userauth, next_packet(State#state{auth_user = Ssh#ssh.user, ssh_params = Ssh})}; + {next_state, userauth, next_packet(State#state{auth_user = Ssh#ssh.user, ssh_params = Ssh})}. +%%-------------------------------------------------------------------- +-spec userauth(#ssh_msg_userauth_request{} | #ssh_msg_userauth_info_request{} | + #ssh_msg_userauth_info_response{} | #ssh_msg_userauth_success{} | + #ssh_msg_userauth_failure{} | #ssh_msg_userauth_banner{}, + #state{}) -> gen_fsm_state_return(). +%%-------------------------------------------------------------------- userauth(#ssh_msg_userauth_request{service = "ssh-connection", method = "none"} = Msg, #state{ssh_params = #ssh{session_id = SessionId, role = server, @@ -1563,10 +1566,10 @@ after_new_keys(#state{renegotiate = false, ssh_params = #ssh{role = client} = Ssh0} = State) -> {Msg, Ssh} = ssh_auth:service_request_msg(Ssh0), send_msg(Msg, State), - {next_state, userauth, State#state{ssh_params = Ssh}}; + {next_state, service_request, State#state{ssh_params = Ssh}}; after_new_keys(#state{renegotiate = false, ssh_params = #ssh{role = server}} = State) -> - {next_state, userauth, State}. + {next_state, service_request, State}. after_new_keys_events({sync, _Event, From}, {stop, _Reason, _StateData}=Terminator) -> gen_fsm:reply(From, {error, closed}), -- cgit v1.2.3 From a45b4cccb1cf2c669fd73236602b74a9c1c4c773 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 15 Sep 2015 15:20:49 +0200 Subject: ssh: new states for keyboard-interactive --- lib/ssh/src/ssh_auth.erl | 23 ++------- lib/ssh/src/ssh_connection_handler.erl | 85 ++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 47 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index a91b8c200e..ddf033c334 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -153,7 +153,7 @@ userauth_request_msg(#ssh{userauth_methods = Methods, not_ok -> userauth_request_msg(Ssh); Result -> - Result + {Pref,Result} end; false -> userauth_request_msg(Ssh) @@ -313,6 +313,8 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User, #ssh_msg_userauth_failure{authentications = Methods, partial_success = false}, Ssh)}. + + handle_userauth_info_request( #ssh_msg_userauth_info_request{name = Name, instruction = Instr, @@ -330,36 +332,21 @@ handle_userauth_info_request( handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1, data = <>}, #ssh{opts = Opts, - kb_tries_left = KbTriesLeft0, + kb_tries_left = KbTriesLeft, kb_data = InfoMsg, user = User, userauth_supported_methods = Methods} = Ssh) -> - KbTriesLeft = KbTriesLeft0 - 1, case check_password(User, unicode:characters_to_list(Password), Opts) of true -> {authorized, User, ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false when KbTriesLeft > 0 -> - UserAuthInfoMsg = - InfoMsg#ssh_msg_userauth_info_request{ - name = "", - instruction = - lists:concat( - ["Bad user or password, try again. ", - integer_to_list(KbTriesLeft), - " tries left."]) - }, - {not_authorized, {User, undefined}, - ssh_transport:ssh_packet(UserAuthInfoMsg, - Ssh#ssh{kb_tries_left = KbTriesLeft})}; - false -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, partial_success = false}, Ssh#ssh{kb_data = undefined, - kb_tries_left = 0} + kb_tries_left = max(KbTriesLeft-1, 0)} )} end; diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index b7a80ae5d4..646f787874 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -49,7 +49,10 @@ -export([hello/2, kexinit/2, key_exchange/2, key_exchange_dh_gex_init/2, key_exchange_dh_gex_reply/2, new_keys/2, - userauth/2, service_request/2, connected/2, + service_request/2, connected/2, + userauth/2, + userauth_keyboard_interactive/2, + userauth_keyboard_interactive_info_response/2, error/2]). -export([init/1, handle_event/3, @@ -83,7 +86,11 @@ }). -type state_name() :: hello | kexinit | key_exchange | key_exchange_dh_gex_init | - key_exchange_dh_gex_reply | new_keys | service_request | userauth | connection. + key_exchange_dh_gex_reply | new_keys | service_request | + userauth | userauth_keyboard_interactive | + userauth_keyboard_interactive_info_response | + connection. + -type gen_fsm_state_return() :: {next_state, state_name(), term()} | {next_state, state_name(), term(), timeout()} | {stop, term(), term()}. @@ -524,6 +531,10 @@ userauth(#ssh_msg_userauth_request{service = "ssh-connection", connected_fun(User, Address, Method, Opts), {next_state, connected, next_packet(State#state{auth_user = User, ssh_params = Ssh})}; + {not_authorized, {User, Reason}, {Reply, Ssh}} when Method == "keyboard-interactive" -> + retry_fun(User, Address, Reason, Opts), + send_msg(Reply, State), + {next_state, userauth_keyboard_interactive, next_packet(State#state{ssh_params = Ssh})}; {not_authorized, {User, Reason}, {Reply, Ssh}} -> retry_fun(User, Address, Reason, Opts), send_msg(Reply, State), @@ -533,30 +544,6 @@ userauth(#ssh_msg_userauth_request{service = "ssh-connection", userauth(Msg#ssh_msg_userauth_request{method="none"}, State) end; -userauth(#ssh_msg_userauth_info_request{} = Msg, - #state{ssh_params = #ssh{role = client, - io_cb = IoCb} = Ssh0} = State) -> - {ok, {Reply, Ssh}} = ssh_auth:handle_userauth_info_request(Msg, IoCb, Ssh0), - send_msg(Reply, State), - {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}; - -userauth(#ssh_msg_userauth_info_response{} = Msg, - #state{ssh_params = #ssh{role = server, - peer = {_, Address}} = Ssh0, - opts = Opts, starter = Pid} = State) -> - case ssh_auth:handle_userauth_info_response(Msg, Ssh0) of - {authorized, User, {Reply, Ssh}} -> - send_msg(Reply, State), - Pid ! ssh_connected, - connected_fun(User, Address, "keyboard-interactive", Opts), - {next_state, connected, - next_packet(State#state{auth_user = User, ssh_params = Ssh})}; - {not_authorized, {User, Reason}, {Reply, Ssh}} -> - retry_fun(User, Address, Reason, Opts), - send_msg(Reply, State), - {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} - end; - userauth(#ssh_msg_userauth_success{}, #state{ssh_params = #ssh{role = client} = Ssh, starter = Pid} = State) -> Pid ! ssh_connected, @@ -583,19 +570,25 @@ userauth(#ssh_msg_userauth_failure{authentications = Methodes}, {disconnect, DisconnectMsg, {Msg, Ssh}} -> send_msg(Msg, State), handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh}); - {Msg, Ssh} -> + {"keyboard-interactive", {Msg, Ssh}} -> + send_msg(Msg, State), + {next_state, userauth_keyboard_interactive, next_packet(State#state{ssh_params = Ssh})}; + {_Method, {Msg, Ssh}} -> send_msg(Msg, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} end; %% The prefered authentication method failed try next method -userauth(#ssh_msg_userauth_failure{}, +userauth(#ssh_msg_userauth_failure{}, #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> case ssh_auth:userauth_request_msg(Ssh0) of {disconnect, DisconnectMsg,{Msg, Ssh}} -> send_msg(Msg, State), handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh}); - {Msg, Ssh} -> + {"keyboard-interactive", {Msg, Ssh}} -> + send_msg(Msg, State), + {next_state, userauth_keyboard_interactive, next_packet(State#state{ssh_params = Ssh})}; + {_Method, {Msg, Ssh}} -> send_msg(Msg, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} end; @@ -610,6 +603,40 @@ userauth(#ssh_msg_userauth_banner{message = Msg}, io:format("~s", [Msg]), {next_state, userauth, next_packet(State)}. + + +userauth_keyboard_interactive(#ssh_msg_userauth_info_request{} = Msg, + #state{ssh_params = #ssh{role = client, + io_cb = IoCb} = Ssh0} = State) -> + {ok, {Reply, Ssh}} = ssh_auth:handle_userauth_info_request(Msg, IoCb, Ssh0), + send_msg(Reply, State), + {next_state, userauth_keyboard_interactive_info_response, next_packet(State#state{ssh_params = Ssh})}; + +userauth_keyboard_interactive(#ssh_msg_userauth_info_response{} = Msg, + #state{ssh_params = #ssh{role = server, + peer = {_, Address}} = Ssh0, + opts = Opts, starter = Pid} = State) -> + case ssh_auth:handle_userauth_info_response(Msg, Ssh0) of + {authorized, User, {Reply, Ssh}} -> + send_msg(Reply, State), + Pid ! ssh_connected, + connected_fun(User, Address, "keyboard-interactive", Opts), + {next_state, connected, + next_packet(State#state{auth_user = User, ssh_params = Ssh})}; + {not_authorized, {User, Reason}, {Reply, Ssh}} -> + retry_fun(User, Address, Reason, Opts), + send_msg(Reply, State), + {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} + end. + + + +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_failure{}, State) -> + userauth(Msg, State); + +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_success{}, State) -> + userauth(Msg, State). + %%-------------------------------------------------------------------- -spec connected({#ssh_msg_kexinit{}, binary()}, %%| %% #ssh_msg_kexdh_init{}, #state{}) -> gen_fsm_state_return(). -- cgit v1.2.3 From e67f7ea7d62d8addc0a06447ddb28d425d3f650d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 22 Sep 2015 16:26:32 +0200 Subject: ssl: Retry ssl connections on econnreset errors To avoid test case failure due to test case setup timing issues. Suspected problem is that the listen queue builds up to quickly in client_unique_session test when running on slow computers. --- lib/ssl/test/ssl_test_lib.erl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index ba8588f2f9..f25f6f9425 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -226,6 +226,17 @@ run_client(Opts) -> ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]), Pid ! {self(), {error, Reason}} end; + {error, econnreset = Reason} -> + case get(retries) of + N when N < 5 -> + ct:log("~p:~p~neconnreset retries=~p sleep ~p",[?MODULE,?LINE, N,?SLEEP]), + put(retries, N+1), + ct:sleep(?SLEEP), + run_client(Opts); + _ -> + ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]), + Pid ! {self(), {error, Reason}} + end; {error, Reason} -> ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]), Pid ! {connect_failed, Reason}; -- cgit v1.2.3 From 9066d71101d5ac78cdb9690c69d5f74de3e9d10e Mon Sep 17 00:00:00 2001 From: Rich Morin Date: Wed, 23 Sep 2015 11:23:06 -0700 Subject: fix capitalization of headings Several initialisms (eg, ERTS, ETS, SMP) are used as headings. They were being capitalized incorrectly, --- lib/observer/src/observer_sys_wx.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl index d6183d0249..dfd15380f2 100644 --- a/lib/observer/src/observer_sys_wx.erl +++ b/lib/observer/src/observer_sys_wx.erl @@ -83,11 +83,11 @@ update_syspage(#sys_wx_state{node = Node, fields=Fields, sizer=Sizer}) -> info_fields() -> Info = [{"System and Architecture", [{"System Version", otp_release}, - {"Erts Version", version}, + {"ERTS Version", version}, {"Compiled for", system_architecture}, {"Emulator Wordsize", wordsize_external}, {"Process Wordsize", wordsize_internal}, - {"Smp Support", smp_support}, + {"SMP Support", smp_support}, {"Thread Support", threads}, {"Async thread pool size", thread_pool_size} ]}, @@ -106,7 +106,7 @@ info_fields() -> {"Atoms", {bytes, atom}}, {"Binaries", {bytes, binary}}, {"Code", {bytes, code}}, - {"Ets", {bytes, ets}} + {"ETS", {bytes, ets}} ]}, {"Statistics", right, [{"Up time", {time_ms, uptime}}, -- cgit v1.2.3 From fa096962df681f39b1dfe4191f0f3ecc177d906c Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 24 Sep 2015 12:57:42 +0200 Subject: Flush timeout message from message queue when canceling timer In ct_netconfc, if a timer expired 'at the same time' as the server sent the rpc-reply, the timeout message might already be in the client's message queue when the client removed the timer ref from its 'pending' list. This caused a crash in the client since the timer ref could no longer be found when handling the timeout message. This commit fixes the problem by always flushing the timeout message from the message queue when canceling a timer. --- lib/common_test/src/ct_netconfc.erl | 28 ++++++++++++++-------- .../ct_netconfc_SUITE_data/netconfc1_SUITE.erl | 23 ++++++++++++++++++ 2 files changed, 41 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 0de7bf03af..05977e5649 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -1272,6 +1272,14 @@ set_request_timer(T) -> {ok,TRef} = timer:send_after(T,{Ref,timeout}), {Ref,TRef}. +%%%----------------------------------------------------------------- +cancel_request_timer(undefined,undefined) -> + ok; +cancel_request_timer(Ref,TRef) -> + _ = timer:cancel(TRef), + receive {Ref,timeout} -> ok + after 0 -> ok + end. %%%----------------------------------------------------------------- client_hello(Options) when is_list(Options) -> @@ -1404,9 +1412,9 @@ handle_error(Reason, State) -> Pending -> %% Assuming the first request gets the %% first answer - P=#pending{tref=TRef,caller=Caller} = + P=#pending{tref=TRef,ref=Ref,caller=Caller} = lists:last(Pending), - _ = timer:cancel(TRef), + cancel_request_timer(Ref,TRef), Reason1 = {failed_to_parse_received_data,Reason}, ct_gen_conn:return(Caller,{error,Reason1}), lists:delete(P,Pending) @@ -1492,8 +1500,8 @@ decode({Tag,Attrs,_}=E, #state{connection=Connection,pending=Pending}=State) -> {error,Reason} -> {noreply,State#state{hello_status = {error,Reason}}} end; - #pending{tref=TRef,caller=Caller} -> - _ = timer:cancel(TRef), + #pending{tref=TRef,ref=Ref,caller=Caller} -> + cancel_request_timer(Ref,TRef), case decode_hello(E) of {ok,SessionId,Capabilities} -> ct_gen_conn:return(Caller,ok), @@ -1519,9 +1527,8 @@ decode({Tag,Attrs,_}=E, #state{connection=Connection,pending=Pending}=State) -> %% there is just one pending that matches (i.e. has %% undefined msg_id and op) case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of - [#pending{tref=TRef, - caller=Caller}] -> - _ = timer:cancel(TRef), + [#pending{tref=TRef,ref=Ref,caller=Caller}] -> + cancel_request_timer(Ref,TRef), ct_gen_conn:return(Caller,E), {noreply,State#state{pending=[]}}; _ -> @@ -1542,8 +1549,8 @@ get_msg_id(Attrs) -> decode_rpc_reply(MsgId,{_,Attrs,Content0}=E,#state{pending=Pending} = State) -> case lists:keytake(MsgId,#pending.msg_id,Pending) of - {value, #pending{tref=TRef,op=Op,caller=Caller}, Pending1} -> - _ = timer:cancel(TRef), + {value, #pending{tref=TRef,ref=Ref,op=Op,caller=Caller}, Pending1} -> + cancel_request_timer(Ref,TRef), Content = forward_xmlns_attr(Attrs,Content0), {CallerReply,{ServerReply,State2}} = do_decode_rpc_reply(Op,Content,State#state{pending=Pending1}), @@ -1555,10 +1562,11 @@ decode_rpc_reply(MsgId,{_,Attrs,Content0}=E,#state{pending=Pending} = State) -> %% pending that matches (i.e. has undefined msg_id and op) case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of [#pending{tref=TRef, + ref=Ref, msg_id=undefined, op=undefined, caller=Caller}] -> - _ = timer:cancel(TRef), + cancel_request_timer(Ref,TRef), ct_gen_conn:return(Caller,E), {noreply,State#state{pending=[]}}; _ -> diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl index 64ebfbc463..aaa0723488 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -73,6 +73,7 @@ all() -> timeout_close_session, get, timeout_get, + flush_timeout_get, get_xpath, get_config, get_config_xpath, @@ -360,6 +361,28 @@ timeout_get(Config) -> ?ok = ct_netconfc:close_session(Client), ok. +%% Test OTP-13008 "ct_netconfc crash when receiving unknown timeout" +%% If the timer expires "at the same time" as the rpc reply is +%% received, the timeout message might already be sent when the timer +%% is cancelled. This test checks that the timeout message is flushed +%% from the message queue. If it isn't, the client crashes and the +%% session can not be closed afterwards. +%% Note that we can only hope that the test case triggers the problem +%% every now and then, as it is very timing dependent... +flush_timeout_get(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}], + ?NS:expect_reply('get',{data,Data}), + timer:sleep(1000), + case ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},1) of + {error,timeout} -> ok; % problem not triggered + {ok,Data} -> ok % problem possibly triggered + end, + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + get_xpath(Config) -> DataDir = ?config(data_dir,Config), {ok,Client} = open_success(DataDir), -- cgit v1.2.3 From cb2ba8f0c880479fcc60017f122f892a23c4f5b2 Mon Sep 17 00:00:00 2001 From: Luca Favatella Date: Tue, 1 Oct 2013 18:54:34 +0100 Subject: Fix typo in SNMP MIB in documentation --- lib/snmp/doc/src/snmp_advanced_agent.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/snmp/doc/src/snmp_advanced_agent.xml b/lib/snmp/doc/src/snmp_advanced_agent.xml index 717f7426c6..b17246438d 100644 --- a/lib/snmp/doc/src/snmp_advanced_agent.xml +++ b/lib/snmp/doc/src/snmp_advanced_agent.xml @@ -340,7 +340,7 @@ SEQUENCE { empDepNo INTEGER, empName DisplayString, - empTelNo DisplayString + empTelNo DisplayString, empStatus RowStatus } -- cgit v1.2.3 From 8b480500f5004cf179f4993a56ad97e8f8171d94 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 24 Sep 2015 16:52:30 +0200 Subject: ssh: remove unused filed #ssh.kb_data --- lib/ssh/src/ssh.hrl | 1 - lib/ssh/src/ssh_auth.erl | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 462c98f503..da64e4abf9 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -133,7 +133,6 @@ userauth_supported_methods, % string() eg "keyboard-interactive,password" userauth_methods, % list( string() ) eg ["keyboard-interactive", "password"] kb_tries_left = 0, % integer(), num tries left for "keyboard-interactive" - kb_data, userauth_preference, available_host_keys, authenticated = false diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index ddf033c334..726f52132f 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -299,8 +299,7 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User, >> }, {not_authorized, {User, undefined}, - ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User, - kb_data = Msg + ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User })} end; @@ -333,7 +332,6 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1, data = <>}, #ssh{opts = Opts, kb_tries_left = KbTriesLeft, - kb_data = InfoMsg, user = User, userauth_supported_methods = Methods} = Ssh) -> case check_password(User, unicode:characters_to_list(Password), Opts) of @@ -345,8 +343,7 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, partial_success = false}, - Ssh#ssh{kb_data = undefined, - kb_tries_left = max(KbTriesLeft-1, 0)} + Ssh#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} )} end; -- cgit v1.2.3 From 14cb29199246feabf3851f3e0d3f8b69da0d990d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 24 Sep 2015 20:01:09 +0200 Subject: inets: Adjust makefile to new windows compiler --- lib/inets/test/httpd_SUITE_data/Makefile.src | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/inets/test/httpd_SUITE_data/Makefile.src b/lib/inets/test/httpd_SUITE_data/Makefile.src index b0fdb43d8d..cea40dd8cb 100644 --- a/lib/inets/test/httpd_SUITE_data/Makefile.src +++ b/lib/inets/test/httpd_SUITE_data/Makefile.src @@ -10,5 +10,10 @@ all: $(PROGS) cgi_echo@exe@: cgi_echo@obj@ $(LD) $(CROSSLDFLAGS) -o cgi_echo cgi_echo@obj@ @LIBS@ +@IFEQ@ (@CC@, cl -nologo) +cgi_echo@obj@: cgi_echo.c + $(CC) /c /Focgi_echo@obj@ $(CFLAGS) cgi_echo.c +@ELSE@ cgi_echo@obj@: cgi_echo.c $(CC) -c -o cgi_echo@obj@ $(CFLAGS) cgi_echo.c +@ENDIF@ -- cgit v1.2.3 From 5e476007bf9ede36911965b509598f76d9cf082a Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Fri, 18 Sep 2015 15:59:52 +0100 Subject: Fix typos in crypto documentation s/stong_rand_bytes/strong_rand_bytes/, s/bts/bits/ --- lib/crypto/doc/src/crypto.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 385a583883..291a5145e4 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -617,7 +617,7 @@ RAND_seed function from openssl. Only use this if the system you are running on does not have enough "randomness" built in. Normally this is when - stong_rand_bytes/1 returns low_entropy

+ strong_rand_bytes/1 returns low_entropy

@@ -710,7 +710,7 @@

Initializes the state for use in streaming AES encryption using Counter mode (CTR). - Key is the AES key and must be either 128, 192, or 256 bts long. IVec is + Key is the AES key and must be either 128, 192, or 256 bits long. IVec is an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with stream_encrypt and stream_decrypt.

-- cgit v1.2.3 From 68aac2e50559d9d67b1c2152166f8f2e08b03880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Wei=C3=9F?= Date: Tue, 2 Jun 2015 16:12:15 +0200 Subject: inet_res: Make host name lookups case-insensitive This partly reverts commit 8152505ea3793037984a7f3349ac95cc20c4e44c. --- lib/kernel/src/inet_db.erl | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl index 2ebdc0f554..ee7dfaeb3d 100644 --- a/lib/kernel/src/inet_db.erl +++ b/lib/kernel/src/inet_db.erl @@ -632,20 +632,22 @@ make_hostent(Name, Datas, Aliases, Type) -> hostent_by_domain(Domain, Type) -> ?dbg("hostent_by_domain: ~p~n", [Domain]), - hostent_by_domain(stripdot(Domain), [], Type). + hostent_by_domain(stripdot(Domain), [], [], Type). -hostent_by_domain(Domain, Aliases, Type) -> +hostent_by_domain(Domain, Aliases, LAliases, Type) -> case lookup_type(Domain, Type) of [] -> case lookup_cname(Domain) of [] -> {error, nxdomain}; [CName | _] -> - case lists:member(CName, [Domain | Aliases]) of + LDomain = tolower(Domain), + case lists:member(CName, [LDomain | LAliases]) of true -> {error, nxdomain}; false -> - hostent_by_domain(CName, [Domain | Aliases], Type) + hostent_by_domain(CName, [Domain | Aliases], + [LDomain | LAliases], Type) end end; Addrs -> @@ -670,24 +672,26 @@ lookup_rr(Domain, Class, Type) -> %% match data field directly and cache RRs. %% res_hostent_by_domain(Domain, Type, Rec) -> - res_cache_answer(Rec), - RRs = Rec#dns_rec.anlist, + RRs = lists:map(fun lower_rr/1, Rec#dns_rec.anlist), + res_cache_answer(Rec#dns_rec{anlist = RRs}), ?dbg("res_hostent_by_domain: ~p - ~p~n", [Domain, RRs]), - res_hostent_by_domain(stripdot(Domain), [], Type, RRs). + res_hostent_by_domain(stripdot(Domain), [], [], Type, RRs). -res_hostent_by_domain(Domain, Aliases, Type, RRs) -> - case res_lookup_type(Domain, Type, RRs) of +res_hostent_by_domain(Domain, Aliases, LAliases, Type, RRs) -> + LDomain = tolower(Domain), + case res_lookup_type(LDomain, Type, RRs) of [] -> - case res_lookup_type(Domain, ?S_CNAME, RRs) of + case res_lookup_type(LDomain, ?S_CNAME, RRs) of [] -> {error, nxdomain}; [CName | _] -> - case lists:member(CName, [Domain | Aliases]) of + case lists:member(tolower(CName), [LDomain | LAliases]) of true -> {error, nxdomain}; false -> res_hostent_by_domain(CName, [Domain | Aliases], - Type, RRs) + [LDomain | LAliases], Type, + RRs) end end; Addrs -> @@ -720,7 +724,8 @@ gethostbyaddr(IP) -> %% res_gethostbyaddr(IP, Rec) -> {ok, {IP1, HType, HLen}} = dnt(IP), - res_cache_answer(Rec), + RRs = lists:map(fun lower_rr/1, Rec#dns_rec.anlist), + res_cache_answer(Rec#dns_rec{anlist = RRs}), ent_gethostbyaddr(Rec#dns_rec.anlist, IP1, HType, HLen). ent_gethostbyaddr(RRs, IP, AddrType, Length) -> @@ -1378,7 +1383,7 @@ times() -> %% lookup and remove old entries do_lookup_rr(Domain, Class, Type) -> - match_rr(#dns_rr{domain = Domain, class = Class,type = Type, + match_rr(#dns_rr{domain = tolower(Domain), class = Class,type = Type, cnt = '_', tm = '_', ttl = '_', bm = '_', func = '_', data = '_'}). @@ -1400,6 +1405,11 @@ filter_rr([RR | RRs], Time) -> [RR | filter_rr(RRs, Time)]; filter_rr([], _Time) -> []. +%% Lower case the domain name before storage. +%% +lower_rr(#dns_rr{domain=Domain}=RR) when is_list(Domain) -> + RR#dns_rr { domain = tolower(Domain) }; +lower_rr(RR) -> RR. %% %% Case fold upper-case to lower-case according to RFC 4343 -- cgit v1.2.3 From ba531a173d0dc6906f8492f3bfa0b2cd40e2951a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 25 Sep 2015 12:40:14 +0200 Subject: typer: Fix a bug Instead of outputting a formatted message showing errors found, a core was (often) created. --- lib/typer/src/typer.erl | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl index ec00bfaba0..562530c868 100644 --- a/lib/typer/src/typer.erl +++ b/lib/typer/src/typer.erl @@ -1012,15 +1012,7 @@ compile_error(Reason) -> -spec msg(string()) -> 'ok'. msg(Msg) -> - case os:type() of - {unix, _} -> % Output a message on 'stderr', if possible - P = open_port({fd, 0, 2}, [out]), - port_command(P, Msg), - true = port_close(P), - ok; - _ -> % win32 - io:format("~s", [Msg]) - end. + io:format(standard_error, "~s", [Msg]). %%-------------------------------------------------------------------- %% Version and help messages. -- cgit v1.2.3 From 9504c0dd71d0b1b49251a97f45c71c8882ce7708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 15 Sep 2015 13:55:38 +0200 Subject: v3_codegen: Optimize matching of the final size-less binary segment Consider the following function: f(Bin, Bool) -> case Bin of <> when Bool -> Val end. Simplified, the generated code looks like: bs_start_match2 Fail Live Bin => Bin bs_get_integer2 Fail Live Bin size=Sz unit=1 => Val bs_skip_bits2 Fail Bin size=all unit=8 is_eq_exact Fail Bool true The code generator will replace the bs_skip_bits2 instruction with a bs_test_unit instruction if it can be clearly seen that the context register will not be used again. In this case, it is not obvious without looking at the code at the Fail label. However, it turns out that bs_test_unit instruction is always safe beacuse of the way v3_kernel compiles pattern matching. It doesn't matter whether the match context will be used again. If it will be used again, the position in it will *not* be used. Instead, a bs_restore2 instruction will restore one of the saved instructions. --- lib/compiler/src/v3_codegen.erl | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index 34c67b16ca..5083995f30 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -827,21 +827,24 @@ select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf, {bs_save2,CtxReg,{Ctx,Tl}}],Int1} end, {Es,clear_dead(Aft, I, Vdb),St}; -select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf, +select_extract_bin([{var,Hd}], Size, Unit, binary, Flags, Vf, I, Vdb, Bef, Ctx, Body, St) -> - SizeReg = get_bin_size_reg(Size0, Bef), + %% Match the last segment of a binary. We KNOW that the size + %% must be 'all'. + Size = {atom,all}, %Assertion. {Es,Aft} = case vdb_find(Hd, Vdb) of {_,_,Lhd} when Lhd =< I -> + %% The result will not be used. Furthermore, since we + %% we are at the end of the binary, the position will + %% not be used again; thus, it is safe to do a cheaper + %% test of the unit. CtxReg = fetch_var(Ctx, Bef), - {case SizeReg =:= {atom,all} andalso is_context_unused(Body) of - true when Unit =:= 1 -> + {case Unit of + 1 -> []; - true -> - [{test,bs_test_unit,{f,Vf},[CtxReg,Unit]}]; - false -> - [{test,bs_skip_bits2,{f,Vf}, - [CtxReg,SizeReg,Unit,{field_flags,Flags}]}] + _ -> + [{test,bs_test_unit,{f,Vf},[CtxReg,Unit]}] end,Bef}; {_,_,_} -> case is_context_unused(Body) of @@ -853,7 +856,7 @@ select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf, Name = bs_get_binary2, Live = max_reg(Bef#sr.reg), {[{test,Name,{f,Vf},Live, - [CtxReg,SizeReg,Unit,{field_flags,Flags}],Rhd}], + [CtxReg,Size,Unit,{field_flags,Flags}],Rhd}], Int1}; true -> %% Since the matching context will not be used again, @@ -868,7 +871,7 @@ select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf, Name = bs_get_binary2, Live = max_reg(Int1#sr.reg), {[{test,Name,{f,Vf},Live, - [CtxReg,SizeReg,Unit,{field_flags,Flags}],CtxReg}], + [CtxReg,Size,Unit,{field_flags,Flags}],CtxReg}], Int1} end end, -- cgit v1.2.3 From f7fd259f27bce0058d996af6287e6bb81d12ea47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 15 Sep 2015 16:50:19 +0200 Subject: sys_core_fold: Extend the list of BIFs that return integers Knowing that a BIF returns an integer makes it possible to replace '==' with the cheaper '=:=' test. --- lib/compiler/src/sys_core_fold.erl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 27d023d067..0a16776bd4 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -2793,12 +2793,18 @@ extract_type_1(Expr, Sub) -> true -> bool end. +returns_integer('band', [_,_]) -> true; +returns_integer('bnot', [_]) -> true; +returns_integer('bor', [_,_]) -> true; +returns_integer('bxor', [_,_]) -> true; returns_integer(bit_size, [_]) -> true; returns_integer('bsl', [_,_]) -> true; returns_integer('bsr', [_,_]) -> true; returns_integer(byte_size, [_]) -> true; +returns_integer('div', [_,_]) -> true; returns_integer(length, [_]) -> true; returns_integer('rem', [_,_]) -> true; +returns_integer('round', [_]) -> true; returns_integer(size, [_]) -> true; returns_integer(tuple_size, [_]) -> true; returns_integer(trunc, [_]) -> true; -- cgit v1.2.3 From 8372f56a06ef24cf4455a54e15d876ab6ca8c570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 21 Sep 2015 14:27:30 +0200 Subject: Move out bit syntax optimizations from beam_block In the future we might want to add more bit syntax optimizations, but beam_block is already sufficiently complicated. Therefore, move the bit syntax optimizations out of beam_block into a separate compiler pass called beam_bs. --- lib/compiler/src/Makefile | 1 + lib/compiler/src/beam_block.erl | 261 ++------------------------------- lib/compiler/src/beam_bs.erl | 278 ++++++++++++++++++++++++++++++++++++ lib/compiler/src/compile.erl | 2 + lib/compiler/src/compiler.app.src | 1 + lib/compiler/test/compile_SUITE.erl | 2 + lib/compiler/test/misc_SUITE.erl | 4 + 7 files changed, 298 insertions(+), 251 deletions(-) create mode 100644 lib/compiler/src/beam_bs.erl (limited to 'lib') diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index ae4007c61c..f75beaba20 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -50,6 +50,7 @@ MODULES = \ beam_asm \ beam_block \ beam_bool \ + beam_bs \ beam_bsm \ beam_clean \ beam_dead \ diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index ebf9b5fec5..741fdbb973 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -23,13 +23,13 @@ -module(beam_block). -export([module/2]). --import(lists, [mapfoldl/3,reverse/1,reverse/2,foldl/3,member/2]). +-import(lists, [reverse/1,reverse/2,foldl/3,member/2]). -module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) -> - {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0), +module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> + Fs = [function(F) || F <- Fs0], {ok,{Mod,Exp,Attr,Fs,Lc}}. -function({function,Name,Arity,CLabel,Is0}, Lc0) -> +function({function,Name,Arity,CLabel,Is0}) -> try %% Collect basic blocks and optimize them. Is1 = blockify(Is0), @@ -39,11 +39,8 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) -> Is5 = opt_blocks(Is4), Is6 = beam_utils:delete_live_annos(Is5), - %% Optimize bit syntax. - {Is,Lc} = bsm_opt(Is6, Lc0), - %% Done. - {{function,Name,Arity,CLabel,Is},Lc} + {function,Name,Arity,CLabel,Is6} catch Class:Error -> Stack = erlang:get_stacktrace(), @@ -89,18 +86,11 @@ blockify([{test,is_atom,{f,Fail},[Reg]}=I| {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc]) end; blockify([I|Is0]=IsAll, Acc) -> - case is_bs_put(I) of - true -> - {BsPuts0,Is} = collect_bs_puts(IsAll), - BsPuts = opt_bs_puts(BsPuts0), - blockify(Is, reverse(BsPuts, Acc)); - false -> - case collect(I) of - error -> blockify(Is0, [I|Acc]); - Instr when is_tuple(Instr) -> - {Block,Is} = collect_block(IsAll), - blockify(Is, [{block,Block}|Acc]) - end + case collect(I) of + error -> blockify(Is0, [I|Acc]); + Instr when is_tuple(Instr) -> + {Block,Is} = collect_block(IsAll), + blockify(Is, [{block,Block}|Acc]) end; blockify([], Acc) -> reverse(Acc). @@ -493,234 +483,3 @@ x_dead([], Regs) -> Regs. x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N)); x_live([_|Rs], Regs) -> x_live(Rs, Regs); x_live([], Regs) -> Regs. - -%%% -%%% Evaluation of constant bit fields. -%%% - -is_bs_put({bs_put,_,{bs_put_integer,_,_},_}) -> true; -is_bs_put({bs_put,_,{bs_put_float,_,_},_}) -> true; -is_bs_put(_) -> false. - -collect_bs_puts(Is) -> - collect_bs_puts_1(Is, []). - -collect_bs_puts_1([I|Is]=Is0, Acc) -> - case is_bs_put(I) of - false -> {reverse(Acc),Is0}; - true -> collect_bs_puts_1(Is, [I|Acc]) - end. - -opt_bs_puts(Is) -> - opt_bs_1(Is, []). - -opt_bs_1([{bs_put,Fail, - {bs_put_float,1,Flags0},[{integer,Sz},Src]}=I0|Is], Acc) -> - try eval_put_float(Src, Sz, Flags0) of - <> -> - Flags = force_big(Flags0), - I = {bs_put,Fail,{bs_put_integer,1,Flags}, - [{integer,Sz},{integer,Int}]}, - opt_bs_1([I|Is], Acc) - catch - error:_ -> - opt_bs_1(Is, [I0|Acc]) - end; -opt_bs_1([{bs_put,_,{bs_put_integer,1,_},[{integer,8},{integer,_}]}|_]=IsAll, - Acc0) -> - {Is,Acc} = bs_collect_string(IsAll, Acc0), - opt_bs_1(Is, Acc); -opt_bs_1([{bs_put,Fail,{bs_put_integer,1,F},[{integer,Sz},{integer,N}]}=I|Is0], - Acc) when Sz > 8 -> - case field_endian(F) of - big -> - %% We can do this optimization for any field size without risk - %% for code explosion. - case bs_split_int(N, Sz, Fail, Is0) of - no_split -> opt_bs_1(Is0, [I|Acc]); - Is -> opt_bs_1(Is, Acc) - end; - little when Sz < 128 -> - %% We only try to optimize relatively small fields, to avoid - %% an explosion in code size. - <> = <>, - Flags = force_big(F), - Is = [{bs_put,Fail,{bs_put_integer,1,Flags}, - [{integer,Sz},{integer,Int}]}|Is0], - opt_bs_1(Is, Acc); - _ -> %native or too wide little field - opt_bs_1(Is0, [I|Acc]) - end; -opt_bs_1([{bs_put,Fail,{Op,U,F},[{integer,Sz},Src]}|Is], Acc) when U > 1 -> - opt_bs_1([{bs_put,Fail,{Op,1,F},[{integer,U*Sz},Src]}|Is], Acc); -opt_bs_1([I|Is], Acc) -> - opt_bs_1(Is, [I|Acc]); -opt_bs_1([], Acc) -> reverse(Acc). - -eval_put_float(Src, Sz, Flags) when Sz =< 256 -> %Only evaluate if Sz is reasonable. - Val = value(Src), - case field_endian(Flags) of - little -> <>; - big -> <> - %% native intentionally not handled here - we can't optimize it. - end. - -value({integer,I}) -> I; -value({float,F}) -> F. - -bs_collect_string(Is, [{bs_put,_,{bs_put_string,Len,{string,Str}},[]}|Acc]) -> - bs_coll_str_1(Is, Len, reverse(Str), Acc); -bs_collect_string(Is, Acc) -> - bs_coll_str_1(Is, 0, [], Acc). - -bs_coll_str_1([{bs_put,_,{bs_put_integer,U,_},[{integer,Sz},{integer,V}]}|Is], - Len, StrAcc, IsAcc) when U*Sz =:= 8 -> - Byte = V band 16#FF, - bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc); -bs_coll_str_1(Is, Len, StrAcc, IsAcc) -> - {Is,[{bs_put,{f,0},{bs_put_string,Len,{string,reverse(StrAcc)}},[]}|IsAcc]}. - -field_endian({field_flags,F}) -> field_endian_1(F). - -field_endian_1([big=E|_]) -> E; -field_endian_1([little=E|_]) -> E; -field_endian_1([native=E|_]) -> E; -field_endian_1([_|Fs]) -> field_endian_1(Fs). - -force_big({field_flags,F}) -> - {field_flags,force_big_1(F)}. - -force_big_1([big|_]=Fs) -> Fs; -force_big_1([little|Fs]) -> [big|Fs]; -force_big_1([F|Fs]) -> [F|force_big_1(Fs)]. - -bs_split_int(0, Sz, _, _) when Sz > 64 -> - %% We don't want to split in this case because the - %% string will consist of only zeroes. - no_split; -bs_split_int(-1, Sz, _, _) when Sz > 64 -> - %% We don't want to split in this case because the - %% string will consist of only 255 bytes. - no_split; -bs_split_int(N, Sz, Fail, Acc) -> - FirstByteSz = case Sz rem 8 of - 0 -> 8; - Rem -> Rem - end, - bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc). - -bs_split_int_1(-1, _, Sz, Fail, Acc) when Sz > 64 -> - I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, - [{integer,Sz},{integer,-1}]}, - [I|Acc]; -bs_split_int_1(0, _, Sz, Fail, Acc) when Sz > 64 -> - I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, - [{integer,Sz},{integer,0}]}, - [I|Acc]; -bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 -> - Mask = (1 bsl ByteSz) - 1, - I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, - [{integer,ByteSz},{integer,N band Mask}]}, - bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]); -bs_split_int_1(_, _, _, _, Acc) -> Acc. - - -%%% -%%% Optimization of new bit syntax matching: get rid -%%% of redundant bs_restore2/2 instructions across select_val -%%% instructions, as well as a few other simple peep-hole optimizations. -%%% - -bsm_opt(Is0, Lc0) -> - {Is1,D0,Lc} = bsm_scan(Is0, [], Lc0, []), - Is2 = case D0 of - [] -> - Is1; - _ -> - D = gb_trees:from_orddict(orddict:from_list(D0)), - bsm_reroute(Is1, D, none, []) - end, - Is = beam_clean:bs_clean_saves(Is2), - {bsm_opt_2(Is, []),Lc}. - -bsm_scan([{label,L}=Lbl,{bs_restore2,_,Save}=R|Is], D0, Lc, Acc0) -> - D = [{{L,Save},Lc}|D0], - Acc = [{label,Lc},R,Lbl|Acc0], - bsm_scan(Is, D, Lc+1, Acc); -bsm_scan([I|Is], D, Lc, Acc) -> - bsm_scan(Is, D, Lc, [I|Acc]); -bsm_scan([], D, Lc, Acc) -> - {reverse(Acc),D,Lc}. - -bsm_reroute([{bs_save2,Reg,Save}=I|Is], D, _, Acc) -> - bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); -bsm_reroute([{bs_restore2,Reg,Save}=I|Is], D, _, Acc) -> - bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); -bsm_reroute([{label,_}=I|Is], D, S, Acc) -> - bsm_reroute(Is, D, S, [I|Acc]); -bsm_reroute([{select,select_val,Reg,F0,Lbls0}|Is], D, {_,Save}=S, Acc0) -> - [F|Lbls] = bsm_subst_labels([F0|Lbls0], Save, D), - Acc = [{select,select_val,Reg,F,Lbls}|Acc0], - bsm_reroute(Is, D, S, Acc); -bsm_reroute([{test,TestOp,F0,TestArgs}=I|Is], D, {_,Save}=S, Acc0) -> - F = bsm_subst_label(F0, Save, D), - Acc = [{test,TestOp,F,TestArgs}|Acc0], - case bsm_not_bs_test(I) of - true -> - %% The test instruction will not update the bit offset for the - %% binary being matched. Therefore the save position can be kept. - bsm_reroute(Is, D, S, Acc); - false -> - %% The test instruction might update the bit offset. Kill our - %% remembered Save position. - bsm_reroute(Is, D, none, Acc) - end; -bsm_reroute([{test,TestOp,F0,Live,TestArgs,Dst}|Is], D, {_,Save}, Acc0) -> - F = bsm_subst_label(F0, Save, D), - Acc = [{test,TestOp,F,Live,TestArgs,Dst}|Acc0], - %% The test instruction will update the bit offset. Kill our - %% remembered Save position. - bsm_reroute(Is, D, none, Acc); -bsm_reroute([{block,[{set,[],[],{alloc,_,_}}]}=Bl, - {bs_context_to_binary,_}=I|Is], D, S, Acc) -> - %% To help further bit syntax optimizations. - bsm_reroute([I,Bl|Is], D, S, Acc); -bsm_reroute([I|Is], D, _, Acc) -> - bsm_reroute(Is, D, none, [I|Acc]); -bsm_reroute([], _, _, Acc) -> reverse(Acc). - -bsm_opt_2([{test,bs_test_tail2,F,[Ctx,Bits]}|Is], - [{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]}|Acc]) -> - bsm_opt_2(Is, [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|Acc]); -bsm_opt_2([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,_]}|Is], - [{test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,Flags]}|Acc]) -> - bsm_opt_2(Is, [{test,bs_skip_bits2,F, - [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]); -bsm_opt_2([I|Is], Acc) -> - bsm_opt_2(Is, [I|Acc]); -bsm_opt_2([], Acc) -> reverse(Acc). - -%% bsm_not_bs_test({test,Name,_,Operands}) -> true|false. -%% Test whether is the test is a "safe", i.e. does not move the -%% bit offset for a binary. -%% -%% 'true' means that the test is safe, 'false' that we don't know or -%% that the test moves the offset (e.g. bs_get_integer2). - -bsm_not_bs_test({test,bs_test_tail2,_,[_,_]}) -> true; -bsm_not_bs_test(Test) -> beam_utils:is_pure_test(Test). - -bsm_subst_labels(Fs, Save, D) -> - bsm_subst_labels_1(Fs, Save, D, []). - -bsm_subst_labels_1([F|Fs], Save, D, Acc) -> - bsm_subst_labels_1(Fs, Save, D, [bsm_subst_label(F, Save, D)|Acc]); -bsm_subst_labels_1([], _, _, Acc) -> - reverse(Acc). - -bsm_subst_label({f,Lbl0}=F, Save, D) -> - case gb_trees:lookup({Lbl0,Save}, D) of - {value,Lbl} -> {f,Lbl}; - none -> F - end; -bsm_subst_label(Other, _, _) -> Other. diff --git a/lib/compiler/src/beam_bs.erl b/lib/compiler/src/beam_bs.erl new file mode 100644 index 0000000000..55fa7ce10c --- /dev/null +++ b/lib/compiler/src/beam_bs.erl @@ -0,0 +1,278 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% Purpose : Partitions assembly instructions into basic blocks and +%% optimizes them. + +-module(beam_bs). + +-export([module/2]). +-import(lists, [mapfoldl/3,reverse/1]). + +module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) -> + {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0), + {ok,{Mod,Exp,Attr,Fs,Lc}}. + +function({function,Name,Arity,CLabel,Is0}, Lc0) -> + try + Is1 = bs_put_opt(Is0), + {Is,Lc} = bsm_opt(Is1, Lc0), + {{function,Name,Arity,CLabel,Is},Lc} + catch + Class:Error -> + Stack = erlang:get_stacktrace(), + io:fwrite("Function: ~w/~w\n", [Name,Arity]), + erlang:raise(Class, Error, Stack) + end. + +%%% +%%% Evaluation of constant bit fields. +%%% + +bs_put_opt([{bs_put,_,_,_}=I|Is0]) -> + {BsPuts0,Is} = collect_bs_puts(Is0, [I]), + BsPuts = opt_bs_puts(BsPuts0), + BsPuts ++ bs_put_opt(Is); +bs_put_opt([I|Is]) -> + [I|bs_put_opt(Is)]; +bs_put_opt([]) -> []. + +collect_bs_puts([{bs_put,_,_,_}=I|Is], Acc) -> + collect_bs_puts(Is, [I|Acc]); +collect_bs_puts([_|_]=Is, Acc) -> + {reverse(Acc),Is}. + +opt_bs_puts(Is) -> + opt_bs_1(Is, []). + +opt_bs_1([{bs_put,Fail, + {bs_put_float,1,Flags0},[{integer,Sz},Src]}=I0|Is], Acc) -> + try eval_put_float(Src, Sz, Flags0) of + <> -> + Flags = force_big(Flags0), + I = {bs_put,Fail,{bs_put_integer,1,Flags}, + [{integer,Sz},{integer,Int}]}, + opt_bs_1([I|Is], Acc) + catch + error:_ -> + opt_bs_1(Is, [I0|Acc]) + end; +opt_bs_1([{bs_put,_,{bs_put_integer,1,_},[{integer,8},{integer,_}]}|_]=IsAll, + Acc0) -> + {Is,Acc} = bs_collect_string(IsAll, Acc0), + opt_bs_1(Is, Acc); +opt_bs_1([{bs_put,Fail,{bs_put_integer,1,F},[{integer,Sz},{integer,N}]}=I|Is0], + Acc) when Sz > 8 -> + case field_endian(F) of + big -> + %% We can do this optimization for any field size without + %% risk for code explosion. + case bs_split_int(N, Sz, Fail, Is0) of + no_split -> opt_bs_1(Is0, [I|Acc]); + Is -> opt_bs_1(Is, Acc) + end; + little when Sz < 128 -> + %% We only try to optimize relatively small fields, to + %% avoid an explosion in code size. + <> = <>, + Flags = force_big(F), + Is = [{bs_put,Fail,{bs_put_integer,1,Flags}, + [{integer,Sz},{integer,Int}]}|Is0], + opt_bs_1(Is, Acc); + _ -> %native or too wide little field + opt_bs_1(Is0, [I|Acc]) + end; +opt_bs_1([{bs_put,Fail,{Op,U,F},[{integer,Sz},Src]}|Is], Acc) when U > 1 -> + opt_bs_1([{bs_put,Fail,{Op,1,F},[{integer,U*Sz},Src]}|Is], Acc); +opt_bs_1([I|Is], Acc) -> + opt_bs_1(Is, [I|Acc]); +opt_bs_1([], Acc) -> reverse(Acc). + +eval_put_float(Src, Sz, Flags) when Sz =< 256 -> + %%Only evaluate if Sz is reasonable. + Val = value(Src), + case field_endian(Flags) of + little -> <>; + big -> <> + %% native intentionally not handled here - we can't optimize + %% it. + end. + +value({integer,I}) -> I; +value({float,F}) -> F. + +bs_collect_string(Is, [{bs_put,_,{bs_put_string,Len,{string,Str}},[]}|Acc]) -> + bs_coll_str_1(Is, Len, reverse(Str), Acc); +bs_collect_string(Is, Acc) -> + bs_coll_str_1(Is, 0, [], Acc). + +bs_coll_str_1([{bs_put,_,{bs_put_integer,U,_},[{integer,Sz},{integer,V}]}|Is], + Len, StrAcc, IsAcc) when U*Sz =:= 8 -> + Byte = V band 16#FF, + bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc); +bs_coll_str_1(Is, Len, StrAcc, IsAcc) -> + {Is,[{bs_put,{f,0},{bs_put_string,Len,{string,reverse(StrAcc)}},[]}|IsAcc]}. + +field_endian({field_flags,F}) -> field_endian_1(F). + +field_endian_1([big=E|_]) -> E; +field_endian_1([little=E|_]) -> E; +field_endian_1([native=E|_]) -> E; +field_endian_1([_|Fs]) -> field_endian_1(Fs). + +force_big({field_flags,F}) -> + {field_flags,force_big_1(F)}. + +force_big_1([big|_]=Fs) -> Fs; +force_big_1([little|Fs]) -> [big|Fs]; +force_big_1([F|Fs]) -> [F|force_big_1(Fs)]. + +bs_split_int(0, Sz, _, _) when Sz > 64 -> + %% We don't want to split in this case because the + %% string will consist of only zeroes. + no_split; +bs_split_int(-1, Sz, _, _) when Sz > 64 -> + %% We don't want to split in this case because the + %% string will consist of only 255 bytes. + no_split; +bs_split_int(N, Sz, Fail, Acc) -> + FirstByteSz = case Sz rem 8 of + 0 -> 8; + Rem -> Rem + end, + bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc). + +bs_split_int_1(-1, _, Sz, Fail, Acc) when Sz > 64 -> + I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, + [{integer,Sz},{integer,-1}]}, + [I|Acc]; +bs_split_int_1(0, _, Sz, Fail, Acc) when Sz > 64 -> + I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, + [{integer,Sz},{integer,0}]}, + [I|Acc]; +bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 -> + Mask = (1 bsl ByteSz) - 1, + I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}}, + [{integer,ByteSz},{integer,N band Mask}]}, + bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]); +bs_split_int_1(_, _, _, _, Acc) -> Acc. + +%%% +%%% Optimization of bit syntax matching: get rid +%%% of redundant bs_restore2/2 instructions across select_val +%%% instructions, as well as a few other simple peep-hole +%%% optimizations. +%%% + +bsm_opt(Is0, Lc0) -> + {Is1,D0,Lc} = bsm_scan(Is0, [], Lc0, []), + Is2 = case D0 of + [] -> + %% No bit syntax matching in this function. + Is1; + [_|_] -> + %% Optimize the bit syntax matching. + D = gb_trees:from_orddict(orddict:from_list(D0)), + bsm_reroute(Is1, D, none, []) + end, + Is = beam_clean:bs_clean_saves(Is2), + {bsm_opt_2(Is, []),Lc}. + +bsm_scan([{label,L}=Lbl,{bs_restore2,_,Save}=R|Is], D0, Lc, Acc0) -> + D = [{{L,Save},Lc}|D0], + Acc = [{label,Lc},R,Lbl|Acc0], + bsm_scan(Is, D, Lc+1, Acc); +bsm_scan([I|Is], D, Lc, Acc) -> + bsm_scan(Is, D, Lc, [I|Acc]); +bsm_scan([], D, Lc, Acc) -> + {reverse(Acc),D,Lc}. + +bsm_reroute([{bs_save2,Reg,Save}=I|Is], D, _, Acc) -> + bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); +bsm_reroute([{bs_restore2,Reg,Save}=I|Is], D, _, Acc) -> + bsm_reroute(Is, D, {Reg,Save}, [I|Acc]); +bsm_reroute([{label,_}=I|Is], D, S, Acc) -> + bsm_reroute(Is, D, S, [I|Acc]); +bsm_reroute([{select,select_val,Reg,F0,Lbls0}|Is], D, {_,Save}=S, Acc0) -> + [F|Lbls] = bsm_subst_labels([F0|Lbls0], Save, D), + Acc = [{select,select_val,Reg,F,Lbls}|Acc0], + bsm_reroute(Is, D, S, Acc); +bsm_reroute([{test,TestOp,F0,TestArgs}=I|Is], D, {_,Save}=S, Acc0) -> + F = bsm_subst_label(F0, Save, D), + Acc = [{test,TestOp,F,TestArgs}|Acc0], + case bsm_not_bs_test(I) of + true -> + %% The test instruction will not update the bit offset for + %% the binary being matched. Therefore the save position + %% can be kept. + bsm_reroute(Is, D, S, Acc); + false -> + %% The test instruction might update the bit offset. Kill + %% our remembered Save position. + bsm_reroute(Is, D, none, Acc) + end; +bsm_reroute([{test,TestOp,F0,Live,TestArgs,Dst}|Is], D, {_,Save}, Acc0) -> + F = bsm_subst_label(F0, Save, D), + Acc = [{test,TestOp,F,Live,TestArgs,Dst}|Acc0], + %% The test instruction will update the bit offset. Kill our + %% remembered Save position. + bsm_reroute(Is, D, none, Acc); +bsm_reroute([{block,[{set,[],[],{alloc,_,_}}]}=Bl, + {bs_context_to_binary,_}=I|Is], D, S, Acc) -> + %% To help further bit syntax optimizations. + bsm_reroute([I,Bl|Is], D, S, Acc); +bsm_reroute([I|Is], D, _, Acc) -> + bsm_reroute(Is, D, none, [I|Acc]); +bsm_reroute([], _, _, Acc) -> reverse(Acc). + +bsm_opt_2([{test,bs_test_tail2,F,[Ctx,Bits]}|Is], + [{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]}|Acc]) -> + bsm_opt_2(Is, [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|Acc]); +bsm_opt_2([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,_]}|Is], + [{test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,Flags]}|Acc]) -> + bsm_opt_2(Is, [{test,bs_skip_bits2,F, + [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]); +bsm_opt_2([I|Is], Acc) -> + bsm_opt_2(Is, [I|Acc]); +bsm_opt_2([], Acc) -> reverse(Acc). + +%% bsm_not_bs_test({test,Name,_,Operands}) -> true|false. +%% Test whether is the test is a "safe", i.e. does not move the +%% bit offset for a binary. +%% +%% 'true' means that the test is safe, 'false' that we don't know or +%% that the test moves the offset (e.g. bs_get_integer2). + +bsm_not_bs_test({test,bs_test_tail2,_,[_,_]}) -> true; +bsm_not_bs_test(Test) -> beam_utils:is_pure_test(Test). + +bsm_subst_labels(Fs, Save, D) -> + bsm_subst_labels_1(Fs, Save, D, []). + +bsm_subst_labels_1([F|Fs], Save, D, Acc) -> + bsm_subst_labels_1(Fs, Save, D, [bsm_subst_label(F, Save, D)|Acc]); +bsm_subst_labels_1([], _, _, Acc) -> + reverse(Acc). + +bsm_subst_label({f,Lbl0}=F, Save, D) -> + case gb_trees:lookup({Lbl0,Save}, D) of + {value,Lbl} -> {f,Lbl}; + none -> F + end; +bsm_subst_label(Other, _, _) -> Other. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 605f5b8fd5..a2a23a2b90 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -679,6 +679,8 @@ asm_passes() -> {iff,dblk,{listing,"block"}}, {unless,no_except,{pass,beam_except}}, {iff,dexcept,{listing,"except"}}, + {unless,no_bs_opt,{pass,beam_bs}}, + {iff,dbs,{listing,"bs"}}, {unless,no_bopt,{pass,beam_bool}}, {iff,dbool,{listing,"bool"}}, {unless,no_topt,{pass,beam_type}}, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index 62ea9cee80..a2b2a1d277 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -25,6 +25,7 @@ beam_asm, beam_block, beam_bool, + beam_bs, beam_bsm, beam_clean, beam_dead, diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index cbdd9ce8cd..806cb58bab 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -330,6 +330,8 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> do_listing(Simple, TargetDir, dlife, ".life"), do_listing(Simple, TargetDir, dcg, ".codegen"), do_listing(Simple, TargetDir, dblk, ".block"), + do_listing(Simple, TargetDir, dexcept, ".except"), + do_listing(Simple, TargetDir, dbs, ".bs"), do_listing(Simple, TargetDir, dbool, ".bool"), do_listing(Simple, TargetDir, dtype, ".type"), do_listing(Simple, TargetDir, ddead, ".dead"), diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index 3582e055c8..b88abaf62d 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -208,6 +208,10 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, ?line expect_error(fun() -> beam_block:module(BlockInput, []) end), + %% beam_bs + BsInput = BlockInput, + expect_error(fun() -> beam_bs:module(BsInput, []) end), + %% beam_type TypeInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, -- cgit v1.2.3 From 58a0c1c6c7efdb1f1250edec1b5fcd5eb72e99b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 22 Sep 2015 06:14:36 +0200 Subject: beam_dead: Optimize select_val instructions In a select_val instruction, values associated with a label which is the same as the failure label can be removed. We already do this optimization in beam_clean, but it is better do this sort of optimization before the beam_jump pass. Also rewrite a select_val instruction with a single value to is_eq_exact instruction followed by a jump instruction. --- lib/compiler/src/beam_dead.erl | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index 0cb5040177..fcd108bd89 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -239,10 +239,18 @@ backward([{test,is_eq_exact,Fail,[Dst,{integer,Arity}]}=I| backward([{label,Lbl}=L|Is], D, Acc) -> backward(Is, beam_utils:index_label(Lbl, Acc, D), [L|Acc]); backward([{select,select_val,Reg,{f,Fail0},List0}|Is], D, Acc) -> - List = shortcut_select_list(List0, Reg, D, []), + List1 = shortcut_select_list(List0, Reg, D, []), Fail1 = shortcut_label(Fail0, D), Fail = shortcut_bs_test(Fail1, Is, D), + List = prune_redundant(List1, Fail), case List of + [] -> + Jump = {jump,{f,Fail}}, + backward([Jump|Is], D, Acc); + [V,F] -> + Test = {test,is_eq_exact,{f,Fail},[Reg,V]}, + Jump = {jump,F}, + backward([Jump,Test|Is], D, Acc); [{atom,B1},F,{atom,B2},F] when B1 =:= not B2 -> Test = {test,is_boolean,{f,Fail},[Reg]}, Jump = {jump,F}, @@ -307,6 +315,16 @@ backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) -> %% An is_atom test before an is_boolean test (with the %% same failure label) is redundant. backward(Is, D, Acc); + {{test,is_atom,Fail,[R]}, + [{test,is_eq_exact,Fail,[R,{atom,_}]}|_]} -> + %% An is_atom test before a comparison with an atom (with + %% the same failure label) is redundant. + backward(Is, D, Acc); + {{test,is_integer,Fail,[R]}, + [{test,is_eq_exact,Fail,[R,{integer,_}]}|_]} -> + %% An is_integer test before a comparison with an integer + %% (with the same failure label) is redundant. + backward(Is, D, Acc); {{test,_,_,_},_} -> %% Still a test instruction. Done. backward(Is, D, [I|Acc]); @@ -366,6 +384,12 @@ shortcut_label(To0, D) -> shortcut_select_label(To, Reg, Lit, D) -> shortcut_rel_op(To, is_ne_exact, [Reg,Lit], D). +prune_redundant([_,{f,Fail}|T], Fail) -> + prune_redundant(T, Fail); +prune_redundant([V,F|T], Fail) -> + [V,F|prune_redundant(T, Fail)]; +prune_redundant([], _) -> []. + %% Replace a comparison operator with a test instruction and a jump. %% For example, if we have this code: %% -- cgit v1.2.3 From 105c5b0071056dc062797e58772e098d2a3a4627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 22 Sep 2015 10:40:06 +0200 Subject: beam_dead: Improve optimization of literal binary matching When the bit syntax is used to match a single binary literal, the bit syntax instructions will be replaced with a comparison to a binary literal. The only problem is that the bs_context_to_binary instruction will not be eliminated. Example: f(<<"string">>) -> ok. This function would be translated to: {function, f, 1, 2}. {label,1}. {line,...}. {func_info,...}. {label,2}. {test,is_eq_exact,{f,3},[{x,0},{literal,<<"string">>}]}. {move,{atom,ok},{x,0}}. return. {label,3}. {bs_context_to_binary,{x,0}}. {jump,{f,1}}. The bs_context_to_binary instruction serves no useful purpose, since {x,0} can never be a match context. Eliminating the instruction, the resulting code will be: {function, f, 1, 2}. {label,1}. {line,...}. {func_info,...}. {label,2}. {test,is_eq_exact,{f,1},[{x,0},{literal,<<"string">>}]}. {move,{atom,ok},{x,0}}. return. --- lib/compiler/src/beam_dead.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index fcd108bd89..11129c39bc 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -272,14 +272,17 @@ backward([{jump,{f,To}}=J|[{bif,Op,_,Ops,Reg}|Is]=Is0], D, Acc) -> catch throw:not_possible -> backward(Is0, D, [J|Acc]) end; -backward([{test,bs_start_match2,F,_,[R,_],Ctxt}=I|Is], D, +backward([{test,bs_start_match2,F,Live,[R,_]=Args,Ctxt}|Is], D, [{test,bs_match_string,F,[Ctxt,Bs]}, {test,bs_test_tail2,F,[Ctxt,0]}|Acc0]=Acc) -> + {f,To0} = F, + To = shortcut_bs_start_match(To0, R, D), case beam_utils:is_killed(Ctxt, Acc0, D) of true -> - Eq = {test,is_eq_exact,F,[R,{literal,Bs}]}, + Eq = {test,is_eq_exact,{f,To},[R,{literal,Bs}]}, backward(Is, D, [Eq|Acc0]); false -> + I = {test,bs_start_match2,{f,To},Live,Args,Ctxt}, backward(Is, D, [I|Acc]) end; backward([{test,bs_start_match2,{f,To0},Live,[Src|_]=Info,Dst}|Is], D, Acc) -> -- cgit v1.2.3 From c60b4d8ae7d6481bd02782f561fd4d9f626ea6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 23 Sep 2015 10:35:52 +0200 Subject: beam_type: Fix forgotten change of internal representation 30cc5c90 changed the internal representation of catch and try...catch, but beam_type was not updated in one place. --- lib/compiler/src/beam_type.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index 40d67d1670..6b5cf667ba 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -311,7 +311,7 @@ flt_need_heap_2({set,_,_,{get_tuple_element,_}}, H, Fl) -> {[],H,Fl}; flt_need_heap_2({set,_,_,get_list}, H, Fl) -> {[],H,Fl}; -flt_need_heap_2({set,_,_,{'catch',_}}, H, Fl) -> +flt_need_heap_2({set,_,_,{try_catch,_,_}}, H, Fl) -> {[],H,Fl}; %% All other instructions should cause the insertion of an allocation %% instruction if needed. -- cgit v1.2.3 From ae125a3bc62c2165a9db028e12aa6e9f90c7d9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 24 Sep 2015 14:46:16 +0200 Subject: beam_type: Remove unused clause The clause cannot possibly match, because there will always be a {bif,...} clause that will match before reaching the fclearerror instruction. --- lib/compiler/src/beam_type.erl | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index 6b5cf667ba..bb91bbcc0a 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -618,7 +618,6 @@ checkerror(Is) -> checkerror_1(Is, Is). checkerror_1([{set,[],[],fcheckerror}|_], OrigIs) -> OrigIs; -checkerror_1([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs; checkerror_1([{set,_,_,{bif,fadd,_}}|_], OrigIs) -> checkerror_2(OrigIs); checkerror_1([{set,_,_,{bif,fsub,_}}|_], OrigIs) -> checkerror_2(OrigIs); checkerror_1([{set,_,_,{bif,fmul,_}}|_], OrigIs) -> checkerror_2(OrigIs); -- cgit v1.2.3 From c0c5943c3a2646a3383d974c2a1afcff8c5d16d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 23 Sep 2015 07:23:15 +0200 Subject: beam_type: Improve optimization by keeping track of integers The ASN.1 compiler often generates code similar to: f(<<0:1,...>>) -> ...; f(<<1:1,...>>) -> .... Internally that will be rewritten to (conceptually): f(<>) -> case B of 0 -> case Tail of ... end; 1 -> case Tail of ... end; _ -> error(case_clause) end. Since B comes from a bit field of one bit, we know that the only possible values are 0 and 1. Therefore the error clause can be eliminated like this: f(<>) -> case B of 0 -> case Tail of ... end; _ -> case Tail of ... end end. Similarly, we can also a deduce the range for an integer from a 'band' operation with a literal integer. While we are at it, also add a test case to improve the coverage. --- lib/compiler/src/beam_type.erl | 121 ++++++++++++++++++++++++++++++---- lib/compiler/test/Makefile | 2 + lib/compiler/test/beam_type_SUITE.erl | 87 ++++++++++++++++++++++++ lib/compiler/test/bs_match_SUITE.erl | 18 ++++- 4 files changed, 215 insertions(+), 13 deletions(-) create mode 100644 lib/compiler/test/beam_type_SUITE.erl (limited to 'lib') diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index bb91bbcc0a..17ce7082f6 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -23,7 +23,8 @@ -export([module/2]). --import(lists, [foldl/3,reverse/1,filter/2]). +-import(lists, [filter/2,foldl/3,keyfind/3,member/2, + reverse/1,reverse/2,sort/1]). module({Mod,Exp,Attr,Fs0,Lc}, _Opts) -> Fs = [function(F) || F <- Fs0], @@ -94,6 +95,12 @@ simplify_basic_1([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Acc) - end; simplify_basic_1([{set,_,_,{try_catch,_,_}}=I|Is], _Ts, Acc) -> simplify_basic_1(Is, tdb_new(), [I|Acc]); +simplify_basic_1([{test,is_integer,_,[R]}=I|Is], Ts, Acc) -> + case tdb_find(R, Ts) of + integer -> simplify_basic_1(Is, Ts, Acc); + {integer,_} -> simplify_basic_1(Is, Ts, Acc); + _ -> simplify_basic_1(Is, Ts, [I|Acc]) + end; simplify_basic_1([{test,is_tuple,_,[R]}=I|Is], Ts, Acc) -> case tdb_find(R, Ts) of {tuple,_,_} -> simplify_basic_1(Is, Ts, Acc); @@ -137,6 +144,14 @@ simplify_basic_1([{test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I|Is], Ts0 Ts = update(I, Ts0), simplify_basic_1(Is, Ts, [I|Acc]) end; +simplify_basic_1([{select,select_val,Reg,_,_}=I0|Is], Ts, Acc) -> + I = case tdb_find(Reg, Ts) of + {integer,Range} -> + simplify_select_val_int(I0, Range); + _ -> + I0 + end, + simplify_basic_1(Is, tdb_new(), [I|Acc]); simplify_basic_1([I|Is], Ts0, Acc) -> Ts = update(I, Ts0), simplify_basic_1(Is, Ts, [I|Acc]); @@ -144,6 +159,23 @@ simplify_basic_1([], Ts, Acc) -> Is = reverse(Acc), {Is,Ts}. +simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) -> + Vs = sort([V || {integer,V} <- L0]), + case eq_ranges(Vs, Min, Max) of + false -> I; + true -> simplify_select_val_1(L0, {integer,Max}, R, []) + end. + +simplify_select_val_1([Val,F|T], Val, R, Acc) -> + L = reverse(Acc, T), + {select,select_val,R,F,L}; +simplify_select_val_1([V,F|T], Val, R, Acc) -> + simplify_select_val_1(T, Val, R, [F,V|Acc]). + +eq_ranges([H], H, H) -> true; +eq_ranges([H|T], H, Max) -> eq_ranges(T, H+1, Max); +eq_ranges(_, _, _) -> false. + %% simplify_float([Instruction], TypeDatabase) -> %% {[Instruction],TypeDatabase'} | not_possible %% Simplify floating point operations in blocks. @@ -390,6 +422,13 @@ update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) -> true -> tdb_update([{D,float}], Ts0); false -> Ts0 end; +update({set,[D],[S1,S2],{alloc,_,{gc_bif,'band',{f,0}}}}, Ts) -> + case keyfind(integer, 1, [S1,S2]) of + {integer,N} -> + update_band(N, D, Ts); + false -> + tdb_update([{D,integer}], Ts) + end; update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts0) -> %% Make sure we reject non-numeric literals. case possibly_numeric(S1) andalso possibly_numeric(S2) of @@ -397,15 +436,17 @@ update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts0) -> false -> Ts0 end; update({set,[D],[S1,S2],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts0) -> - case arith_op(Op) of - no -> - tdb_update([{D,kill}], Ts0); - {yes,_} -> + case op_type(Op) of + integer -> + tdb_update([{D,integer}], Ts0); + {float,_} -> case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of {float,_} -> tdb_update([{D,float}], Ts0); {_,float} -> tdb_update([{D,float}], Ts0); {_,_} -> tdb_update([{D,kill}], Ts0) - end + end; + unknown -> + tdb_update([{D,kill}], Ts0) end; update({set,[],_Src,_Op}, Ts0) -> Ts0; update({set,[D],_Src,_Op}, Ts0) -> @@ -437,6 +478,8 @@ update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) -> tdb_update([{Src,{tuple,Arity,[Tag]}}], Ts); update({test,_Test,_Fail,_Other}, Ts) -> Ts; +update({test,bs_get_integer2,_,_,Args,Dst}, Ts) -> + tdb_update([{Dst,get_bs_integer_type(Args)}], Ts); update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) -> case is_math_bif(Math, Ar) of true -> tdb_update([{{x,0},float}], Ts); @@ -453,10 +496,43 @@ update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts); update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts); update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts); update({line,_}, Ts) -> Ts; +update({bs_save2,_,_}, Ts) -> Ts; +update({bs_restore2,_,_}, Ts) -> Ts; %% The instruction is unknown. Kill all information. update(_I, _Ts) -> tdb_new(). +update_band(N, Reg, Ts) -> + Type = update_band_1(N, 0), + tdb_update([{Reg,Type}], Ts). + +update_band_1(N, Bits) when Bits < 64 -> + case 1 bsl Bits of + P when P =:= N + 1 -> + {integer,{0,N}}; + P when P > N + 1 -> + integer; + _ -> + update_band_1(N, Bits+1) + end; +update_band_1(_, _) -> + %% Negative or large positive number. Give up. + integer. + +get_bs_integer_type([_,{integer,N},U,{field_flags,Fl}]) + when N*U < 64 -> + NumBits = N*U, + case member(unsigned, Fl) of + true -> + {integer,{0,(1 bsl NumBits)-1}}; + false -> + %% Signed integer. Don't bother. + integer + end; +get_bs_integer_type(_) -> + %% Avoid creating ranges with a huge upper limit. + integer. + is_math_bif(cos, 1) -> true; is_math_bif(cosh, 1) -> true; is_math_bif(sin, 1) -> true; @@ -545,11 +621,22 @@ load_reg(V, Ts, Rs0, Is0) -> {Rs,Is} end. -arith_op('+') -> {yes,fadd}; -arith_op('-') -> {yes,fsub}; -arith_op('*') -> {yes,fmul}; -arith_op('/') -> {yes,fdiv}; -arith_op(_) -> no. +arith_op(Op) -> + case op_type(Op) of + {float,Instr} -> {yes,Instr}; + _ -> no + end. + +op_type('+') -> {float,fadd}; +op_type('-') -> {float,fsub}; +op_type('*') -> {float,fmul}; +%% '/' and 'band' are specially handled. +op_type('bor') -> integer; +op_type('bxor') -> integer; +op_type('bsl') -> integer; +op_type('bsr') -> integer; +op_type('div') -> integer; +op_type(_) -> unknown. flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) -> Acc = flush_all(Rs, Is0, Acc0), @@ -639,6 +726,9 @@ checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs]. %%% of the first element). %%% %%% 'float' means that the register contains a float. +%%% +%%% 'integer' or {integer,{Min,Max}} that the register contains an +%%% integer. %% tdb_new() -> EmptyDataBase %% Creates a new, empty type database. @@ -728,10 +818,19 @@ merge_type_info({tuple,Sz1,[]}, {tuple,_Sz2,First}=Tuple2) -> merge_type_info({tuple,Sz1,First}, Tuple2); merge_type_info({tuple,_Sz1,First}=Tuple1, {tuple,Sz2,_}) -> merge_type_info(Tuple1, {tuple,Sz2,First}); +merge_type_info(integer, {integer,_}=Int) -> + Int; +merge_type_info({integer,_}=Int, integer) -> + Int; +merge_type_info({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) -> + {integer,{max(Min1, Min2),min(Max1, Max2)}}; merge_type_info(NewType, _) -> verify_type(NewType), NewType. +verify_type(integer) -> ok; +verify_type({integer,{Min,Max}}) + when is_integer(Min), is_integer(Max) -> ok; verify_type(map) -> ok; verify_type(nonempty_list) -> ok; verify_type({tuple,Sz,[]}) when is_integer(Sz) -> ok; diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index 6553d10077..0cd8618730 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -11,6 +11,7 @@ MODULES= \ beam_validator_SUITE \ beam_disasm_SUITE \ beam_except_SUITE \ + beam_type_SUITE \ beam_utils_SUITE \ bs_bincomp_SUITE \ bs_bit_binaries_SUITE \ @@ -43,6 +44,7 @@ NO_OPT= \ andor \ apply \ beam_except \ + beam_type \ beam_utils \ bs_construct \ bs_match \ diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl new file mode 100644 index 0000000000..8d99d76180 --- /dev/null +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -0,0 +1,87 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(beam_type_SUITE). + +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + integers/1,coverage/1]). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + test_lib:recompile(?MODULE), + [{group,p}]. + +groups() -> + [{p,[parallel], + [integers, + coverage + ]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +integers(_Config) -> + a = do_integers_1(2#11000), + b = do_integers_1(2#11001), + + a = do_integers_2(<<0:1>>), + {'EXIT',{{case_clause,-1},_}} = (catch do_integers_2(<<1:1>>)), + + ok. + +do_integers_1(B0) -> + B = B0 band 1, + case B band 15 of + 0 -> a; + 1 -> b + end. + +do_integers_2(Bin) -> + <> = Bin, + case B of + 0 -> a; + 1 -> b + end. + +coverage(_Config) -> + {'EXIT',{badarith,_}} = (catch id(1) bsl 0.5), + {'EXIT',{badarith,_}} = (catch id(2.0) bsl 2), + {'EXIT',{badarith,_}} = (catch a + 0.5), + {'EXIT',{badarith,_}} = (catch 2.0 * b), + + {'EXIT',{badarith,_}} = (catch id(42.0) / (1 bsl 2000)), + + id(id(42) band 387439739874298734983787934283479243879), + id(-1 band id(13)), + + ok. + +id(I) -> + I. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 6e138b0a43..a19b152bc5 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -36,7 +36,7 @@ match_string/1,zero_width/1,bad_size/1,haystack/1, cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1, no_partition/1,calling_a_binary/1,binary_in_map/1, - match_string_opt/1]). + match_string_opt/1,select_on_integer/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -62,7 +62,7 @@ groups() -> otp_7498,match_string,zero_width,bad_size,haystack, cover_beam_bool,matched_out_size,follow_fail_branch, no_partition,calling_a_binary,binary_in_map, - match_string_opt]}]. + match_string_opt,select_on_integer]}]. init_per_suite(Config) -> @@ -1225,6 +1225,20 @@ match_string_opt(Config) when is_list(Config) -> do_match_string_opt({<<1>>,{v,V}}=T) -> {x,V,T}. +select_on_integer(Config) when is_list(Config) -> + 42 = do_select_on_integer(<<42>>), + <<"abc">> = do_select_on_integer(<<128,"abc">>), + + {'EXIT',_} = (catch do_select_on_integer(<<0:1>>)), + {'EXIT',_} = (catch do_select_on_integer(<<1:1>>)), + {'EXIT',_} = (catch do_select_on_integer(<<0:1,0:15>>)), + ok. + +%% The ASN.1 compiler frequently generates code like this. +do_select_on_integer(<<0:1,I:7>>) -> + I; +do_select_on_integer(<<1:1,_:7,Bin/binary>>) -> + Bin. check(F, R) -> R = F(). -- cgit v1.2.3 From b66193afc3fe85072da4631c52c5ccec136caa05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 23 Sep 2015 12:30:16 +0200 Subject: beam_type: Improve optimizations by keeping track of booleans There is an optimization in beam_block to simplify a select_val on a known boolean value. We can implement this optimization in a cleaner way in beam_type and it will also be applicable in more situations. (When I added the optimization to beam_type without removing the optimization from beam_block, the optimization was applied 66 times.) --- lib/compiler/src/beam_block.erl | 34 ---------------------------------- lib/compiler/src/beam_type.erl | 28 ++++++++++++++++++++++++++++ lib/compiler/test/beam_type_SUITE.erl | 15 +++++++++++++-- 3 files changed, 41 insertions(+), 36 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 741fdbb973..10dbaf462c 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -58,33 +58,6 @@ blockify(Is) -> blockify([{loop_rec,{f,Fail},{x,0}},{loop_rec_end,_Lbl},{label,Fail}|Is], Acc) -> %% Useless instruction sequence. blockify(Is, Acc); -blockify([{test,is_atom,{f,Fail},[Reg]}=I| - [{select,select_val,Reg,{f,Fail}, - [{atom,false},{f,_}=BrFalse, - {atom,true}=AtomTrue,{f,_}=BrTrue]}|Is]=Is0], - [{block,Bl}|_]=Acc) -> - case is_last_bool(Bl, Reg) of - false -> - blockify(Is0, [I|Acc]); - true -> - %% The last instruction is a boolean operator/guard BIF that can't fail. - %% We can convert the three-way branch to a two-way branch (eliminating - %% the reference to the failure label). - blockify(Is, [{jump,BrTrue}, - {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc]) - end; -blockify([{test,is_atom,{f,Fail},[Reg]}=I| - [{select,select_val,Reg,{f,Fail}, - [{atom,true}=AtomTrue,{f,_}=BrTrue, - {atom,false},{f,_}=BrFalse]}|Is]=Is0], - [{block,Bl}|_]=Acc) -> - case is_last_bool(Bl, Reg) of - false -> - blockify(Is0, [I|Acc]); - true -> - blockify(Is, [{jump,BrTrue}, - {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc]) - end; blockify([I|Is0]=IsAll, Acc) -> case collect(I) of error -> blockify(Is0, [I|Acc]); @@ -94,13 +67,6 @@ blockify([I|Is0]=IsAll, Acc) -> end; blockify([], Acc) -> reverse(Acc). -is_last_bool([{set,[Reg],As,{bif,N,_}}], Reg) -> - Ar = length(As), - erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar) - orelse erl_internal:bool_op(N, Ar); -is_last_bool([_|Is], Reg) -> is_last_bool(Is, Reg); -is_last_bool([], _) -> false. - collect_block(Is) -> collect_block(Is, []). diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index 17ce7082f6..4b45c28623 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -95,6 +95,11 @@ simplify_basic_1([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Acc) - end; simplify_basic_1([{set,_,_,{try_catch,_,_}}=I|Is], _Ts, Acc) -> simplify_basic_1(Is, tdb_new(), [I|Acc]); +simplify_basic_1([{test,is_atom,_,[R]}=I|Is], Ts, Acc) -> + case tdb_find(R, Ts) of + boolean -> simplify_basic_1(Is, Ts, Acc); + _ -> simplify_basic_1(Is, Ts, [I|Acc]) + end; simplify_basic_1([{test,is_integer,_,[R]}=I|Is], Ts, Acc) -> case tdb_find(R, Ts) of integer -> simplify_basic_1(Is, Ts, Acc); @@ -148,6 +153,8 @@ simplify_basic_1([{select,select_val,Reg,_,_}=I0|Is], Ts, Acc) -> I = case tdb_find(Reg, Ts) of {integer,Range} -> simplify_select_val_int(I0, Range); + boolean -> + simplify_select_val_bool(I0); _ -> I0 end, @@ -166,6 +173,15 @@ simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) -> true -> simplify_select_val_1(L0, {integer,Max}, R, []) end. +simplify_select_val_bool({select,select_val,R,_,L}=I) -> + Vs = sort([V || {atom,V} <- L]), + case Vs of + [false,true] -> + simplify_select_val_1(L, {atom,false}, R, []); + _ -> + I + end. + simplify_select_val_1([Val,F|T], Val, R, Acc) -> L = reverse(Acc, T), {select,select_val,R,F,L}; @@ -414,6 +430,17 @@ update({set,[D],[{integer,I},Reg],{bif,element,_}}, Ts0) -> tdb_update([{Reg,{tuple,I,[]}},{D,kill}], Ts0); update({set,[D],[_Index,Reg],{bif,element,_}}, Ts0) -> tdb_update([{Reg,{tuple,0,[]}},{D,kill}], Ts0); +update({set,[D],Args,{bif,N,_}}, Ts0) -> + Ar = length(Args), + BoolOp = erl_internal:new_type_test(N, Ar) orelse + erl_internal:comp_op(N, Ar) orelse + erl_internal:bool_op(N, Ar), + case BoolOp of + true -> + tdb_update([{D,boolean}], Ts0); + false -> + tdb_update([{D,kill}], Ts0) + end; update({set,[D],[S],{get_tuple_element,0}}, Ts) -> tdb_update([{D,{tuple_element,S,0}}], Ts); update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) -> @@ -828,6 +855,7 @@ merge_type_info(NewType, _) -> verify_type(NewType), NewType. +verify_type(boolean) -> ok; verify_type(integer) -> ok; verify_type({integer,{Min,Max}}) when is_integer(Min), is_integer(Max) -> ok; diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 8d99d76180..8d5c0190ed 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -21,7 +21,7 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, - integers/1,coverage/1]). + integers/1,coverage/1,booleans/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -32,7 +32,8 @@ all() -> groups() -> [{p,[parallel], [integers, - coverage + coverage, + booleans ]}]. init_per_suite(Config) -> @@ -83,5 +84,15 @@ coverage(_Config) -> ok. +booleans(_Config) -> + {'EXIT',{{case_clause,_},_}} = (catch do_booleans(42)), + ok. + +do_booleans(B) -> + case is_integer(B) of + yes -> yes; + no -> no + end. + id(I) -> I. -- cgit v1.2.3 From 464ca2f8049feec6453d2d9a327f996662978e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 25 Sep 2015 07:06:38 +0200 Subject: Move select_val optimization from beam_clean to beam_peep There is an optimization in beam_clean that will remove values having the same label as the failure label in a select_val instruction. Conceptually, this optimization is in the wrong module since ideally beam_clean is a mandatory pass that should not do optimizations. Furthermore, this part of beam_clean is called three times (from beam_dead, beam_peep, and as a compiler pass from the 'compile' module), but it only does useful one of the times it is called. Therefore, move this optimization to the beam_peep pass. The same optimization is done in beam_dead, but unfortunately it misses some opportunities for optimization because the code sharing optimization in beam_jump (share/1) runs after beam_dead. It would be more satisfactory to have this optimization only in beam_dead, but it turned out not to be trivial. If we try to run beam_jump:share/1 before beam_dead, some optimizations will no longer work in beam_dead because fallthroughs have been eliminated. For the moment, the possible solutions to this problem seems to involve more work and more complicated code than the gain from eliminating the duplicated optimization would gain. --- lib/compiler/src/beam_clean.erl | 20 ++++---------------- lib/compiler/src/beam_peep.erl | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl index 7d66985791..d9108c383d 100644 --- a/lib/compiler/src/beam_clean.erl +++ b/lib/compiler/src/beam_clean.erl @@ -190,17 +190,11 @@ replace([{test,Test,{f,Lbl},Ops}|Is], Acc, D) -> replace([{test,Test,{f,Lbl},Live,Ops,Dst}|Is], Acc, D) -> replace(Is, [{test,Test,{f,label(Lbl, D)},Live,Ops,Dst}|Acc], D); replace([{select,I,R,{f,Fail0},Vls0}|Is], Acc, D) -> - Vls1 = map(fun ({f,L}) -> {f,label(L, D)}; - (Other) -> Other end, Vls0), + Vls = map(fun ({f,L}) -> {f,label(L, D)}; + (Other) -> Other + end, Vls0), Fail = label(Fail0, D), - case redundant_values(Vls1, Fail, []) of - [] -> - %% Oops, no choices left. The loader will not accept that. - %% Convert to a plain jump. - replace(Is, [{jump,{f,Fail}}|Acc], D); - Vls -> - replace(Is, [{select,I,R,{f,Fail},Vls}|Acc], D) - end; + replace(Is, [{select,I,R,{f,Fail},Vls}|Acc], D); replace([{'try',R,{f,Lbl}}|Is], Acc, D) -> replace(Is, [{'try',R,{f,label(Lbl, D)}}|Acc], D); replace([{'catch',R,{f,Lbl}}|Is], Acc, D) -> @@ -241,12 +235,6 @@ label(Old, D) -> {value,Val} -> Val; none -> throw({error,{undefined_label,Old}}) end. - -redundant_values([_,{f,Fail}|Vls], Fail, Acc) -> - redundant_values(Vls, Fail, Acc); -redundant_values([Val,Lbl|Vls], Fail, Acc) -> - redundant_values(Vls, Fail, [Lbl,Val|Acc]); -redundant_values([], _, Acc) -> reverse(Acc). %%% %%% Final fixup of bs_start_match2/5,bs_save2/bs_restore2 instructions for diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl index 75be86b83f..0c1abfe6a0 100644 --- a/lib/compiler/src/beam_peep.erl +++ b/lib/compiler/src/beam_peep.erl @@ -83,6 +83,16 @@ peep([{gc_bif,_,_,_,_,Dst}=I|Is], SeenTests0, Acc) -> %% Kill all remembered tests that depend on the destination register. SeenTests = kill_seen(Dst, SeenTests0), peep(Is, SeenTests, [I|Acc]); +peep([{select,Op,R,F,Vls0}|Is], _, Acc) -> + case prune_redundant_values(Vls0, F) of + [] -> + %% No values left. Must convert to plain jump. + I = {jump,F}, + peep(Is, gb_sets:empty(), [I|Acc]); + [_|_]=Vls -> + I = {select,Op,R,F,Vls}, + peep(Is, gb_sets:empty(), [I|Acc]) + end; peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) -> case beam_utils:is_pure_test(I) of false -> @@ -127,3 +137,9 @@ kill_seen_1([{_,Ops}=Test|T], Dst) -> false -> [Test|kill_seen_1(T, Dst)] end; kill_seen_1([], _) -> []. + +prune_redundant_values([_Val,F|Vls], F) -> + prune_redundant_values(Vls, F); +prune_redundant_values([Val,Lbl|Vls], F) -> + [Val,Lbl|prune_redundant_values(Vls, F)]; +prune_redundant_values([], _) -> []. -- cgit v1.2.3 From 67b38c36eaa9b6d3edb80df75637f0e8cd1823f3 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 28 Sep 2015 15:37:41 +0200 Subject: Speed up receive of many small packages When data from the netconf server was split into many ssh packages, the netconf client performed really bad. This is now improved. --- lib/common_test/src/ct_netconfc.erl | 22 ++++++++++++-------- .../ct_netconfc_SUITE_data/netconfc1_SUITE.erl | 24 ++++++++++++++++------ lib/common_test/test/ct_netconfc_SUITE_data/ns.erl | 15 ++++++++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 0de7bf03af..799d795ed0 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -1366,11 +1366,18 @@ to_xml_doc(Simple) -> %%% Parse and handle received XML data handle_data(NewData,#state{connection=Connection,buff=Buff0} = State0) -> log(Connection,recv,NewData), - Data = append_wo_initial_nl(Buff0,NewData), - case binary:split(Data,[?END_TAG],[]) of + {Start,AddSz} = + case byte_size(Buff0) of + BSz when BSz<5 -> {0,BSz}; + BSz -> {BSz-5,5} + end, + Length = byte_size(NewData) + AddSz, + Data = <>, + case binary:split(Data,?END_TAG,[{scope,{Start,Length}}]) of [_NoEndTagFound] -> {noreply, State0#state{buff=Data}}; - [FirstMsg,Buff1] -> + [FirstMsg0,Buff1] -> + FirstMsg = remove_initial_nl(FirstMsg0), SaxArgs = [{event_fun,fun sax_event/3}, {event_state,[]}], case xmerl_sax_parser:stream(FirstMsg, SaxArgs) of {ok, Simple, _Thrash} -> @@ -1392,11 +1399,10 @@ handle_data(NewData,#state{connection=Connection,buff=Buff0} = State0) -> %% xml does not accept a leading nl and some netconf server add a nl after %% each ?END_TAG, ignore them -append_wo_initial_nl(<<>>,NewData) -> NewData; -append_wo_initial_nl(<<"\n", Data/binary>>, NewData) -> - append_wo_initial_nl(Data, NewData); -append_wo_initial_nl(Data, NewData) -> - <>. +remove_initial_nl(<<"\n", Data/binary>>) -> + remove_initial_nl(Data); +remove_initial_nl(Data) -> + Data. handle_error(Reason, State) -> Pending1 = case State#state.pending of diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl index 64ebfbc463..5f84634f74 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -36,7 +36,8 @@ -compile(export_all). suite() -> - [{ct_hooks, [{cth_conn_log, + [{timetrap,?default_timeout}, + {ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,html}, %will be overwritten by config {hosts,[my_named_connection,netconf1]}] }] @@ -72,6 +73,7 @@ all() -> invalid_opt, timeout_close_session, get, + get_a_lot, timeout_get, get_xpath, get_config, @@ -112,12 +114,9 @@ end_per_group(_GroupName, Config) -> init_per_testcase(_Case, Config) -> ets:delete_all_objects(ns_tab), - Dog = test_server:timetrap(?default_timeout), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. init_per_suite(Config) -> @@ -351,6 +350,19 @@ get(Config) -> ?ok = ct_netconfc:close_session(Client), ok. +get_a_lot(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Descr = lists:append(lists:duplicate(1000,"Description of myserver! ")), + Server = {server,[{xmlns,"myns"}],[{name,[],["myserver"]}, + {description,[],[Descr]}]}, + Data = lists:duplicate(100,Server), + ?NS:expect_reply('get',{fragmented,{data,Data}}), + {ok,Data} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + timeout_get(Config) -> DataDir = ?config(data_dir,Config), {ok,Client} = open_success(DataDir), diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl index 8c30383343..3fc99e5486 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl @@ -277,6 +277,18 @@ hupp_kill(State = #session{connection = ConnRef}) -> send({CM,Ch},Data) -> ssh_connection:send(CM, Ch, Data). +%%% Split into many small parts and send to client +send_frag({CM,Ch},Data) -> + Sz = rand:uniform(2000), + case Data of + <> -> + ssh_connection:send(CM, Ch, Chunk), + send_frag({CM,Ch},Rest); + Chunk -> + ssh_connection:send(CM, Ch, Chunk) + end. + + %%% Kill ssh connection kill({CM,_Ch}) -> ssh:close(CM). @@ -424,6 +436,9 @@ do(_, undefined) -> reply(_,undefined) -> ?dbg("no reply~n",[]), ok; +reply(ConnRef,{fragmented,Reply}) -> + ?dbg("Reply fragmented: ~p~n",[Reply]), + send_frag(ConnRef,make_msg(Reply)); reply(ConnRef,Reply) -> ?dbg("Reply: ~p~n",[Reply]), send(ConnRef, make_msg(Reply)). -- cgit v1.2.3 From 4cf832f1ad163f5b25dd8a6f2d314c169c23c82f Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 28 Sep 2015 16:45:05 +0200 Subject: Don't log headings without content The netconf server collects data until an XML tag is completed before pretty printing received data. Each time data is logged, a heading like the following is printed: = CT_NETCONFC ==== 28-Sep-2015::16:43:46,842 =================================== = Client <0.194.0> <----- {"127.0.0.1",2060} =================================== This commit removes printing of this header if there is no data to be printed below - i.e. if the XML tag is not yet complete and we are waiting for more data. --- lib/common_test/src/ct_conn_log_h.erl | 11 ++++++++--- lib/common_test/src/ct_netconfc.erl | 25 +++++++++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl index 2dd4fdac05..5eb67853d9 100644 --- a/lib/common_test/src/ct_conn_log_h.erl +++ b/lib/common_test/src/ct_conn_log_h.erl @@ -109,9 +109,14 @@ write_report(_Time,#conn_log{header=false,module=ConnMod}=Info,Data,GL,State) -> write_report(Time,#conn_log{module=ConnMod}=Info,Data,GL,State) -> {LogType,Fd} = get_log(Info,GL,State), - io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time), - format_title(LogType,Info), - format_data(ConnMod,LogType,Data)]). + case format_data(ConnMod,LogType,Data) of + [] -> + ok; + FormattedData -> + io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time), + format_title(LogType,Info), + FormattedData]) + end. write_error(Time,#conn_log{module=ConnMod}=Info,Report,GL,State) -> case get_log(Info,GL,State) of diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 799d795ed0..ed805e4d14 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -1768,9 +1768,14 @@ format_data(How,Data) -> do_format_data(raw,Data) -> io_lib:format("~n~ts~n",[hide_password(Data)]); do_format_data(pretty,Data) -> - io_lib:format("~n~ts~n",[indent(Data)]); + maybe_io_lib_format(indent(Data)); do_format_data(html,Data) -> - io_lib:format("~n~ts~n",[html_format(Data)]). + maybe_io_lib_format(html_format(Data)). + +maybe_io_lib_format(<<>>) -> + []; +maybe_io_lib_format(String) -> + io_lib:format("~n~ts~n",[String]). %%%----------------------------------------------------------------- %%% Hide password elements from XML data @@ -1809,13 +1814,21 @@ indent1(" Line++indent1(Rest2,Indent2); indent1(" %% Stop tag - {Line,Rest2,Indent2} = indent_line1(Rest1,Indent1,[$/,$<]), - "\n"++Line++indent1(Rest2,Indent2); + case indent_line1(Rest1,Indent1,[$/,$<]) of + {[],[],_} -> + []; + {Line,Rest2,Indent2} -> + "\n"++Line++indent1(Rest2,Indent2) + end; indent1("<"++Rest1,Indent1) -> %% Start- or empty tag put(tag,get_tag(Rest1)), - {Line,Rest2,Indent2} = indent_line(Rest1,Indent1,[$<]), - "\n"++Line++indent1(Rest2,Indent2); + case indent_line(Rest1,Indent1,[$<]) of + {[],[],_} -> + []; + {Line,Rest2,Indent2} -> + "\n"++Line++indent1(Rest2,Indent2) + end; indent1([H|T],Indent) -> [H|indent1(T,Indent)]; indent1([],_Indent) -> -- cgit v1.2.3 From 543231f01e46df527ad2a7ad74942836a05b5a00 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 29 Sep 2015 11:43:30 +0200 Subject: Allow internal spaces in IFEQ test in generated Makefile When generating Makefile from Makefile.src, ts_lib:get_arg/4 earlier removed all spaces in the extracted argument. The code was probably meant for removing leading and trailing spaces only, and is now corrected to do so. --- lib/test_server/src/ts_lib.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/test_server/src/ts_lib.erl b/lib/test_server/src/ts_lib.erl index 61bd55a654..7c3f450194 100644 --- a/lib/test_server/src/ts_lib.erl +++ b/lib/test_server/src/ts_lib.erl @@ -250,12 +250,10 @@ do_test(Rest, Vars, Test) -> {Result,Comment,Rest2}. %% extract an argument -get_arg([$ |Rest], Vars, Stop, Acc) -> - get_arg(Rest, Vars, Stop, Acc); get_arg([$(|Rest], Vars, Stop, _) -> get_arg(Rest, Vars, Stop, []); get_arg([Stop|Rest], Vars, Stop, Acc) -> - Arg = lists:reverse(Acc), + Arg = string:strip(lists:reverse(Acc)), Subst = subst(Arg, Vars), {Subst,Rest}; get_arg([C|Rest], Vars, Stop, Acc) -> -- cgit v1.2.3 From ec1284c810cdc176b93d7316e78dc9c6aa84a504 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 30 Sep 2015 15:28:59 +0200 Subject: inets: Add behaviour httpd_custom_api Add this now as 18 allows optional callback specs --- lib/inets/src/http_server/Makefile | 12 ++++++++-- lib/inets/src/http_server/httpd_custom.erl | 8 ++++++- lib/inets/src/http_server/httpd_custom_api.erl | 31 ++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 lib/inets/src/http_server/httpd_custom_api.erl (limited to 'lib') diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile index b09877550d..b9f2290289 100644 --- a/lib/inets/src/http_server/Makefile +++ b/lib/inets/src/http_server/Makefile @@ -40,6 +40,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # ---------------------------------------------------- # Target Specs # ---------------------------------------------------- + +BEHAVIOUR_MODULES= \ + httpd_custom_api + MODULES = \ httpd \ httpd_acceptor \ @@ -86,10 +90,13 @@ MODULES = \ HRL_FILES = httpd.hrl httpd_internal.hrl mod_auth.hrl -ERL_FILES = $(MODULES:%=%.erl) +ERL_FILES = $(MODULES:%=%.erl)\ + $(BEHAVIOUR_MODULES:%=%.erl) TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR)) + INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"' @@ -109,11 +116,12 @@ ERL_COMPILE_FLAGS += \ # ---------------------------------------------------- # Targets # ---------------------------------------------------- +$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES) debug opt: $(TARGET_FILES) clean: - rm -f $(TARGET_FILES) + rm -f $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) rm -f core docs: diff --git a/lib/inets/src/http_server/httpd_custom.erl b/lib/inets/src/http_server/httpd_custom.erl index a1fe058bd1..b62fc25fac 100644 --- a/lib/inets/src/http_server/httpd_custom.erl +++ b/lib/inets/src/http_server/httpd_custom.erl @@ -23,7 +23,13 @@ -export([response_header/1, request_header/1]). -export([customize_headers/3]). --include_lib("inets/src/inets_app/inets_internal.hrl"). +-include("../inets_app/inets_internal.hrl"). + +-behaviour(httpd_custom_api). + +%%-------------------------------------------------------------------- +%% Behavior API ----------------------------------- +%%-------------------------------------------------------------------- response_header(Header) -> {true, httpify(Header)}. diff --git a/lib/inets/src/http_server/httpd_custom_api.erl b/lib/inets/src/http_server/httpd_custom_api.erl new file mode 100644 index 0000000000..282f3a6ee6 --- /dev/null +++ b/lib/inets/src/http_server/httpd_custom_api.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% +-module(httpd_custom_api). + +-callback response_default_headers() -> + [{Key::string(), Value::string()}]. +-callback response_header({Key::string(), Value::string()}) -> + {true, {Key::string(), Value::string()}} | false. +-callback request_header({Key::string(), Value::string()}) -> + {true, {Key::string(), Value::string()}} | false. + +-optional_callbacks([response_default_headers/0, response_header/1, + request_header/1]). -- cgit v1.2.3 From fe48161dbc7511220b0b91b06c26d2beba7a6586 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 30 Sep 2015 10:24:35 +0200 Subject: inets: Add new customize function response_default_headers This enables the user to provide default HTTP header values for headers that should always be sent. Note that these values may override built in defaults. --- lib/inets/doc/src/httpd_custom_api.xml | 14 ++++++++++ lib/inets/src/http_server/httpd_custom.erl | 23 +++++++++++++++-- lib/inets/src/http_server/httpd_response.erl | 21 ++++++++++----- lib/inets/test/httpd_SUITE.erl | 38 +++++++++++++++++++++++----- lib/inets/test/httpd_test_lib.erl | 4 +-- 5 files changed, 82 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/httpd_custom_api.xml b/lib/inets/doc/src/httpd_custom_api.xml index 23417900fa..d2e5441895 100644 --- a/lib/inets/doc/src/httpd_custom_api.xml +++ b/lib/inets/doc/src/httpd_custom_api.xml @@ -33,6 +33,20 @@ + + response_default_headers() -> [Header] + Provide default headers for the HTTP servers responses. + + Header = {HeaderName :: string(), HeaderValue::string()} + string:to_lower/1 will be performed on the HeaderName + + +

Provide default headers for the HTTP servers responses. Note that this + option may override built-in defaults. +

+
+
+ response_header({HeaderName, HeaderValue}) -> {true, Header} | false Filter and possible alter HTTP response headers. diff --git a/lib/inets/src/http_server/httpd_custom.erl b/lib/inets/src/http_server/httpd_custom.erl index b62fc25fac..2b9701ef75 100644 --- a/lib/inets/src/http_server/httpd_custom.erl +++ b/lib/inets/src/http_server/httpd_custom.erl @@ -20,8 +20,8 @@ %% -module(httpd_custom). --export([response_header/1, request_header/1]). --export([customize_headers/3]). +-export([response_header/1, request_header/1, response_default_headers/0]). +-export([customize_headers/3, response_default_headers/1]). -include("../inets_app/inets_internal.hrl"). @@ -35,7 +35,12 @@ response_header(Header) -> {true, httpify(Header)}. request_header(Header) -> {true, Header}. +response_default_headers() -> + []. +%%-------------------------------------------------------------------- +%% Internal API ----------------------------------- +%%-------------------------------------------------------------------- customize_headers(?MODULE, Function, Arg) -> ?MODULE:Function(Arg); customize_headers(Module, Function, Arg) -> @@ -49,6 +54,20 @@ customize_headers(Module, Function, Arg) -> ?MODULE:Function(Arg) end. +response_default_headers(?MODULE) -> + response_default_headers(); +response_default_headers(Module) -> + try Module:response_default_headers() of + Defaults -> + [{http_util:to_lower(Key), Value} || {Key, Value} <- Defaults, + is_list(Key), is_list(Value)] + catch + _:_ -> + ?MODULE:response_default_headers() + end. +%%-------------------------------------------------------------------- +%% Internal functions ----------------------------------- +%%-------------------------------------------------------------------- httpify({Key0, Value}) -> %% make sure first letter is capital (defacto standard) Words1 = string:tokens(Key0, "-"), diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl index 7e73da7060..71243f525a 100644 --- a/lib/inets/src/http_server/httpd_response.erl +++ b/lib/inets/src/http_server/httpd_response.erl @@ -287,14 +287,21 @@ create_header(ConfigDb, KeyValueTupleHeaders) -> Date = httpd_util:rfc1123_date(), ContentType = "text/html", Server = server(ConfigDb), - Headers0 = add_default_headers([{"date", Date}, - {"content-type", ContentType} - | if Server=="" -> []; - true -> [{"server", Server}] - end - ], - KeyValueTupleHeaders), CustomizeCB = httpd_util:lookup(ConfigDb, customize, httpd_custom), + + CustomDefaults = httpd_custom:response_default_headers(CustomizeCB), + SystemDefaultes = ([{"date", Date}, + {"content-type", ContentType} + | if Server=="" -> []; + true -> [{"server", Server}] + end + ]), + + %% System defaults not present in custom defaults will be added + %% to defaults + Defaults = add_default_headers(SystemDefaultes, CustomDefaults), + + Headers0 = add_default_headers(Defaults, KeyValueTupleHeaders), lists:filtermap(fun(H) -> httpd_custom:customize_headers(CustomizeCB, response_header, H) end, diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index a6236f828a..b50d31a5c1 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -97,7 +97,7 @@ groups() -> {https_reload, [], [{group, reload}]}, {http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]}, {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, - {custom, [], [customize]}, + {custom, [], [customize, add_default]}, {reload, [], [non_disturbing_reconfiger_dies, disturbing_reconfiger_dies, non_disturbing_1_1, @@ -1003,10 +1003,23 @@ customize(Config) when is_list(Config) -> {no_header, "Server"}, {version, Version}]). -response_header({"server", _}) -> - false; -response_header(Header) -> - {true, Header}. +add_default() -> + [{doc, "Test adding default header with custom callback"}]. + +add_default(Config) when is_list(Config) -> + Version = "HTTP/1.1", + Host = ?config(host, Config), + Type = ?config(type, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + http_request("GET /index.html ", Version, Host), + [{statuscode, 200}, + {header, "Content-Type", "text/html"}, + {header, "Date", "Override-date"}, + {header, "X-Frame-Options"}, + {version, Version}]). %%------------------------------------------------------------------------- max_header() -> @@ -1425,9 +1438,9 @@ server_config(http_limit, Config) -> %% Make sure option checking code is run {max_content_length, 100000002}] ++ server_config(http, Config); server_config(http_custom, Config) -> - [{custom, ?MODULE}] ++ server_config(http, Config); + [{customize, ?MODULE}] ++ server_config(http, Config); server_config(https_custom, Config) -> - [{custom, ?MODULE}] ++ server_config(https, Config); + [{customize, ?MODULE}] ++ server_config(https, Config); server_config(https_limit, Config) -> [{max_clients, 1}] ++ server_config(https, Config); server_config(http_basic_auth, Config) -> @@ -2030,3 +2043,14 @@ typestr(ip_comm) -> "tcp"; typestr(_) -> "ssl". + +response_header({"server", _}) -> + false; +response_header(Header) -> + {true, Header}. + +response_default_headers() -> + [%% Add new header + {"X-Frame-Options", "SAMEORIGIN"}, + %% Override built-in default + {"Date", "Override-date"}]. diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl index cb2e86c81e..a5b836f651 100644 --- a/lib/inets/test/httpd_test_lib.erl +++ b/lib/inets/test/httpd_test_lib.erl @@ -294,9 +294,9 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) -> {value, {LowerHeaderField, Value}} -> ok; false -> - ct:fail({wrong_header_field_value, LowerHeaderField, Header}); + ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value}); _ -> - ct:fail({wrong_header_field_value, LowerHeaderField, Header}) + ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value}) end, do_validate(Header, Rest, N, P); do_validate(Header,[{no_header, HeaderField}|Rest],N,P) -> -- cgit v1.2.3 From 6b5aa5c7b807b0963fcfc31c2c4ee22249f75428 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 1 Oct 2015 12:16:45 +0200 Subject: ssh: document ecdh and hmac-sha2-512 --- lib/ssh/doc/src/ssh.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index cf5e8f1aff..6c95fa3399 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -41,10 +41,10 @@ For application dependencies see ssh(6) Supported SSH version is 2.0. Supported public key algorithms: ssh-rsa and ssh-dss. - Supported MAC algorithms: hmac-sha2-256 and hmac-sha1. + Supported MAC algorithms: hmac-sha2-512, hmac-sha2-256 and hmac-sha1. Supported encryption algorithms: aes128-ctr, aes128-cb and 3des-cbc. - Supported key exchange algorithms: diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256. - Supported compression algorithms: none, zlib, zlib@openssh.com, + Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256. + Supported compression algorithms: none, zlib Supports unicode filenames if the emulator and the underlaying OS support it. See section DESCRIPTION in the file manual page in kernel -- cgit v1.2.3 From 0bc3430528ff489ba9ae1cc93a3d6e729f0c0c7a Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 1 Oct 2015 16:48:02 +0200 Subject: inets: Use ?MODULE_STRING instead of ?MODULE as argument should be a string --- lib/inets/src/http_server/mod_auth_server.erl | 2 +- lib/inets/src/http_server/mod_security_server.erl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_server/mod_auth_server.erl b/lib/inets/src/http_server/mod_auth_server.erl index 3685c2e617..7d1e1a3431 100644 --- a/lib/inets/src/http_server/mod_auth_server.erl +++ b/lib/inets/src/http_server/mod_auth_server.erl @@ -316,7 +316,7 @@ lookup(Db, Key) -> make_name(Addr, Port, Profile) -> - httpd_util:make_name(?MODULE, Addr, Port, Profile). + httpd_util:make_name(?MODULE_STRING, Addr, Port, Profile). call(Name, Req) -> diff --git a/lib/inets/src/http_server/mod_security_server.erl b/lib/inets/src/http_server/mod_security_server.erl index 81561493a0..f9281b0fdc 100644 --- a/lib/inets/src/http_server/mod_security_server.erl +++ b/lib/inets/src/http_server/mod_security_server.erl @@ -523,10 +523,10 @@ unblock_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, CBModule) -> ets:match_delete(ETS, {blocked_user, {User, Addr, Port, Profile, Dir, '_'}}). make_name(Addr,Port, Profile) -> - httpd_util:make_name(?MODULE,Addr,Port, Profile). + httpd_util:make_name(?MODULE_STRING, Addr, Port, Profile). make_name(Addr,Port, Profile, Num) -> - httpd_util:make_name(?MODULE,Addr,Port, + httpd_util:make_name(?MODULE_STRING, Addr,Port, atom_to_list(Profile) ++ "__" ++ integer_to_list(Num)). auth_fail_event(Mod,Addr,Port,Dir,User,Passwd) -> -- cgit v1.2.3 From c31a42fe95c06d4f491424a42fc7c90f94fe5801 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 1 Oct 2015 16:58:29 +0200 Subject: ssh: document dh-gex default values --- lib/ssh/doc/src/ssh.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index cf5e8f1aff..d57bcb96eb 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -243,7 +243,7 @@ kex is implicit but public_key is set explicitly.

Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group. - See RFC 4419 for the function of thoose. The default value is {512, 1024, 4096}. + See RFC 4419 for the function of thoose. The default value is {1024, 6144, 8192}.

-- cgit v1.2.3 From c4bd1ea37ac2ace2bed1b82962248efb3e780b5d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 1 Oct 2015 17:51:21 +0200 Subject: inets: Prepare for release --- lib/inets/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index a6aeedfe12..480caeca4b 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 6.0.1 +INETS_VSN = 6.0.2 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" -- cgit v1.2.3 From bb63fc9bca7233d0f9e8b9abe96c66eac5bdc933 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 2 Oct 2015 08:49:04 +0200 Subject: ssh: 4.1->4.2 --- lib/ssh/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index b305eedcdc..d828bccd29 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.1 +SSH_VSN = 4.2 APP_VSN = "ssh-$(SSH_VSN)" -- cgit v1.2.3 From b02221cf90bf7021b382e4bdfb61b08cccc2c99d Mon Sep 17 00:00:00 2001 From: Roger Lipscombe Date: Mon, 7 Sep 2015 19:53:43 +0100 Subject: Pass 'raw' options through In Erlang R16B03-1, I've been passing raw options to ssl:listen as follows, and it's been working fine: % The constants are defined elsewhere. LOpts = [{raw, ?IPPROTO_TCP, ?TCP_MAXSEG, <>} | ...], {ok, LSocket} = ssl:listen(0, LOpts) In Erlang 17.3, this fails with {option_not_a_key_value_tuple,{raw,6,2,<<64,2,0,0>>}} I originally reported this in http://erlang.org/pipermail/erlang-questions/2014-October/081226.html I need to pass this particular raw option to ssl:listen, because it needs to be applied when the socket is first opened -- between inet:open and prim_inet:listen -- it cannot be applied later by setopts. This means that it needs to be done by inet_tcp:listen/2 -- well, actually by inet:open/8, but... Otherwise it's racey -- a client could connect between prim_inet:listen and the setopts call. The MSS option is advertised in the SYN,ACK packet, and can't be changed later. --- lib/ssl/src/ssl.erl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 9f2af73204..19b091df59 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -1169,6 +1169,8 @@ assert_proplist([]) -> assert_proplist([{Key,_} | Rest]) when is_atom(Key) -> assert_proplist(Rest); %% Handle exceptions +assert_proplist([{raw,_,_,_} | Rest]) -> + assert_proplist(Rest); assert_proplist([inet | Rest]) -> assert_proplist(Rest); assert_proplist([inet6 | Rest]) -> -- cgit v1.2.3 From d22396bce11debcbb6d8826468bd111ac0efbf7b Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Fri, 2 Oct 2015 13:47:41 +0200 Subject: mnesia: Fix mnesia:restore/2 which caused a disk_log leak Introduced a leak of disk_log processes in the rewrite to try-catch. --- lib/mnesia/src/mnesia_bup.erl | 14 ++++++++++---- lib/mnesia/test/mnesia_evil_backup.erl | 10 +++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl index 0e653f2bc4..1f150ae38b 100644 --- a/lib/mnesia/src/mnesia_bup.erl +++ b/lib/mnesia/src/mnesia_bup.erl @@ -157,10 +157,11 @@ fallback_to_schema(Fname) -> read_schema(Mod, Opaque) -> R = #restore{bup_module = Mod, bup_data = Opaque}, try read_schema_section(R) of - {_, {_Header, Schema, _}} -> Schema + {R2, {_Header, Schema, _}} -> + close_read(R2), + Schema catch throw:{error,_} = Error -> Error - after close_read(R) end. %% Open backup media and extract schema @@ -173,8 +174,13 @@ read_schema_section(R) -> do_read_schema_section(R) -> R2 = safe_apply(R, open_read, [R#restore.bup_data]), - {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]), - do_read_schema_section(R3, verify_header(RawSchema), []). + try + {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]), + do_read_schema_section(R3, verify_header(RawSchema), []) + catch T:E -> + close_read(R2), + erlang:raise(T,E,erlang:get_stacktrace()) + end. do_read_schema_section(R, {ok, B, C, []}, Acc) -> case safe_apply(R, read, [R#restore.bup_data]) of diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl index 89f2861661..e605fa7926 100644 --- a/lib/mnesia/test/mnesia_evil_backup.erl +++ b/lib/mnesia/test/mnesia_evil_backup.erl @@ -232,7 +232,13 @@ restore(Config, Op) -> Res21 = [{Tab2, N, N+1} || N <- lists:seq(1, 11)], Res31 = [[{Tab3, N, N+1}, {Tab3, N, N+44}] || N <- lists:seq(1, 10)], - + Check = fun() -> + [disk_log:pid2name(X) || + X <- processes(), Data <- [process_info(X, [current_function])], + Data =/= undefined, + element(1, element(2, lists:keyfind(current_function, 1, Data)))=:= disk_log] + end, + Before = Check(), ?match({atomic, [Tab1]}, Restore(File1, [{Op, [Tab1]}, {skip_tables, Tabs -- [Tab1]}])), case Op of @@ -319,6 +325,8 @@ restore(Config, Op) -> end, ?match(ok, file:delete(File1)), ?match(ok, file:delete(File2)), + ?match([], Check() -- Before), + ?verify_mnesia(Nodes, []). -- cgit v1.2.3 From c881813b0643138e9b1c1b1a573645460f14404e Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Fri, 2 Oct 2015 12:44:44 +0200 Subject: Compile without errors for exported variables --- lib/hipe/rtl/Makefile | 2 +- lib/hipe/rtl/hipe_rtl_binary_match.erl | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile index d2517b13fc..1bf52fe312 100644 --- a/lib/hipe/rtl/Makefile +++ b/lib/hipe/rtl/Makefile @@ -75,7 +75,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) include ../native.mk -ERL_COMPILE_FLAGS += +inline +warn_unused_import +warn_exported_vars +ERL_COMPILE_FLAGS += -Werror +inline +warn_unused_import +warn_exported_vars # ---------------------------------------------------- # Targets diff --git a/lib/hipe/rtl/hipe_rtl_binary_match.erl b/lib/hipe/rtl/hipe_rtl_binary_match.erl index 364aab1b6f..37263a951a 100644 --- a/lib/hipe/rtl/hipe_rtl_binary_match.erl +++ b/lib/hipe/rtl/hipe_rtl_binary_match.erl @@ -2,7 +2,7 @@ %%% %%% %CopyrightBegin% %%% -%%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %%% %%% Licensed under the Apache License, Version 2.0 (the "License"); %%% you may not use this file except in compliance with the License. @@ -181,17 +181,20 @@ gen_rtl({bs_get_binary, Size, Flags}, [Dst, NewMs], Args, [hipe_rtl:mk_goto(FalseLblName)]; false -> Unsafe = unsafe(Flags), - case Args of - [Ms] -> - SizeReg = hipe_rtl:mk_new_reg(), - SizeCode = [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))]; - [Ms, BitsVar] -> - {SizeCode, SizeReg} = make_size(Size, BitsVar, FalseLblName) - end, - InCode = get_binary(Dst, Ms, SizeReg, Unsafe, + {OldMs, SizeReg, SizeCode} = + case Args of + [Ms] -> + SzReg = hipe_rtl:mk_new_reg(), + SzCode = [hipe_rtl:mk_move(SzReg, hipe_rtl:mk_imm(Size))], + {Ms, SzReg, SzCode}; + [Ms, BitsVar] -> + {SzCode, SzReg} = make_size(Size, BitsVar, FalseLblName), + {Ms, SzReg, SzCode} + end, + InCode = get_binary(Dst, OldMs, SizeReg, Unsafe, TrueLblName, FalseLblName), [hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE)] ++ - update_ms(NewMs, Ms) ++ SizeCode ++ InCode + update_ms(NewMs, OldMs) ++ SizeCode ++ InCode end; %% ----- bs_get_utf8 ----- gen_rtl(bs_get_utf8, [Dst, NewMs], [Ms], TrueLblName, FalseLblName) -> -- cgit v1.2.3 From 5aea81c495f06d58d72b5d3dba86ed9326b1eb14 Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Fri, 2 Oct 2015 14:50:29 +0200 Subject: Fix matching with huge binaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In certain cases of matching with very big binaries, the HiPE compiler generated code that would fail the match, even in cases that the matching was successful. The problem was more quite noticeable on 32-bit platforms where certain integer quantities would be represented as bignums. Brief summary of changes: * gen_rtl({bs_skip_bits, ...}, ...) could not handle too large constants. Previously the constants were truncated to word size. * hipe_rtl_binary_match:make_size/3 erroneously assumed that the output of first_part/3 would not overflow when multiplied by 8, which is no longer true. To maintain full performance, the overflow test is only performed when BitsVar was a bignum. Thus, the fast path is identical to before. * hipe_rtl_binary_match:set_high/2 was assuming that only bits below bit 27 were ever set in arguments to bs_skip_bits, which is not only false when the arguments are bignums, but also on 64-bit platforms. The commit includes a test taken from the bs_match_bin_SUITE. Most of the credit for finding these HiPE compiler errors and for creating appropriate fixes for them should go to Magnus Lång. --- lib/hipe/rtl/hipe_rtl_binary_match.erl | 81 ++++++++++++++++------- lib/hipe/rtl/hipe_tagscheme.erl | 30 ++++++--- lib/hipe/test/bs_SUITE_data/bs_match.erl | 108 ++++++++++++++++++++++++++++++- 3 files changed, 186 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/hipe/rtl/hipe_rtl_binary_match.erl b/lib/hipe/rtl/hipe_rtl_binary_match.erl index 37263a951a..51213b71d1 100644 --- a/lib/hipe/rtl/hipe_rtl_binary_match.erl +++ b/lib/hipe/rtl/hipe_rtl_binary_match.erl @@ -233,14 +233,26 @@ gen_rtl({bs_skip_bits_all, Unit, _Flags}, Dst, [Ms], skip_bits_all(Unit, Ms, TrueLblName, FalseLblName); %% ----- bs_skip_bits ----- gen_rtl({bs_skip_bits, Bits}, Dst, [Ms|Args], TrueLblName, FalseLblName) -> + MaxValue = (1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE)), opt_update_ms(Dst, Ms) ++ - case Args of - [] -> - skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName); - [Arg] -> - {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName), - InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName), - SizeCode ++ InCode + case Bits < MaxValue of + true -> + case Args of + [] -> + skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName); + [Arg] -> + {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName), + InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName), + SizeCode ++ InCode + end; + false -> % handle overflow case + case Args of + [] -> + [hipe_rtl:mk_goto(FalseLblName)]; + [Arg] -> + [hipe_rtl:mk_branch(Arg, 'eq', hipe_tagscheme:mk_fixnum(0), + TrueLblName, FalseLblName, 0.5)] + end end; %% ----- bs_restore ----- gen_rtl({bs_restore, Slot}, [NewMs], [Ms], TrueLblName, _FalseLblName) -> @@ -1089,23 +1101,47 @@ create_gcsafe_regs(0) -> []. first_part(Var, Register, FalseLblName) -> - [SuccessLbl1, SuccessLbl2] = create_lbls(2), - [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(SuccessLbl1), - FalseLblName, 0.99), - SuccessLbl1, - hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)), - hipe_rtl:label_name(SuccessLbl2), FalseLblName, 0.99), - SuccessLbl2, - hipe_tagscheme:untag_fixnum(Register, Var)]. + [EndLbl] = create_lbls(1), + EndName = hipe_rtl:label_name(EndLbl), + first_part(Var, Register, FalseLblName, EndName, EndName, [EndLbl]). + +first_part(Var, Register, FalseLblName, TrueLblName, BigLblName, Tail) -> + [FixnumLbl, NotFixnumLbl, BignumLbl, SuccessLbl] = create_lbls(4), + [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(FixnumLbl), + hipe_rtl:label_name(NotFixnumLbl), 0.99), + FixnumLbl, + hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)), + hipe_rtl:label_name(SuccessLbl), FalseLblName, + 0.99), + SuccessLbl, + hipe_tagscheme:untag_fixnum(Register, Var), + hipe_rtl:mk_goto(TrueLblName), + NotFixnumLbl, + %% Since binaries are not allowed to be larger than 2^wordsize bits + %% and since bignum digits are words, we know that a bignum with an + %% arity larger than one can't match. + hipe_tagscheme:test_pos_bignum_arity(Var, 1, hipe_rtl:label_name(BignumLbl), + FalseLblName, 0.99), + BignumLbl, + hipe_tagscheme:unsafe_get_one_word_pos_bignum(Register, Var), + hipe_rtl:mk_goto(BigLblName) | Tail]. make_size(1, BitsVar, FalseLblName) -> [DstReg] = create_regs(1), {first_part(BitsVar, DstReg, FalseLblName), DstReg}; make_size(?BYTE_SIZE, BitsVar, FalseLblName) -> [DstReg] = create_regs(1), - Code = - first_part(BitsVar, DstReg, FalseLblName) ++ - [hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))], + [FixnumLbl, BignumLbl] = create_lbls(2), + WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE, + FixnumLblName = hipe_rtl:label_name(FixnumLbl), + Tail = [BignumLbl, + hipe_rtl:mk_branch(DstReg, 'ltu', + hipe_rtl:mk_imm(1 bsl (WordBits - ?BYTE_SHIFT)), + FixnumLblName, FalseLblName, 0.99), + FixnumLbl, + hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))], + Code = first_part(BitsVar, DstReg, FalseLblName, FixnumLblName, + hipe_rtl:label_name(BignumLbl), Tail), {Code, DstReg}; make_size(UnitImm, BitsVar, FalseLblName) -> [DstReg] = create_regs(1), @@ -1154,12 +1190,13 @@ floorlog2(X) -> round(math:log(X)/math:log(2)-0.5). set_high(X) -> - set_high(X, 0). + WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE, + set_high(min(X, WordBits), WordBits, 0). -set_high(0, Y) -> +set_high(0, _, Y) -> Y; -set_high(X, Y) -> - set_high(X-1, Y+(1 bsl (27-X))). +set_high(X, WordBits, Y) -> + set_high(X-1, WordBits, Y+(1 bsl (WordBits-X))). is_illegal_const(Const) -> Const >= 1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE) orelse Const < 0. diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl index 1bb4c3cc5f..d77078acb6 100644 --- a/lib/hipe/rtl/hipe_tagscheme.erl +++ b/lib/hipe/rtl/hipe_tagscheme.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -41,7 +41,8 @@ test_any_pid/4, test_any_port/4, test_ref/4, test_fun/4, test_fun2/5, test_matchstate/4, test_binary/4, test_bitstr/4, test_list/4, test_map/4, - test_integer/4, test_number/4, test_tuple_N/5]). + test_integer/4, test_number/4, test_tuple_N/5, + test_pos_bignum_arity/5]). -export([realtag_fixnum/2, tag_fixnum/2, realuntag_fixnum/2, untag_fixnum/2]). -export([test_two_fixnums/3, test_fixnums/4, unsafe_fixnum_add/3, unsafe_fixnum_sub/3, @@ -53,9 +54,10 @@ -export([unsafe_closure_element/3]). -export([mk_fun_header/0, tag_fun/2]). -export([unsafe_untag_float/2, unsafe_tag_float/2]). --export([mk_sub_binary/6,mk_sub_binary/7]). +-export([mk_sub_binary/6, mk_sub_binary/7]). -export([unsafe_mk_big/3, unsafe_load_float/3]). --export([bignum_sizeneed/1,bignum_sizeneed_code/2, get_one_word_pos_bignum/3]). +-export([bignum_sizeneed/1, bignum_sizeneed_code/2, get_one_word_pos_bignum/3, + unsafe_get_one_word_pos_bignum/2]). -export([test_subbinary/3, test_heap_binary/3]). -export([create_heap_binary/3, create_refc_binary/3, create_refc_binary/4]). -export([create_matchstate/6, convert_matchstate/1, compare_matchstate/4]). @@ -349,6 +351,15 @@ test_pos_bignum(X, TrueLab, FalseLab, Pred) -> mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG, TrueLab, FalseLab, Pred)]. +test_pos_bignum_arity(X, Arity, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + HeaderImm = hipe_rtl:mk_imm(mk_header(Arity, ?TAG_HEADER_POS_BIG)), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + hipe_rtl:mk_branch(Tmp, 'eq', HeaderImm, TrueLab, FalseLab, Pred)]. + test_matchstate(X, TrueLab, FalseLab, Pred) -> Tmp = hipe_rtl:mk_new_reg_gcsafe(), HalfTrueLab = hipe_rtl:mk_new_label(), @@ -963,13 +974,16 @@ get_one_word_pos_bignum(USize, Size, Fail) -> Header = hipe_rtl:mk_new_reg(), HalfLbl = hipe_rtl:mk_new_label(), HalfLblName = hipe_rtl:label_name(HalfLbl), - WordSize = hipe_rtl_arch:word_size(), PosHead = hipe_rtl:mk_imm(mk_header(1, ?TAG_HEADER_POS_BIG)), [get_header(Header, Size), hipe_rtl:mk_branch(Header, eq, PosHead, HalfLblName, Fail), - HalfLbl, - hipe_rtl:mk_load(USize, Size, hipe_rtl:mk_imm(1*WordSize - -?TAG_PRIMARY_BOXED))]. + HalfLbl | + unsafe_get_one_word_pos_bignum(USize, Size)]. + +unsafe_get_one_word_pos_bignum(USize, Size) -> + WordSize = hipe_rtl_arch:word_size(), + Imm = hipe_rtl:mk_imm(1*WordSize-?TAG_PRIMARY_BOXED), + [hipe_rtl:mk_load(USize, Size, Imm)]. -spec bignum_sizeneed(non_neg_integer()) -> non_neg_integer(). diff --git a/lib/hipe/test/bs_SUITE_data/bs_match.erl b/lib/hipe/test/bs_SUITE_data/bs_match.erl index 7bc93a316b..b241ea8d35 100644 --- a/lib/hipe/test/bs_SUITE_data/bs_match.erl +++ b/lib/hipe/test/bs_SUITE_data/bs_match.erl @@ -1,8 +1,8 @@ %%% -*- erlang-indent-level: 2 -*- %%%------------------------------------------------------------------- %%% File : bs_match.erl -%%% Author : Per Gustafsson -%%% Purpose : Performs simple matching and construction of binaries +%%% Authors : Per Gustafsson , Kostis Sagonas +%%% Purpose : Tests matching and construction of binaries %%% TODO : Add binary and float tests %%% Created : 20 Feb 2004 %%%------------------------------------------------------------------- @@ -13,7 +13,7 @@ test() -> Funs = [fun test_aligned/0, fun test_unaligned/0, fun test_zero_tail/0, fun test_integer_matching/0, - fun test_writable_bin/0], + fun test_writable_bin/0, fun test_match_huge_bin/0], lists:foreach(fun (F) -> ok = F() end, Funs). %%------------------------------------------------------------------- @@ -175,6 +175,9 @@ test_dynamic_integer_matching(N) -> <<12:N/integer-little, 0:S>> = <<12:N/integer-little, 0:S>>, ok. +%%------------------------------------------------------------------- +%% Test writable bin -- added by Sverker Eriksson + test_writable_bin() -> test_writable_bin(<<>>, 0), ok. @@ -185,3 +188,102 @@ test_writable_bin(Bin0, N) when N < 128 -> Bin1 = <>, <<_/utf8, _/binary>> = Bin1, test_writable_bin(Bin1, N+1). + +%%------------------------------------------------------------------- +%% Test matching with a huge bin -- taken from bs_match_bin_SUITE + +test_match_huge_bin() -> + Bin = <<0:(1 bsl 27),13:8>>, + skip_huge_bin_1(1 bsl 27, Bin), + 16777216 = match_huge_bin_1(1 bsl 27, Bin), + %% Test overflowing the size of a binary field. + nomatch = overflow_huge_bin_skip_32(Bin), + nomatch = overflow_huge_bin_32(Bin), + nomatch = overflow_huge_bin_skip_64(Bin), + nomatch = overflow_huge_bin_64(Bin), + %% Size in variable + ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)), + ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)), + ok. + +overflow_huge_bin(Bin, [Sz0|Sizes]) -> + Sz = id(1 bsl Sz0), + case Bin of + <<_:Sz/binary-unit:8,0,_/binary>> -> + {error,Sz}; + _ -> + case Bin of + <> -> + {error,Sz,size(NewBin)}; + _ -> + overflow_huge_bin(Bin, Sizes) + end + end; +overflow_huge_bin(_, []) -> ok. + +overflow_huge_bin_unit128(Bin, [Sz0|Sizes]) -> + Sz = id(1 bsl Sz0), + case Bin of + <<_:Sz/binary-unit:128,0,_/binary>> -> + {error,Sz}; + _ -> + case Bin of + <> -> + {error,Sz,size(NewBin)}; + _ -> + overflow_huge_bin_unit128(Bin, Sizes) + end + end; +overflow_huge_bin_unit128(_, []) -> ok. + +skip_huge_bin_1(I, Bin) -> + <<_:I/binary-unit:1,13>> = Bin, + ok. + +match_huge_bin_1(I, Bin) -> + case Bin of + <> -> size(Val); + _ -> nomatch + end. + +overflow_huge_bin_skip_32(<<_:4294967296/binary,0,_/binary>>) -> 1; % 1 bsl 32 +overflow_huge_bin_skip_32(<<_:33554432/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 25 +overflow_huge_bin_skip_32(<<_:67108864/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 26 +overflow_huge_bin_skip_32(<<_:134217728/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 27 +overflow_huge_bin_skip_32(<<_:268435456/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 28 +overflow_huge_bin_skip_32(<<_:536870912/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 29 +overflow_huge_bin_skip_32(<<_:1073741824/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 30 +overflow_huge_bin_skip_32(<<_:2147483648/binary-unit:8,0,_/binary>>) -> 8; % 1 bsl 31 +overflow_huge_bin_skip_32(_) -> nomatch. + +overflow_huge_bin_32(<>) -> {1,Bin}; % 1 bsl 32 +overflow_huge_bin_32(<>) -> {2,Bin}; % 1 bsl 25 +overflow_huge_bin_32(<>) -> {3,Bin}; % 1 bsl 26 +overflow_huge_bin_32(<>) -> {4,Bin}; % 1 bsl 27 +overflow_huge_bin_32(<>) -> {5,Bin}; % 1 bsl 28 +overflow_huge_bin_32(<>) -> {6,Bin}; % 1 bsl 29 +overflow_huge_bin_32(<>) -> {7,Bin}; % 1 bsl 30 +overflow_huge_bin_32(<>) -> {8,Bin}; % 1 bsl 31 +overflow_huge_bin_32(_) -> nomatch. + +overflow_huge_bin_skip_64(<<_:18446744073709551616/binary,0,_/binary>>) -> 1; % 1 bsl 64 +overflow_huge_bin_skip_64(<<_:144115188075855872/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 57 +overflow_huge_bin_skip_64(<<_:288230376151711744/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 58 +overflow_huge_bin_skip_64(<<_:576460752303423488/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 59 +overflow_huge_bin_skip_64(<<_:1152921504606846976/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 60 +overflow_huge_bin_skip_64(<<_:2305843009213693952/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 61 +overflow_huge_bin_skip_64(<<_:4611686018427387904/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 62 +overflow_huge_bin_skip_64(<<_:9223372036854775808/binary-unit:8,_/binary>>) -> 8; % 1 bsl 63 +overflow_huge_bin_skip_64(_) -> nomatch. + +overflow_huge_bin_64(<>) -> {1,Bin}; % 1 bsl 64 +overflow_huge_bin_64(<>) -> {2,Bin}; % 1 bsl 57 +overflow_huge_bin_64(<>) -> {3,Bin}; % 1 bsl 58 +overflow_huge_bin_64(<>) -> {4,Bin}; % 1 bsl 59 +overflow_huge_bin_64(<>) -> {5,Bin}; % 1 bsl 60 +overflow_huge_bin_64(<>) -> {6,Bin}; % 1 bsl 61 +overflow_huge_bin_64(<>) -> {7,Bin}; % 1 bsl 62 +overflow_huge_bin_64(<>) -> {8,Bin}; % 1 bsl 63 +overflow_huge_bin_64(_) -> nomatch. + +id(I) -> I. -- cgit v1.2.3 From e0cdb50524c260ca96b67e9b1000d320bd8903c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Mon, 5 Oct 2015 11:01:01 +0200 Subject: Prepare release --- lib/inets/doc/src/notes.xml | 33 ++++++++++++++++++++++++++++++++- lib/mnesia/doc/src/notes.xml | 18 +++++++++++++++++- lib/mnesia/vsn.mk | 2 +- 3 files changed, 50 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index eb1027b028..ef11fdc10c 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,38 @@ notes.xml -
Inets 6.0.1 +
Inets 6.0.2 + +
Fixed Bugs and Malfunctions + + +

+ Avoid crash in mod_auth_server and mod_security_server + due to using an atom instead of a string when creating a + name.

+

+ Own Id: OTP-13022

+
+
+
+ + +
Improvements and New Features + + +

+ Add function response_default_headers/0 to httpd + customize API, to allow user to specify default values + for HTTP response headers.

+

+ Own Id: OTP-13013

+
+
+
+ +
+ +
Inets 6.0.1
Fixed Bugs and Malfunctions diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 3b35a9879b..8650e03a60 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,23 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.

-
Mnesia 4.13.1 +
Mnesia 4.13.2 + +
Fixed Bugs and Malfunctions + + +

+ Fixed a process and file descriptor leak in + mnesia:restore/2.

+

+ Own Id: OTP-13025 Aux Id: seq12957

+
+
+
+ +
+ +
Mnesia 4.13.1
Fixed Bugs and Malfunctions diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index e27045e16f..0fe5b5db8b 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.13.1 +MNESIA_VSN = 4.13.2 -- cgit v1.2.3 From 76bb9f0e9a0b36ea7c9720c2bf90f6b52a4eabf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 5 Oct 2015 06:43:12 +0200 Subject: beam_reorder: Eliminate compiler crash c288ab87 added beam_reorder to move get_tuple_element instructions. Compiling code such as the following would crash the compiler: alloc(_U1, _U2, R) -> V = R#alloc.version, Res = id(V), _ = id(0), Res. The crash would occur because the following two instructions: {get_tuple_element,{x,2},1,{x,1}}. {allocate_zero,1,2}. were swapped and rewritten to: {allocate_zero,1,1}. {get_tuple_element,{x,2},1,{x,1}}. That transformation is not safe because the allocate_zero instruction would kill {x,2}, which is the register that is holding the reference to the tuple. Only do the transformation when the tuple reference is in an x register with a lower number than the destination register. --- lib/compiler/src/beam_reorder.erl | 21 ++++++---- lib/compiler/test/Makefile | 2 + lib/compiler/test/beam_reorder_SUITE.erl | 69 ++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 lib/compiler/test/beam_reorder_SUITE.erl (limited to 'lib') diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl index 70adca6b04..41586a7bf2 100644 --- a/lib/compiler/src/beam_reorder.erl +++ b/lib/compiler/src/beam_reorder.erl @@ -110,14 +110,19 @@ reorder_1([{test,_,{f,L},Ss}=I|Is0], D0, end end end; -reorder_1([{allocate_zero,N,Live}|Is], D, - [{get_tuple_element,_,_,{x,X}}=G|Acc]) - when X+1 =:= Live -> - %% Move allocation instruction upwards past get_tuple_element - %% instructions to give more opportunities for moving - %% get_tuple_element instructions. - I = {allocate_zero,N,X}, - reorder_1([I,G|Is], D, Acc); +reorder_1([{allocate_zero,N,Live}=I0|Is], D, + [{get_tuple_element,{x,Tup},_,{x,Dst}}=G|Acc]=Acc0) -> + case Tup < Dst andalso Dst+1 =:= Live of + true -> + %% Move allocation instruction upwards past + %% get_tuple_element instructions to create more + %% opportunities for moving get_tuple_element + %% instructions. + I = {allocate_zero,N,Dst}, + reorder_1([I,G|Is], D, Acc); + false -> + reorder_1(Is, D, [I0|Acc0]) + end; reorder_1([I|Is], D, Acc) -> reorder_1(Is, D, [I|Acc]); reorder_1([], _, Acc) -> reverse(Acc). diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index 0cd8618730..400565100f 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -11,6 +11,7 @@ MODULES= \ beam_validator_SUITE \ beam_disasm_SUITE \ beam_except_SUITE \ + beam_reorder_SUITE \ beam_type_SUITE \ beam_utils_SUITE \ bs_bincomp_SUITE \ @@ -44,6 +45,7 @@ NO_OPT= \ andor \ apply \ beam_except \ + beam_reorder \ beam_type \ beam_utils \ bs_construct \ diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl new file mode 100644 index 0000000000..4b2262f65b --- /dev/null +++ b/lib/compiler/test/beam_reorder_SUITE.erl @@ -0,0 +1,69 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(beam_reorder_SUITE). + +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + alloc/1]). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + test_lib:recompile(?MODULE), + [{group,p}]. + +groups() -> + [{p,[parallel], + [alloc + ]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +-record(alloc, {version}). + +alloc(_Config) -> + {ok,42} = alloc_a(1, 2, #alloc{version=42}), + {a,b,c} = alloc_b(1, 2, #alloc{version={a,b,c}}), + ok. + +alloc_a(_U1, _U2, R) -> + V = R#alloc.version, + Res = id({ok,V}), + _ = id(0), + Res. + +alloc_b(_U1, _U2, R) -> + V = R#alloc.version, + Res = id(V), + _ = id(0), + Res. + +id(I) -> + I. -- cgit v1.2.3 From 6167d34cb448f4842474ac05e79bd79e57ffb56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 5 Oct 2015 14:33:19 +0200 Subject: Avoid always updating inet_dns in the primary bootstrap The include file inet_dns_record_adts.hrl is generated by the Perl script inet_dns_record_adts.pl in a non-deterministic way. That is, every time the script is run, the functions will be in a different order. That will cause inet_dns.beam in the primary bootstrap to be updated every time the bootstrap is updated, even though there is no actual code change. Modify the Perl script to sort the keys pulled out from hashes to make the order deterministic. --- lib/kernel/src/inet_dns_record_adts.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/inet_dns_record_adts.pl b/lib/kernel/src/inet_dns_record_adts.pl index 657d2b9d35..6d719d836e 100644 --- a/lib/kernel/src/inet_dns_record_adts.pl +++ b/lib/kernel/src/inet_dns_record_adts.pl @@ -57,7 +57,8 @@ while() { $" = ','; $\ = "\n"; -while( my ($Name, $r) = each(%Names)) { +foreach my $Name (sort keys %Names) { + my $r = $Names{$Name}; # Create substitutions for this Name my ($Record, @Fields) = @{ $r }; my @FieldMatchValues; @@ -110,7 +111,8 @@ while( my ($Name, $r) = each(%Names)) { for my $i ( 0 .. $#INDEX ) { my $line = $INDEX[$i]; if ($line =~ s/^[*]//) { - while( my ($Name, $r) = each(%Names)) { + foreach my $Name (sort keys %Names) { + my $r = $Names{$Name}; my ($Record) = @{ $r }; $_ = $line; s/Name\b/$Name/g; -- cgit v1.2.3 From 000d6be54e5f0c20f797d73a355e50f76fc170c7 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 30 Sep 2015 20:31:32 +0200 Subject: ssh: aes192-ctr and aes256-ctr implemented --- lib/ssh/src/ssh_transport.erl | 167 ++++++++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 65 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 2b6f0a3cdc..e86c93263f 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -79,18 +79,20 @@ supported_algorithms(kex) -> [ {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]}, {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]}, + {'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]}, + {'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]}, + {'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]}, {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]}, - {'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]}, - {'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]}, - {'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]}, - {'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]} + {'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]} ]); supported_algorithms(public_key) -> ssh_auth:default_public_key_algorithms(); supported_algorithms(cipher) -> same( select_crypto_supported( - [{'aes128-ctr', [{ciphers,aes_ctr}]}, + [{'aes256-ctr', [{ciphers,{aes_ctr,256}}]}, + {'aes192-ctr', [{ciphers,{aes_ctr,192}}]}, + {'aes128-ctr', [{ciphers,{aes_ctr,128}}]}, {'aes128-cbc', [{ciphers,aes_cbc128}]}, {'3des-cbc', [{ciphers,des3_cbc}]} ] @@ -98,8 +100,8 @@ supported_algorithms(cipher) -> supported_algorithms(mac) -> same( select_crypto_supported( - [{'hmac-sha2-512', [{hashs,sha512}]}, - {'hmac-sha2-256', [{hashs,sha256}]}, + [{'hmac-sha2-256', [{hashs,sha256}]}, + {'hmac-sha2-512', [{hashs,sha512}]}, {'hmac-sha1', [{hashs,sha}]} ] )); @@ -124,10 +126,25 @@ crypto_supported_curves() -> end. crypto_supported(Conditions, Supported) -> - lists:all( fun({Tag,CryptoName}) -> - lists:member(CryptoName, proplists:get_value(Tag,Supported,[])) + lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) -> + crypto_name_supported(Tag,CryptoName,Supported); + ({Tag,{Name=aes_ctr,Len}}) when is_integer(Len) -> + crypto_name_supported(Tag,Name,Supported) andalso + ctr_len_supported(Name,Len) end, Conditions). +crypto_name_supported(Tag, CryptoName, Supported) -> + lists:member(CryptoName, proplists:get_value(Tag,Supported,[])). + +ctr_len_supported(Name, Len) -> + try + crypto:stream_encrypt(crypto:stream_init(Name, <<0:Len>>, <<0:128>>), <<"">>) + of + {_,X} -> is_binary(X) + catch + _:_ -> false + end. + same(Algs) -> [{client2server,Algs}, {server2client,Algs}]. @@ -899,52 +916,9 @@ verify(PlainText, Hash, Sig, {_, #'Dss-Parms'{}} = Key) -> verify(PlainText, Hash, Sig, Key) -> public_key:verify(PlainText, Hash, Sig, Key). -%% public key algorithms -%% -%% ssh-dss REQUIRED sign Raw DSS Key -%% ssh-rsa RECOMMENDED sign Raw RSA Key -%% x509v3-sign-rsa OPTIONAL sign X.509 certificates (RSA key) -%% x509v3-sign-dss OPTIONAL sign X.509 certificates (DSS key) -%% spki-sign-rsa OPTIONAL sign SPKI certificates (RSA key) -%% spki-sign-dss OPTIONAL sign SPKI certificates (DSS key) -%% pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key) -%% pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key) -%% - -%% key exchange -%% -%% diffie-hellman-group1-sha1 REQUIRED -%% diffie-hellman-group14-sha1 REQUIRED -%% -%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Encryption -%% -%% chiphers %% -%% 3des-cbc REQUIRED -%% three-key 3DES in CBC mode -%% blowfish-cbc OPTIONAL Blowfish in CBC mode -%% twofish256-cbc OPTIONAL Twofish in CBC mode, -%% with 256-bit key -%% twofish-cbc OPTIONAL alias for "twofish256-cbc" (this -%% is being retained for -%% historical reasons) -%% twofish192-cbc OPTIONAL Twofish with 192-bit key -%% twofish128-cbc OPTIONAL Twofish with 128-bit key -%% aes256-cbc OPTIONAL AES in CBC mode, -%% with 256-bit key -%% aes192-cbc OPTIONAL AES with 192-bit key -%% aes128-cbc RECOMMENDED AES with 128-bit key -%% serpent256-cbc OPTIONAL Serpent in CBC mode, with -%% 256-bit key -%% serpent192-cbc OPTIONAL Serpent with 192-bit key -%% serpent128-cbc OPTIONAL Serpent with 128-bit key -%% arcfour OPTIONAL the ARCFOUR stream cipher -%% idea-cbc OPTIONAL IDEA in CBC mode -%% cast128-cbc OPTIONAL CAST-128 in CBC mode -%% none OPTIONAL no encryption; NOT RECOMMENDED +%% Encryption %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -975,16 +949,44 @@ encrypt_init(#ssh{encrypt = 'aes128-cbc', role = server} = Ssh) -> encrypt_block_size = 16, encrypt_ctx = IV}}; encrypt_init(#ssh{encrypt = 'aes128-ctr', role = client} = Ssh) -> - IV = hash(Ssh, "A", 128), + IV = hash(Ssh, "A", 128), <> = hash(Ssh, "C", 128), State = crypto:stream_init(aes_ctr, K, IV), {ok, Ssh#ssh{encrypt_keys = K, encrypt_block_size = 16, encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes192-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "A", 128), + <> = hash(Ssh, "C", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes256-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "A", 128), + <> = hash(Ssh, "C", 256), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = State}}; encrypt_init(#ssh{encrypt = 'aes128-ctr', role = server} = Ssh) -> - IV = hash(Ssh, "B", 128), + IV = hash(Ssh, "B", 128), <> = hash(Ssh, "D", 128), State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes192-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "B", 128), + <> = hash(Ssh, "D", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = State}}; +encrypt_init(#ssh{encrypt = 'aes256-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "B", 128), + <> = hash(Ssh, "D", 256), + State = crypto:stream_init(aes_ctr, K, IV), {ok, Ssh#ssh{encrypt_keys = K, encrypt_block_size = 16, encrypt_ctx = State}}. @@ -1013,6 +1015,14 @@ encrypt(#ssh{encrypt = 'aes128-cbc', encrypt(#ssh{encrypt = 'aes128-ctr', encrypt_ctx = State0} = Ssh, Data) -> {State, Enc} = crypto:stream_encrypt(State0,Data), + {Ssh#ssh{encrypt_ctx = State}, Enc}; +encrypt(#ssh{encrypt = 'aes192-ctr', + encrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_encrypt(State0,Data), + {Ssh#ssh{encrypt_ctx = State}, Enc}; +encrypt(#ssh{encrypt = 'aes256-ctr', + encrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_encrypt(State0,Data), {Ssh#ssh{encrypt_ctx = State}, Enc}. @@ -1053,10 +1063,38 @@ decrypt_init(#ssh{decrypt = 'aes128-ctr', role = client} = Ssh) -> {ok, Ssh#ssh{decrypt_keys = K, decrypt_block_size = 16, decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes192-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "B", 128), + <> = hash(Ssh, "D", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes256-ctr', role = client} = Ssh) -> + IV = hash(Ssh, "B", 128), + <> = hash(Ssh, "D", 256), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = State}}; decrypt_init(#ssh{decrypt = 'aes128-ctr', role = server} = Ssh) -> IV = hash(Ssh, "A", 128), <> = hash(Ssh, "C", 128), State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes192-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "A", 128), + <> = hash(Ssh, "C", 192), + State = crypto:stream_init(aes_ctr, K, IV), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = State}}; +decrypt_init(#ssh{decrypt = 'aes256-ctr', role = server} = Ssh) -> + IV = hash(Ssh, "A", 128), + <> = hash(Ssh, "C", 256), + State = crypto:stream_init(aes_ctr, K, IV), {ok, Ssh#ssh{decrypt_keys = K, decrypt_block_size = 16, decrypt_ctx = State}}. @@ -1084,6 +1122,14 @@ decrypt(#ssh{decrypt = 'aes128-cbc', decrypt_keys = Key, decrypt(#ssh{decrypt = 'aes128-ctr', decrypt_ctx = State0} = Ssh, Data) -> {State, Enc} = crypto:stream_decrypt(State0,Data), + {Ssh#ssh{decrypt_ctx = State}, Enc}; +decrypt(#ssh{decrypt = 'aes192-ctr', + decrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_decrypt(State0,Data), + {Ssh#ssh{decrypt_ctx = State}, Enc}; +decrypt(#ssh{decrypt = 'aes256-ctr', + decrypt_ctx = State0} = Ssh, Data) -> + {State, Enc} = crypto:stream_decrypt(State0,Data), {Ssh#ssh{decrypt_ctx = State}, Enc}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1168,17 +1214,8 @@ decompress(#ssh{decompress = 'zlib@openssh.com', decompress_ctx = Context, authe {Ssh, list_to_binary(Decompressed)}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% MAC calculation %% -%% hmac-sha1 REQUIRED HMAC-SHA1 (digest length = key -%% length = 20) -%% hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest -%% length = 12, key length = 20) -%% hmac-md5 OPTIONAL HMAC-MD5 (digest length = key -%% length = 16) -%% hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest -%% length = 12, key length = 16) -%% none OPTIONAL no MAC; NOT RECOMMENDED +%% MAC calculation %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From d848a4d75ed1baa645df69461b550299325205d9 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 1 Oct 2015 12:12:15 +0200 Subject: ssh: document ctr crypto mode --- lib/ssh/doc/src/ssh.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 293d618eed..dd85baf219 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -42,7 +42,8 @@ Supported SSH version is 2.0. Supported public key algorithms: ssh-rsa and ssh-dss. Supported MAC algorithms: hmac-sha2-512, hmac-sha2-256 and hmac-sha1. - Supported encryption algorithms: aes128-ctr, aes128-cb and 3des-cbc. + Supported MAC algorithms: hmac-sha2-256 and hmac-sha1. + Supported encryption algorithms: aes256-ctr, aes192-ctr, aes128-ctr, aes128-cb and 3des-cbc. Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256. Supported compression algorithms: none, zlib Supports unicode filenames if the emulator and the underlaying OS support it. -- cgit v1.2.3 From f1e82db97780529ccf46b8e7b72d482649b6dcd2 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 1 Oct 2015 10:27:18 +0200 Subject: ssh: Bug in zlib@openssh.com compression fixed --- lib/ssh/src/ssh_connection_handler.erl | 4 ++-- lib/ssh/src/ssh_transport.erl | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 646f787874..ee1dd5c9ce 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -530,7 +530,7 @@ userauth(#ssh_msg_userauth_request{service = "ssh-connection", Pid ! ssh_connected, connected_fun(User, Address, Method, Opts), {next_state, connected, - next_packet(State#state{auth_user = User, ssh_params = Ssh})}; + next_packet(State#state{auth_user = User, ssh_params = Ssh#ssh{authenticated = true}})}; {not_authorized, {User, Reason}, {Reply, Ssh}} when Method == "keyboard-interactive" -> retry_fun(User, Address, Reason, Opts), send_msg(Reply, State), @@ -622,7 +622,7 @@ userauth_keyboard_interactive(#ssh_msg_userauth_info_response{} = Msg, Pid ! ssh_connected, connected_fun(User, Address, "keyboard-interactive", Opts), {next_state, connected, - next_packet(State#state{auth_user = User, ssh_params = Ssh})}; + next_packet(State#state{auth_user = User, ssh_params = Ssh#ssh{authenticated = true}})}; {not_authorized, {User, Reason}, {Reply, Ssh}} -> retry_fun(User, Address, Reason, Opts), send_msg(Reply, State), diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index e86c93263f..840564e246 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -65,9 +65,7 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()]. algo_classes() -> [kex, public_key, cipher, mac, compression]. -default_algorithms(compression) -> - %% Do not announce 'zlib@openssh.com' because there seem to be problems - supported_algorithms(compression, same(['zlib@openssh.com'])); +default_algorithms(kex) -> supported_algorithms(kex, []); %% Just to have a call... default_algorithms(Alg) -> supported_algorithms(Alg). @@ -106,8 +104,10 @@ supported_algorithms(mac) -> ] )); supported_algorithms(compression) -> - same(['none','zlib','zlib@openssh.com']). - + same(['none', + 'zlib@openssh.com', + 'zlib' + ]). supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> [{client2server,As1},{server2client,As2}] = supported_algorithms(Key), -- cgit v1.2.3 From a07d8d5ecd8aa1f09ce5437f58d1c41118337424 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 1 Oct 2015 18:51:10 +0200 Subject: ssh: compression tests skipped if alg is not supported --- lib/ssh/test/ssh_basic_SUITE.erl | 88 ++++++++++++++++++++--------------- lib/ssh/test/ssh_test_lib.erl | 22 ++++++++- lib/ssh/test/ssh_to_openssh_SUITE.erl | 79 +++++++++++++++++-------------- 3 files changed, 116 insertions(+), 73 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 51431da48e..2ff7198bf8 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -362,30 +362,36 @@ exec(Config) when is_list(Config) -> %%-------------------------------------------------------------------- %%% Test that compression option works exec_compressed(Config) when is_list(Config) -> - process_flag(trap_exit, true), - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, - {preferred_algorithms,[{compression, [zlib]}]}, - {failfun, fun ssh_test_lib:failfun/2}]), + case ssh_test_lib:ssh_supports(zlib, compression) of + false -> + {skip, "zlib compression is not supported"}; + + true -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, + {preferred_algorithms,[{compression, [zlib]}]}, + {failfun, fun ssh_test_lib:failfun/2}]), - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user_dir, UserDir}, - {user_interaction, false}]), - {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId, - "1+1.", infinity), - Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, - case ssh_test_lib:receive_exec_result(Data) of - expected -> - ok; - Other -> - ct:fail(Other) - end, - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), - ssh:stop_daemon(Pid). + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}]), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "1+1.", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ok; + Other -> + ct:fail(Other) + end, + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + ssh:stop_daemon(Pid) + end. %%-------------------------------------------------------------------- %%% Idle timeout test @@ -708,22 +714,28 @@ shell_unicode_string(Config) -> %%-------------------------------------------------------------------- %%% Test basic connection with openssh_zlib openssh_zlib_basic_test(Config) -> - SystemDir = filename:join(?config(priv_dir, Config), system), - UserDir = ?config(priv_dir, Config), + case ssh_test_lib:ssh_supports(['zlib@openssh.com',none], compression) of + {false,L} -> + {skip, io_lib:format("~p compression is not supported",[L])}; - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, UserDir}, - {preferred_algorithms,[{compression, ['zlib@openssh.com']}]}, - {failfun, fun ssh_test_lib:failfun/2}]), - ConnectionRef = - ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, - {user_dir, UserDir}, - {user_interaction, false}, - {preferred_algorithms,[{compression, ['zlib@openssh.com', - none]}]} - ]), - ok = ssh:close(ConnectionRef), - ssh:stop_daemon(Pid). + true -> + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {preferred_algorithms,[{compression, ['zlib@openssh.com']}]}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user_interaction, false}, + {preferred_algorithms,[{compression, ['zlib@openssh.com', + none]}]} + ]), + ok = ssh:close(ConnectionRef), + ssh:stop_daemon(Pid) + end. %%-------------------------------------------------------------------- ssh_info_print(Config) -> diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 6d568125bb..e16df6f959 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -552,4 +552,24 @@ algo_intersection(_, _) -> to_atoms(L) -> lists:map(fun erlang:list_to_atom/1, L). - +%%%---------------------------------------------------------------- +ssh_supports(Alg, SshDefaultAlg_tag) -> + SupAlgs = + case proplists:get_value(SshDefaultAlg_tag, + ssh:default_algorithms()) of + [{_K1,L1}, {_K2,L2}] -> + lists:usort(L1++L2); + L -> + L + end, + if + is_atom(Alg) -> + lists:member(Alg, SupAlgs); + is_list(Alg) -> + case Alg--SupAlgs of + [] -> + true; + UnSup -> + {false,UnSup} + end + end. diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 104c1f9107..bc51ae0724 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -182,23 +182,29 @@ erlang_client_openssh_server_exec_compressed() -> erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) -> CompressAlgs = [zlib, 'zlib@openssh.com',none], - ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user_interaction, false}, - {preferred_algorithms, - [{compression,CompressAlgs}]}]), - {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), - success = ssh_connection:exec(ConnectionRef, ChannelId, - "echo testing", infinity), - Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, - case ssh_test_lib:receive_exec_result(Data) of - expected -> - ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); - {unexpected_msg,{ssh_cm, ConnectionRef, - {exit_status, ChannelId, 0}} = ExitStatus} -> - ct:log("0: Collected data ~p", [ExitStatus]), - ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId); - Other -> - ct:fail(Other) + case ssh_test_lib:ssh_supports(CompressAlgs, compression) of + {false,L} -> + {skip, io_lib:format("~p compression is not supported",[L])}; + + true -> + ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, + {user_interaction, false}, + {preferred_algorithms, + [{compression,CompressAlgs}]}]), + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + success = ssh_connection:exec(ConnectionRef, ChannelId, + "echo testing", infinity), + Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}}, + case ssh_test_lib:receive_exec_result(Data) of + expected -> + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId); + {unexpected_msg,{ssh_cm, ConnectionRef, + {exit_status, ChannelId, 0}} = ExitStatus} -> + ct:log("0: Collected data ~p", [ExitStatus]), + ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId); + Other -> + ct:fail(Other) + end end. %%-------------------------------------------------------------------- @@ -425,27 +431,32 @@ erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) -> PrivDir = ?config(priv_dir, Config), KnownHosts = filename:join(PrivDir, "known_hosts"), -%% CompressAlgs = [zlib, 'zlib@openssh.com'], % Does not work - CompressAlgs = [zlib], - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {preferred_algorithms, - [{compression, CompressAlgs}]}, - {failfun, fun ssh_test_lib:failfun/2}]), + CompressAlgs = [zlib, 'zlib@openssh.com'], % Does not work +%% CompressAlgs = [zlib], + case ssh_test_lib:ssh_supports(CompressAlgs, compression) of + {false,L} -> + {skip, io_lib:format("~p compression is not supported",[L])}; - ct:sleep(500), + true -> + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {preferred_algorithms, + [{compression, CompressAlgs}]}, + {failfun, fun ssh_test_lib:failfun/2}]), - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " -C "++ Host ++ " 1+1.", - SshPort = open_port({spawn, Cmd}, [binary]), + ct:sleep(500), - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive answer") + Cmd = "ssh -p " ++ integer_to_list(Port) ++ + " -o UserKnownHostsFile=" ++ KnownHosts ++ " -C "++ Host ++ " 1+1.", + SshPort = open_port({spawn, Cmd}, [binary]), - end, - ssh:stop_daemon(Pid). + receive + {SshPort,{data, <<"2\n">>}} -> + ok + after ?TIMEOUT -> + ct:fail("Did not receive answer") + end, + ssh:stop_daemon(Pid) + end. %%-------------------------------------------------------------------- erlang_client_openssh_server_setenv() -> -- cgit v1.2.3 From f6996a8b1f9ecec034700c7ec5e914c7084fa5b5 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 1 Oct 2015 18:51:32 +0200 Subject: ssh: doc update --- lib/ssh/doc/src/ssh.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index dd85baf219..93bea09e4e 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -45,7 +45,7 @@ Supported MAC algorithms: hmac-sha2-256 and hmac-sha1. Supported encryption algorithms: aes256-ctr, aes192-ctr, aes128-ctr, aes128-cb and 3des-cbc. Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256. - Supported compression algorithms: none, zlib + Supported compression algorithms: none, zlib@openssh.com, zlib Supports unicode filenames if the emulator and the underlaying OS support it. See section DESCRIPTION in the file manual page in kernel -- cgit v1.2.3 From ca0aef835dba5ef2c4185289092ed0fc2f1bb2ba Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 7 Oct 2015 12:15:08 +0200 Subject: ssh: added dh_gex tests --- lib/ssh/src/ssh_transport.erl | 13 +++++++------ lib/ssh/test/ssh_algorithms_SUITE.erl | 25 +++++++++++++++++++++++++ lib/ssh/test/ssh_test_lib.erl | 10 ++++++++-- 3 files changed, 40 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 840564e246..3ba5e4d297 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -336,11 +336,12 @@ key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group1-sha1' ; {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}; -key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group-exchange-sha1' ; - Kex == 'diffie-hellman-group-exchange-sha256' -> - Min = ?DEFAULT_DH_GROUP_MIN, - NBits = ?DEFAULT_DH_GROUP_NBITS, - Max = ?DEFAULT_DH_GROUP_MAX, +key_exchange_first_msg(Kex, Ssh0=#ssh{opts=Opts}) when Kex == 'diffie-hellman-group-exchange-sha1' ; + Kex == 'diffie-hellman-group-exchange-sha256' -> + {Min,NBits,Max} = + proplists:get_value(dh_gex_limits, Opts, {?DEFAULT_DH_GROUP_MIN, + ?DEFAULT_DH_GROUP_NBITS, + ?DEFAULT_DH_GROUP_MAX}), {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kex_dh_gex_request{min = Min, n = NBits, @@ -1387,7 +1388,7 @@ dh_gex_group(Min, N, Max, undefined) -> dh_gex_group(Min, N, Max, dh_gex_default_groups()); dh_gex_group(Min, N, Max, Groups) -> %% First try to find an exact match. If not an exact match, select the largest possible. - {_,Group} = + {_Size,Group} = lists:foldl( fun(_, {I,G}) when I==N -> %% If we have an exact match already: use that one diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index e67fa2469f..1188b324ba 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -161,6 +161,21 @@ simple_exec(Config) -> {Host,Port} = ?config(srvr_addr, Config), ssh_test_lib:std_simple_exec(Host, Port, Config). +%%-------------------------------------------------------------------- +%% Testing all default groups +simple_exec_group14(Config) -> simple_exec_group(2048, Config). +simple_exec_group15(Config) -> simple_exec_group(3072, Config). +simple_exec_group16(Config) -> simple_exec_group(4096, Config). +simple_exec_group17(Config) -> simple_exec_group(6144, Config). +simple_exec_group18(Config) -> simple_exec_group(8192, Config). + +simple_exec_group(I, Config) -> + Min = I-100, + Max = I+100, + {Host,Port} = ?config(srvr_addr, Config), + ssh_test_lib:std_simple_exec(Host, Port, Config, + [{dh_gex_limits,{Min,I,Max}}]). + %%-------------------------------------------------------------------- %% Use the ssh client of the OS to connect sshc_simple_exec(Config) -> @@ -254,6 +269,16 @@ specific_test_cases(Tag, Alg, SshcAlgos, SshdAlgos) -> [sshd_simple_exec]; _ -> [] + end ++ + case {Tag,Alg} of + {kex,'diffie-hellman-group-exchange-sha1'} -> + [simple_exec_group14, + simple_exec_group15, + simple_exec_group16, + simple_exec_group17, + simple_exec_group18]; + _ -> + [] end. supports(Tag, Alg, Algos) -> diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index e16df6f959..f1e1a51c00 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -93,9 +93,12 @@ std_connect(Config, Host, Port, ExtraOpts) -> | ExtraOpts]). std_simple_sftp(Host, Port, Config) -> + std_simple_sftp(Host, Port, Config, []). + +std_simple_sftp(Host, Port, Config, Opts) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "test.data"), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, Opts), {ok, ChannelRef} = ssh_sftp:start_channel(ConnectionRef), Data = crypto:rand_bytes(proplists:get_value(std_simple_sftp_size,Config,10)), ok = ssh_sftp:write_file(ChannelRef, DataFile, Data), @@ -104,7 +107,10 @@ std_simple_sftp(Host, Port, Config) -> Data == ReadData. std_simple_exec(Host, Port, Config) -> - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, []), + std_simple_exec(Host, Port, Config, []). + +std_simple_exec(Host, Port, Config, Opts) -> + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, Opts), {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId, "23+21-2.", infinity), Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"42\n">>}}, -- cgit v1.2.3 From c5810d92afe70ab460f23234665b31cba743bc0a Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 8 Oct 2015 14:14:11 +0200 Subject: Don't attempt logging when log type is 'silent' The error logger handler ct_conn_log_h in common_test did not respect the 'silent' option, and tried to print to an undefined file descriptor. This has been corrected. --- lib/common_test/src/ct_conn_log_h.erl | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl index 2dd4fdac05..5239ec1ff8 100644 --- a/lib/common_test/src/ct_conn_log_h.erl +++ b/lib/common_test/src/ct_conn_log_h.erl @@ -104,18 +104,26 @@ terminate(_,#state{logs=Logs}) -> %%%----------------------------------------------------------------- %%% Writing reports write_report(_Time,#conn_log{header=false,module=ConnMod}=Info,Data,GL,State) -> - {LogType,Fd} = get_log(Info,GL,State), - io:format(Fd,"~n~ts",[format_data(ConnMod,LogType,Data)]); + case get_log(Info,GL,State) of + {silent,_} -> + ok; + {LogType,Fd} -> + io:format(Fd,"~n~ts",[format_data(ConnMod,LogType,Data)]) + end; write_report(Time,#conn_log{module=ConnMod}=Info,Data,GL,State) -> - {LogType,Fd} = get_log(Info,GL,State), - io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time), - format_title(LogType,Info), - format_data(ConnMod,LogType,Data)]). + case get_log(Info,GL,State) of + {silent,_} -> + ok; + {LogType,Fd} -> + io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time), + format_title(LogType,Info), + format_data(ConnMod,LogType,Data)]) + end. write_error(Time,#conn_log{module=ConnMod}=Info,Report,GL,State) -> case get_log(Info,GL,State) of - {html,_} -> + {LogType,_} when LogType==html; LogType==silent -> %% The error will anyway be written in the html log by the %% sasl error handler, so don't write it again. ok; -- cgit v1.2.3 From 6e93fb788aebb9050da2166749b41ff54197e049 Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Thu, 7 May 2015 14:43:02 +0200 Subject: Take out automatic insertion of 'undefined' from typed record fields Background ----------- In record fields with a type declaration but without an initializer, the Erlang parser inserted automatically the singleton type 'undefined' to the list of declared types, if that value was not present there. I.e. the record declaration: -record(rec, {f1 :: float(), f2 = 42 :: integer(), f3 :: some_mod:some_typ()}). was translated by the parser to: -record(rec, {f1 :: float() | 'undefined', f2 = 42 :: integer(), f3 :: some_mod:some_typ() | 'undefined'}). The rationale for this was that creation of a "dummy" #rec{} record should not result in a warning from dialyzer that e.g. the implicit initialization of the #rec.f1 field violates its type declaration. Problems --------- This seemingly innocent action has some unforeseen consequences. For starters, there is no way for programmers to declare that e.g. only floats make sense for the f1 field of #rec{} records when there is no `obvious' default initializer for this field. (This also affects tools like PropEr that use these declarations produced by the Erlang parser to generate random instances of records for testing purposes.) It also means that dialyzer does not warn if e.g. an is_atom/1 test or something more exotic like an atom_to_list/1 call is performed on the value of the f1 field. Similarly, there is no way to extend dialyzer to warn if it finds record constructions where f1 is not initialized to some float. Last but not least, it is semantically problematic when the type of the field is an opaque type: creating a union of an opaque and a structured type is very problematic for analysis because it fundamentally breaks the opacity of the term at that point. Change ------- To solve these problems the parser will not automatically insert the 'undefined' value anymore; instead the user has the option to choose the places where this value makes sense (for the field) and where it does not and insert the | 'undefined' there manually. Consequences of this change ---------------------------- This change means that dialyzer will issue a warning for all places where records with uninitialized fields are created and those fields have a declared type that is incompatible with 'undefined' (e.g. float()). This warning can be suppressed easily by adding | 'undefined' to the type of this field. This also adds documentation that the user really intends to create records where this field is uninitialized. --- .../results/callbacks_and_specs | 6 ++--- lib/dialyzer/test/opaque_SUITE_data/results/crash | 10 ++++---- lib/dialyzer/test/opaque_SUITE_data/results/simple | 2 +- lib/dialyzer/test/r9c_SUITE_data/results/inets | 2 ++ .../test/small_SUITE_data/results/literals | 12 ++++----- .../small_SUITE_data/results/record_creation_diffs | 2 +- .../test/small_SUITE_data/results/record_pat | 2 +- .../results/relevant_record_warning | 2 +- .../test/small_SUITE_data/results/undefined | 2 ++ lib/dialyzer/test/small_SUITE_data/src/trec.erl | 2 +- lib/dialyzer/test/small_SUITE_data/undefined.erl | 29 ++++++++++++++++++++++ lib/hipe/cerl/erl_types.erl | 13 +++++----- lib/stdlib/src/erl_parse.yrl | 22 +--------------- lib/stdlib/test/erl_pp_SUITE.erl | 6 +++-- 14 files changed, 63 insertions(+), 49 deletions(-) create mode 100644 lib/dialyzer/test/small_SUITE_data/results/undefined create mode 100644 lib/dialyzer/test/small_SUITE_data/undefined.erl (limited to 'lib') diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs index 33d135048e..38999e8919 100644 --- a/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs @@ -1,5 +1,5 @@ -my_callbacks_wrong.erl:26: The return type #state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()} in the specification of callback_init/1 is not a subtype of {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour -my_callbacks_wrong.erl:28: The inferred return type of callback_init/1 (#state{parent::'undefined' | pid(),status::'init',subscribe::[],counter::1}) has nothing in common with {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour -my_callbacks_wrong.erl:30: The return type {'reply',#state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()}} in the specification of callback_cast/3 is not a subtype of {'noreply',_}, which is the expected return type for the callback of my_behaviour behaviour +my_callbacks_wrong.erl:26: The return type #state{parent::pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()} in the specification of callback_init/1 is not a subtype of {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour +my_callbacks_wrong.erl:28: The inferred return type of callback_init/1 (#state{parent::pid(),status::'init',subscribe::[],counter::1}) has nothing in common with {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour +my_callbacks_wrong.erl:30: The return type {'reply',#state{parent::pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()}} in the specification of callback_cast/3 is not a subtype of {'noreply',_}, which is the expected return type for the callback of my_behaviour behaviour my_callbacks_wrong.erl:39: The specified type for the 2nd argument of callback_call/3 (atom()) is not a supertype of pid(), which is expected type for this argument in the callback of the my_behaviour behaviour diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/crash b/lib/dialyzer/test/opaque_SUITE_data/results/crash index 69bdc00257..d63389f79c 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/crash +++ b/lib/dialyzer/test/opaque_SUITE_data/results/crash @@ -1,6 +1,6 @@ -crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::'undefined' | crash_1:target() -crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::'undefined' | crash_1:target()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),maybe_improper_list()) -crash_1.erl:50: The pattern <_Branch, []> can never match the type -crash_1.erl:52: The pattern can never match the type -crash_1.erl:54: The pattern can never match the type +crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::crash_1:target() +crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::crash_1:target()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),maybe_improper_list()) +crash_1.erl:50: The pattern <_Branch, []> can never match the type +crash_1.erl:52: The pattern can never match the type +crash_1.erl:54: The pattern can never match the type diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/simple b/lib/dialyzer/test/opaque_SUITE_data/results/simple index 1a7a139d6e..5f58f69730 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/simple +++ b/lib/dialyzer/test/opaque_SUITE_data/results/simple @@ -18,7 +18,7 @@ rec_api.erl:104: Matching of pattern {'r2', 10} tagged with a record name violat rec_api.erl:113: The attempt to match a term of type #r3{f1::queue:queue(_)} against the pattern {'r3', 'a'} breaks the opaqueness of queue:queue(_) rec_api.erl:118: Record construction #r3{f1::10} violates the declared type of field f1::queue:queue(_) rec_api.erl:123: The attempt to match a term of type #r3{f1::10} against the pattern {'r3', 10} breaks the opaqueness of queue:queue(_) -rec_api.erl:24: Record construction #r1{f1::10} violates the declared type of field f1::'undefined' | rec_api:a() +rec_api.erl:24: Record construction #r1{f1::10} violates the declared type of field f1::rec_api:a() rec_api.erl:29: Matching of pattern {'r1', 10} tagged with a record name violates the declared type of #r1{f1::10} rec_api.erl:33: The attempt to match a term of type rec_adt:r1() against the pattern {'r1', 'a'} breaks the opaqueness of the term rec_api.erl:35: Invalid type specification for function rec_api:adt_t1/1. The success typing is (#r1{f1::'a'}) -> #r1{f1::'a'} diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/inets b/lib/dialyzer/test/r9c_SUITE_data/results/inets index d377f34978..89be9652e3 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/inets +++ b/lib/dialyzer/test/r9c_SUITE_data/results/inets @@ -37,6 +37,7 @@ mod_cgi.erl:372: The pattern {'http_response', NewAccResponse} can never match t mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom() | {'no_translation',binary()})) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) mod_dir.erl:72: The pattern {'error', Reason} can never match the type {'ok',[[[any()] | char()],...]} mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type +mod_get.erl:150: Record construction #file_info{} violates the declared type of field size::non_neg_integer() and type::'device' | 'directory' | 'other' | 'regular' | 'symlink' and access::'none' | 'read' | 'read_write' | 'write' and atime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mtime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and ctime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mode::non_neg_integer() and links::non_neg_integer() and major_device::non_neg_integer() and minor_device::non_neg_integer() and inode::non_neg_integer() and uid::non_neg_integer() and gid::non_neg_integer() mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type mod_htaccess.erl:460: The pattern {'error', BadData} can never match the type {'ok',_} mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],maybe_improper_list()} @@ -47,6 +48,7 @@ mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type mod_include.erl:716: Function read_error/3 will never be called mod_include.erl:719: Function read_error/4 will never be called +mod_range.erl:308: Record construction #file_info{} violates the declared type of field size::non_neg_integer() and type::'device' | 'directory' | 'other' | 'regular' | 'symlink' and access::'none' | 'read' | 'read_write' | 'write' and atime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mtime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and ctime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mode::non_neg_integer() and links::non_neg_integer() and major_device::non_neg_integer() and minor_device::non_neg_integer() and inode::non_neg_integer() and uid::non_neg_integer() and gid::non_neg_integer() mod_security_server.erl:386: The variable O can never match since previous clauses completely covered the type [tuple()] mod_security_server.erl:433: The variable Other can never match since previous clauses completely covered the type [tuple()] mod_security_server.erl:585: The variable _ can never match since previous clauses completely covered the type [tuple()] diff --git a/lib/dialyzer/test/small_SUITE_data/results/literals b/lib/dialyzer/test/small_SUITE_data/results/literals index 03e161ca71..222d2c0cdb 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/literals +++ b/lib/dialyzer/test/small_SUITE_data/results/literals @@ -1,14 +1,14 @@ literals.erl:11: Function t1/0 has no local return -literals.erl:12: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:12: Record construction #r{id::'a'} violates the declared type of field id::'integer' literals.erl:14: Function t2/0 has no local return -literals.erl:15: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:15: Record construction #r{id::'a'} violates the declared type of field id::'integer' literals.erl:17: Function t3/0 has no local return -literals.erl:18: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' -literals.erl:21: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined' +literals.erl:18: Record construction #r{id::'a'} violates the declared type of field id::'integer' +literals.erl:21: Record construction #r{id::'a'} violates the declared type of field id::'integer' literals.erl:23: Function m1/1 has no local return -literals.erl:23: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'} +literals.erl:23: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer'} literals.erl:26: Function m2/1 has no local return -literals.erl:26: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'} +literals.erl:26: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer'} literals.erl:29: Function m3/1 has no local return literals.erl:29: The pattern {{'r', 'a'}} can never match the type any() diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs b/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs index f00c4b10ff..c971935bbf 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs +++ b/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs @@ -1,3 +1,3 @@ record_creation_diffs.erl:10: Function foo/1 has no local return -record_creation_diffs.erl:11: Record construction #bar{some_list::{'this','is','a','tuple'}} violates the declared type of field some_list::'undefined' | [any()] +record_creation_diffs.erl:11: Record construction #bar{some_list::{'this','is','a','tuple'}} violates the declared type of field some_list::[any()] diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_pat b/lib/dialyzer/test/small_SUITE_data/results/record_pat index a46be6c451..8317ea041a 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/record_pat +++ b/lib/dialyzer/test/small_SUITE_data/results/record_pat @@ -1,2 +1,2 @@ -record_pat.erl:14: Matching of pattern {'foo', 'baz'} tagged with a record name violates the declared type of #foo{bar::'undefined' | integer()} +record_pat.erl:14: Matching of pattern {'foo', 'baz'} tagged with a record name violates the declared type of #foo{bar::integer()} diff --git a/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning index 2e417e1b2a..ea3ac92d96 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning +++ b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning @@ -1,3 +1,3 @@ relevant_record_warning.erl:22: Function test/1 has no local return -relevant_record_warning.erl:23: Record construction #r{field::<<_:8>>} violates the declared type of field field::'binary' | 'undefined' +relevant_record_warning.erl:23: Record construction #r{field::<<_:8>>} violates the declared type of field field::'binary' diff --git a/lib/dialyzer/test/small_SUITE_data/results/undefined b/lib/dialyzer/test/small_SUITE_data/results/undefined new file mode 100644 index 0000000000..9daa8640d3 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/undefined @@ -0,0 +1,2 @@ + +r.erl:16: Record construction #r{a::{'fi'},b::{'a','b'},c::[],d::'undefined',e::[],f::'undefined'} violates the declared type of field b::[any()] and d::[any()] and f::[any()] diff --git a/lib/dialyzer/test/small_SUITE_data/src/trec.erl b/lib/dialyzer/test/small_SUITE_data/src/trec.erl index 06706162c1..516358f7c6 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/trec.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/trec.erl @@ -8,7 +8,7 @@ -module(trec). -export([test/0, mk_foo_exp/2]). --record(foo, {a :: integer(), b :: [atom()]}). +-record(foo, {a :: integer() | 'undefined', b :: [atom()]}). %% %% For these functions we currently get the following warnings: diff --git a/lib/dialyzer/test/small_SUITE_data/undefined.erl b/lib/dialyzer/test/small_SUITE_data/undefined.erl new file mode 100644 index 0000000000..8549f2e161 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/undefined.erl @@ -0,0 +1,29 @@ +-module(undefined). + +-export([t/0]). + +%% As of OTP 19.0 'undefined' is no longer added to fields with a type +%% declaration but without an initializer. The pretty printing of +%% records (erl_types:t_to_string()) is updated to reflect this: if a +%% field is of type 'undefined', it is output if 'undefined' is not in +%% the declared type of the field. (It used to be the case that the +%% singleton type 'undefined' was never output.) +%% +%% One consequence is shown by the example below: the warning about +%% the record construction violating the the declared type shows +%% #r{..., d::'undefined', ...} which is meant to be of help to the +%% user, who could otherwise get confused the first time (s)he gets +%% confronted by the warning. + +-record(r, + { + a = {fi}, + b = {a,b} :: list(), % violation + c = {a,b} :: list(), + d :: list(), % violation + e = [] :: list(), + f = undefined :: list() % violation + }). + +t() -> + #r{c = []}. diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index cd2d2fe207..420d7e2a8f 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -3974,18 +3974,17 @@ record_to_string(Tag, [_|Fields], FieldNames, RecDict) -> FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []), "#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}". -record_fields_to_string([F|Fs], [{FName, _Abstr, _DefType}|FDefs], +record_fields_to_string([F|Fs], [{FName, _Abstr, DefType}|FDefs], RecDict, Acc) -> NewAcc = - case t_is_equal(F, t_any()) orelse t_is_any_atom('undefined', F) of + case + t_is_equal(F, t_any()) orelse + (t_is_any_atom('undefined', F) andalso + not t_is_none(t_inf(F, DefType))) + of true -> Acc; false -> StrFV = atom_to_string(FName) ++ "::" ++ t_to_string(F, RecDict), - %% ActualDefType = t_subtract(DefType, t_atom('undefined')), - %% Str = case t_is_any(ActualDefType) of - %% true -> StrFV; - %% false -> StrFV ++ "::" ++ t_to_string(ActualDefType, RecDict) - %% end, [StrFV|Acc] end, record_fields_to_string(Fs, FDefs, RecDict, NewAcc); diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index 206b0c6e7b..ae42a8f0b1 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -790,31 +790,11 @@ record_fields([{match,_Am,{atom,Aa,A},Expr}|Fields]) -> [{record_field,Aa,{atom,Aa,A},Expr}|record_fields(Fields)]; record_fields([{typed,Expr,TypeInfo}|Fields]) -> [Field] = record_fields([Expr]), - TypeInfo1 = - case Expr of - {match, _, _, _} -> TypeInfo; %% If we have an initializer. - {atom, Aa, _} -> - case has_undefined(TypeInfo) of - false -> - lift_unions(abstract2(undefined, Aa), TypeInfo); - true -> - TypeInfo - end - end, - [{typed_record_field,Field,TypeInfo1}|record_fields(Fields)]; + [{typed_record_field,Field,TypeInfo}|record_fields(Fields)]; record_fields([Other|_Fields]) -> ret_err(?anno(Other), "bad record field"); record_fields([]) -> []. -has_undefined({atom,_,undefined}) -> - true; -has_undefined({ann_type,_,[_,T]}) -> - has_undefined(T); -has_undefined({type,_,union,Ts}) -> - lists:any(fun has_undefined/1, Ts); -has_undefined(_) -> - false. - term(Expr) -> try normalise(Expr) catch _:_R -> ret_err(?anno(Expr), "bad attribute") diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 389fd059f6..9bb193d865 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -928,7 +928,9 @@ otp_8522(Config) when is_list(Config) -> ?line {ok, _} = compile:file(FileName, [{outdir,?privdir},debug_info]), BF = filename("otp_8522", Config), ?line {ok, A} = beam_lib:chunks(BF, [abstract_code]), - ?line 5 = count_atom(A, undefined), + %% OTP-12719: Since 'undefined' is no longer added by the Erlang + %% Parser, the number of 'undefined' is 4. It used to be 5. + ?line 4 = count_atom(A, undefined), ok. count_atom(A, A) -> @@ -1062,7 +1064,7 @@ otp_9147(Config) when is_list(Config) -> ?line {ok, Bin} = file:read_file(PFileName), %% The parentheses around "F1 :: a | b" are new (bugfix). ?line true = - lists:member("-record(undef,{f1 :: undefined | (F1 :: a | b)}).", + lists:member("-record(undef,{f1 :: F1 :: a | b}).", string:tokens(binary_to_list(Bin), "\n")), ok. -- cgit v1.2.3 From 3224c9b0b7022ccf2483af95f4efd8a6b6234f47 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 6 Oct 2015 15:08:57 +0200 Subject: Update Kernel and STDLIB Record field types have been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/kernel/include/file.hrl | 31 ++++++++++--------- lib/kernel/src/disk_log.erl | 68 +++++++++++++++++++---------------------- lib/kernel/src/disk_log.hrl | 6 ++-- lib/kernel/src/global.erl | 20 ++++++------ lib/kernel/src/global_group.erl | 4 +-- lib/stdlib/include/erl_bits.hrl | 10 +++--- lib/stdlib/src/beam_lib.erl | 2 +- lib/stdlib/src/epp.erl | 3 +- lib/stdlib/src/escript.erl | 8 ++--- lib/stdlib/src/supervisor.erl | 10 +++--- 10 files changed, 80 insertions(+), 82 deletions(-) (limited to 'lib') diff --git a/lib/kernel/include/file.hrl b/lib/kernel/include/file.hrl index 7cf033f7f5..36112bb040 100644 --- a/lib/kernel/include/file.hrl +++ b/lib/kernel/include/file.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -23,37 +23,40 @@ %%-------------------------------------------------------------------------- -record(file_info, - {size :: non_neg_integer(), % Size of file in bytes. - type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink', - access :: 'read' | 'write' | 'read_write' | 'none', - atime :: file:date_time() | non_neg_integer(), + {size :: non_neg_integer() | 'undefined', % Size of file in bytes. + type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink' + | 'undefined', + access :: 'read' | 'write' | 'read_write' | 'none' | 'undefined', + atime :: file:date_time() | non_neg_integer() | 'undefined', % The local time the file was last read: % {{Year, Mon, Day}, {Hour, Min, Sec}}. % atime, ctime, mtime may also be unix epochs() - mtime :: file:date_time() | non_neg_integer(), + mtime :: file:date_time() | non_neg_integer() | 'undefined', % The local time the file was last written. - ctime :: file:date_time() | non_neg_integer(), + ctime :: file:date_time() | non_neg_integer() | 'undefined', % The interpretation of this time field % is dependent on operating system. % On Unix it is the last time the file % or the inode was changed. On Windows, % it is the creation time. - mode :: non_neg_integer(), % File permissions. On Windows, + mode :: non_neg_integer() | 'undefined', + % File permissions. On Windows, % the owner permissions will be % duplicated for group and user. - links :: non_neg_integer(), + links :: non_neg_integer() | 'undefined', % Number of links to the file (1 if the % filesystem doesn't support links). - major_device :: non_neg_integer(), + major_device :: non_neg_integer() | 'undefined', % Identifies the file system (Unix), % or the drive number (A: = 0, B: = 1) % (Windows). %% The following are Unix specific. %% They are set to zero on other operating systems. - minor_device :: non_neg_integer(), % Only valid for devices. - inode :: non_neg_integer(), % Inode number for file. - uid :: non_neg_integer(), % User id for owner. - gid :: non_neg_integer()}). % Group id for owner. + minor_device :: non_neg_integer() | 'undefined', + % Only valid for devices. + inode :: non_neg_integer() | 'undefined', % Inode number for file. + uid :: non_neg_integer() | 'undefined', % User id for owner. + gid :: non_neg_integer() | 'undefined'}). % Group id for owner. -record(file_descriptor, diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index f5450f30af..9b44021872 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1310,13 +1310,20 @@ compare_arg(_Attr, _Val, _A) -> %% -> {ok, Res, log(), Cnt} | Error do_open(A) -> - L = #log{name = A#arg.name, - filename = A#arg.file, - size = A#arg.size, - head = mk_head(A#arg.head, A#arg.format), - mode = A#arg.mode, - version = A#arg.version}, - do_open2(L, A). + #arg{type = Type, format = Format, name = Name, head = Head0, + file = FName, repair = Repair, size = Size, mode = Mode, + version = V} = A, + Head = mk_head(Head0, Format), + case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of + {ok, Ret, Extra, FormatType, NoItems} -> + L = #log{name = Name, type = Type, format = Format, + filename = FName, size = Size, + format_type = FormatType, head = Head, mode = Mode, + version = V, extra = Extra}, + {ok, Ret, L, NoItems}; + Error -> + Error + end. mk_head({head, Term}, internal) -> {ok, term_to_binary(Term)}; mk_head({head, Bytes}, external) -> {ok, check_bytes(Bytes)}; @@ -1432,57 +1439,44 @@ do_inc_wrap_file(L) -> %%----------------------------------------------------------------- %% -> {ok, Reply, log(), Cnt} | Error %% Note: the header is always written, even if the log size is too small. -do_open2(L, #arg{type = halt, format = internal, name = Name, - file = FName, repair = Repair, size = Size, mode = Mode}) -> - case catch disk_log_1:int_open(FName, Repair, Mode, L#log.head) of +do_open2(halt, internal, Name, FName, Repair, Size, Mode, Head, _V) -> + case catch disk_log_1:int_open(FName, Repair, Mode, Head) of {ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, - {ok, {ok, Name}, L#log{format_type = halt_int, extra = Halt}, - NoItems}; + {ok, {ok, Name}, Halt, halt_int, NoItems}; {repaired, FdC, Rec, Bad, FileSize} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, {ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}}, - L#log{format_type = halt_int, extra = Halt}, - Rec}; + Halt, halt_int, Rec}; Error -> Error end; -do_open2(L, #arg{type = wrap, format = internal, size = {MaxB, MaxF}, - name = Name, repair = Repair, file = FName, mode = Mode, - version = V}) -> +do_open2(wrap, internal, Name, FName, Repair, Size, Mode, Head, V) -> + {MaxB, MaxF} = Size, case catch - disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of + disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of {ok, Handle, Cnt} -> - {ok, {ok, Name}, L#log{type = wrap, - format_type = wrap_int, - extra = Handle}, Cnt}; + {ok, {ok, Name}, Handle, wrap_int, Cnt}; {repaired, Handle, Rec, Bad, Cnt} -> {ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}}, - L#log{type = wrap, format_type = wrap_int, extra = Handle}, Cnt}; + Handle, wrap_int, Cnt}; Error -> Error end; -do_open2(L, #arg{type = halt, format = external, file = FName, name = Name, - size = Size, repair = Repair, mode = Mode}) -> - case catch disk_log_1:ext_open(FName, Repair, Mode, L#log.head) of +do_open2(halt, external, Name, FName, Repair, Size, Mode, Head, _V) -> + case catch disk_log_1:ext_open(FName, Repair, Mode, Head) of {ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, - {ok, {ok, Name}, - L#log{format_type = halt_ext, format = external, extra = Halt}, - NoItems}; + {ok, {ok, Name}, Halt, halt_ext, NoItems}; Error -> Error end; -do_open2(L, #arg{type = wrap, format = external, size = {MaxB, MaxF}, - name = Name, file = FName, repair = Repair, mode = Mode, - version = V}) -> +do_open2(wrap, external, Name, FName, Repair, Size, Mode, Head, V) -> + {MaxB, MaxF} = Size, case catch - disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of + disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of {ok, Handle, Cnt} -> - {ok, {ok, Name}, L#log{type = wrap, - format_type = wrap_ext, - extra = Handle, - format = external}, Cnt}; + {ok, {ok, Name}, Handle, wrap_ext, Cnt}; Error -> Error end. diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 6c0aea070f..3262d979ee 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -152,8 +152,8 @@ users = 0 :: non_neg_integer(), %% non-linked users filename :: file:filename(), %% real name of the file owners = [] :: [{pid(), boolean()}],%% [{pid, notify}] - type = halt :: dlog_type(), - format = internal :: dlog_format(), + type :: dlog_type(), + format :: dlog_format(), format_type :: dlog_format_type(), head = none, %% none | {head, H} | {M,F,A} %% called when wraplog wraps diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index 2be1efaf24..dcabeb5e49 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -459,17 +459,17 @@ init([]) -> no_trace end, + Ca = case init:get_argument(connect_all) of + {ok, [["false"]]} -> + false; + _ -> + true + end, S = #state{the_locker = start_the_locker(DoTrace), trace = T0, - the_registrar = start_the_registrar()}, - S1 = trace_message(S, {init, node()}, []), - - case init:get_argument(connect_all) of - {ok, [["false"]]} -> - {ok, S1#state{connect_all = false}}; - _ -> - {ok, S1#state{connect_all = true}} - end. + the_registrar = start_the_registrar(), + connect_all = Ca}, + {ok, trace_message(S, {init, node()}, [])}. %%----------------------------------------------------------------- %% Connection algorithm diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl index 848df13c39..e71f83f9d3 100644 --- a/lib/kernel/src/global_group.erl +++ b/lib/kernel/src/global_group.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. +%% Copyright Ericsson AB 1998-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -273,7 +273,7 @@ init([]) -> {ok, #state{publish_type = PT, group_publish_type = PubTpGrp, sync_state = synced, group_name = DefGroupName, no_contact = lists:sort(DefNodes), - other_grps = DefOther}} + other_grps = DefOther, connect_all = Ca}} end. diff --git a/lib/stdlib/include/erl_bits.hrl b/lib/stdlib/include/erl_bits.hrl index 8405a55d55..2a54587a17 100644 --- a/lib/stdlib/include/erl_bits.hrl +++ b/lib/stdlib/include/erl_bits.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -26,10 +26,10 @@ -type bt_unit() :: 1..256. -record(bittype, { - type :: bt_type(), - unit :: bt_unit(), %% element unit - sign :: bt_sign(), - endian :: bt_endian() + type :: bt_type() | 'undefined', + unit :: bt_unit() | 'undefined', %% element unit + sign :: bt_sign() | 'undefined', + endian :: bt_endian() | 'undefined' }). -record(bitdefault, { diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl index b93ce97cd3..cb19fe4175 100644 --- a/lib/stdlib/src/beam_lib.erl +++ b/lib/stdlib/src/beam_lib.erl @@ -867,7 +867,7 @@ mandatory_chunks() -> %%% can use it. %%% ==================================================================== --record(state, {crypto_key_f :: crypto_fun()}). +-record(state, {crypto_key_f :: crypto_fun() | 'undefined'}). -define(CRYPTO_KEY_SERVER, beam_lib__crypto_key_server). diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index d3124ac593..c8bba579cc 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -49,7 +49,8 @@ -define(DEFAULT_ENCODING, utf8). %% Epp state record. --record(epp, {file :: file:io_device(), %Current file +-record(epp, {file :: file:io_device() + | 'undefined', %Current file location=1, %Current location delta=0 :: non_neg_integer(), %Offset from Location (-file) name="" :: file:name(), %Current file name diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index 41b49f4a86..b8ce311c35 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -38,7 +38,7 @@ -record(state, {file :: file:filename(), module :: module(), forms_or_bin, - source :: source(), + source :: source() | 'undefined', n_errors :: non_neg_integer(), mode :: mode(), exports_main :: boolean(), @@ -49,9 +49,9 @@ -type emu_args() :: string(). -record(sections, {type, - shebang :: shebang(), - comment :: comment(), - emu_args :: emu_args(), + shebang :: shebang() | 'undefined', + comment :: comment() | 'undefined', + emu_args :: emu_args() | 'undefined', body}). -record(extract_options, {compile_source}). diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 92a0c29011..142aaa8688 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -107,11 +107,11 @@ -define(SET, sets:set). -record(state, {name, - strategy :: strategy(), + strategy :: strategy() | 'undefined', children = [] :: [child_rec()], - dynamics :: ?DICT(pid(), list()) | ?SET(pid()), - intensity :: non_neg_integer(), - period :: pos_integer(), + dynamics :: ?DICT(pid(), list()) | ?SET(pid()) | 'undefined', + intensity :: non_neg_integer() | 'undefined', + period :: pos_integer() | 'undefined', restarts = [], module, args}). -- cgit v1.2.3 From cc5a470ee25f7db55b586f4908e7e6b9057cafea Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 30 Sep 2015 16:15:26 +0200 Subject: stdlib: Refactor the supervisor module's state The field 'dynamics' in #state{} is a union of two opaque types, which is possibly problematic. Tagging the types should make the code safe for warnings from future versions of Dialyzer. --- lib/stdlib/src/supervisor.erl | 66 +++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 142aaa8688..23f3aaee1f 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -109,7 +109,9 @@ -record(state, {name, strategy :: strategy() | 'undefined', children = [] :: [child_rec()], - dynamics :: ?DICT(pid(), list()) | ?SET(pid()) | 'undefined', + dynamics :: {'dict', ?DICT(pid(), list())} + | {'set', ?SET(pid())} + | 'undefined', intensity :: non_neg_integer() | 'undefined', period :: pos_integer() | 'undefined', restarts = [], @@ -577,7 +579,7 @@ handle_cast({try_again_restart,Pid}, #state{children=[Child]}=State) when ?is_simple(State) -> RT = Child#child.restart_type, RPid = restarting(Pid), - case dynamic_child_args(RPid, dynamics_db(RT, State#state.dynamics)) of + case dynamic_child_args(RPid, RT, State#state.dynamics) of {ok, Args} -> {M, F, _} = Child#child.mfargs, NChild = Child#child{pid = RPid, mfargs = {M, F, Args}}, @@ -735,7 +737,7 @@ handle_start_child(Child, State) -> restart_child(Pid, Reason, #state{children = [Child]} = State) when ?is_simple(State) -> RestartType = Child#child.restart_type, - case dynamic_child_args(Pid, dynamics_db(RestartType, State#state.dynamics)) of + case dynamic_child_args(Pid, RestartType, State#state.dynamics) of {ok, Args} -> {M, F, _} = Child#child.mfargs, NChild = Child#child{pid = Pid, mfargs = {M, F, Args}}, @@ -812,14 +814,16 @@ restart(simple_one_for_one, Child, State) -> State#state.dynamics)), case do_start_child_i(M, F, A) of {ok, Pid} -> - NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, + DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = DynamicsDb}, {ok, NState}; {ok, Pid, _Extra} -> - NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, + DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = DynamicsDb}, {ok, NState}; {error, Error} -> - NState = State#state{dynamics = ?DICTS:store(restarting(OldPid), A, - Dynamics)}, + DynamicsDb = {dict, ?DICTS:store(restarting(OldPid), A, Dynamics)}, + NState = State#state{dynamics = DynamicsDb}, report_error(start_error, Error, Child, State#state.name), {try_again, NState} end; @@ -1102,31 +1106,32 @@ save_child(Child, #state{children = Children} = State) -> State#state{children = [Child |Children]}. save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) -> - State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))}; + DynamicsDb = dynamics_db(temporary, Dynamics), + State#state{dynamics = {set, ?SETS:add_element(Pid, DynamicsDb)}}; save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) -> - State#state{dynamics = ?DICTS:store(Pid, Args, dynamics_db(RestartType, Dynamics))}. + DynamicsDb = dynamics_db(RestartType, Dynamics), + State#state{dynamics = {dict, ?DICTS:store(Pid, Args, DynamicsDb)}}. dynamics_db(temporary, undefined) -> ?SETS:new(); dynamics_db(_, undefined) -> ?DICTS:new(); -dynamics_db(_,Dynamics) -> - Dynamics. - -dynamic_child_args(Pid, Dynamics) -> - case ?SETS:is_set(Dynamics) of - true -> - {ok, undefined}; - false -> - ?DICTS:find(Pid, Dynamics) - end. +dynamics_db(_, {_Tag, DynamicsDb}) -> + DynamicsDb. + +dynamic_child_args(_Pid, temporary, _DynamicsDb) -> + {ok, undefined}; +dynamic_child_args(Pid, _RT, {dict, DynamicsDb}) -> + ?DICTS:find(Pid, DynamicsDb); +dynamic_child_args(_Pid, _RT, undefined) -> + error. state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) -> NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)), - State#state{dynamics = NDynamics}; + State#state{dynamics = {set, NDynamics}}; state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) -> NDynamics = ?DICTS:erase(Pid, dynamics_db(RType, State#state.dynamics)), - State#state{dynamics = NDynamics}; + State#state{dynamics = {dict, NDynamics}}; state_del_child(Child, State) -> NChildren = del_child(Child#child.name, State#state.children), State#state{children = NChildren}. @@ -1160,19 +1165,19 @@ split_child(_, [], After) -> get_child(Name, State) -> get_child(Name, State, false). + get_child(Pid, State, AllowPid) when AllowPid, is_pid(Pid) -> get_dynamic_child(Pid, State); get_child(Name, State, _) -> lists:keysearch(Name, #child.name, State#state.children). get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) -> - DynamicsDb = dynamics_db(Child#child.restart_type, Dynamics), - case is_dynamic_pid(Pid, DynamicsDb) of + case is_dynamic_pid(Pid, Dynamics) of true -> {value, Child#child{pid=Pid}}; false -> RPid = restarting(Pid), - case is_dynamic_pid(RPid, DynamicsDb) of + case is_dynamic_pid(RPid, Dynamics) of true -> {value, Child#child{pid=RPid}}; false -> @@ -1183,13 +1188,12 @@ get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) -> end end. -is_dynamic_pid(Pid, Dynamics) -> - case ?SETS:is_set(Dynamics) of - true -> - ?SETS:is_element(Pid, Dynamics); - false -> - ?DICTS:is_key(Pid, Dynamics) - end. +is_dynamic_pid(Pid, {dict, Dynamics}) -> + ?DICTS:is_key(Pid, Dynamics); +is_dynamic_pid(Pid, {set, Dynamics}) -> + ?SETS:is_element(Pid, Dynamics); +is_dynamic_pid(_Pid, undefined) -> + false. replace_child(Child, State) -> Chs = do_replace_child(Child, State#state.children), -- cgit v1.2.3 From 794a6d1f2c904be72d4b4327a7c6faa759a25690 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 3 Sep 2015 17:05:53 +0200 Subject: ssh: Tests updated for ecdsa --- lib/ssh/test/ssh_basic_SUITE.erl | 39 ++++++++++++++++++++++ lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 | 5 +++ lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub | 1 + lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 | 6 ++++ lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub | 1 + lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 | 7 ++++ lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub | 1 + .../ssh_basic_SUITE_data/ssh_host_ecdsa_key256 | 5 +++ .../ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub | 1 + .../ssh_basic_SUITE_data/ssh_host_ecdsa_key384 | 6 ++++ .../ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub | 1 + .../ssh_basic_SUITE_data/ssh_host_ecdsa_key521 | 7 ++++ .../ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub | 1 + lib/ssh/test/ssh_protocol_SUITE.erl | 2 +- lib/ssh/test/ssh_test_lib.erl | 32 +++++++++++++++++- lib/ssh/test/ssh_to_openssh_SUITE.erl | 2 +- 16 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256 create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384 create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521 create mode 100644 lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 2ff7198bf8..7f1a64f094 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -77,6 +77,9 @@ all() -> appup_test, {group, dsa_key}, {group, rsa_key}, + {group, ecdsa_sha2_nistp256_key}, + {group, ecdsa_sha2_nistp384_key}, + {group, ecdsa_sha2_nistp521_key}, {group, dsa_pass_key}, {group, rsa_pass_key}, {group, internal_error}, @@ -89,6 +92,9 @@ all() -> groups() -> [{dsa_key, [], basic_tests()}, {rsa_key, [], basic_tests()}, + {ecdsa_sha2_nistp256_key, [], basic_tests()}, + {ecdsa_sha2_nistp384_key, [], basic_tests()}, + {ecdsa_sha2_nistp521_key, [], basic_tests()}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, {internal_error, [], [internal_error]} @@ -129,6 +135,39 @@ init_per_group(rsa_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:setup_rsa(DataDir, PrivDir), Config; +init_per_group(ecdsa_sha2_nistp256_key, Config) -> + case lists:member('ecdsa-sha2-nistp256', + ssh_transport:default_algorithms(public_key)) of + true -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_ecdsa("256", DataDir, PrivDir), + Config; + false -> + {skip, unsupported_pub_key} + end; +init_per_group(ecdsa_sha2_nistp384_key, Config) -> + case lists:member('ecdsa-sha2-nistp384', + ssh_transport:default_algorithms(public_key)) of + true -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_ecdsa("384", DataDir, PrivDir), + Config; + false -> + {skip, unsupported_pub_key} + end; +init_per_group(ecdsa_sha2_nistp521_key, Config) -> + case lists:member('ecdsa-sha2-nistp521', + ssh_transport:default_algorithms(public_key)) of + true -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_ecdsa("521", DataDir, PrivDir), + Config; + false -> + {skip, unsupported_pub_key} + end; init_per_group(rsa_pass_key, Config) -> DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 new file mode 100644 index 0000000000..4b1eb12eaa --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJfCaBKIIKhjbJl5F8BedqlXOQYDX5ba9Skypllmx/w+oAoGCCqGSM49 +AwEHoUQDQgAE49RbK2xQ/19ji3uDPM7uT4692LbwWF1TiaA9vUuebMGazoW/98br +N9xZu0L1AWwtEjs3kmJDTB7eJEGXnjUAcQ== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub new file mode 100644 index 0000000000..a0147e60fa --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPUWytsUP9fY4t7gzzO7k+Ovdi28FhdU4mgPb1LnmzBms6Fv/fG6zfcWbtC9QFsLRI7N5JiQ0we3iRBl541AHE= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 new file mode 100644 index 0000000000..4e8aa40959 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCYXb6OSAZyXRfLXOtMo43za197Hdc/T0YKjgQQjwDt6rlRwqTh7v7S +PV2kXwNGdWigBwYFK4EEACKhZANiAARN2khlJUOOIiwsWHEALwDieeZR96qL4pUd +ci7aeGaczdUK5jOA9D9zmBZtSYTfO8Cr7ekVghDlcWAIJ/BXcswgQwSEQ6wyfaTF +8FYfyr4l3u9IirsnyaFzeIgeoNis8Gw= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub new file mode 100644 index 0000000000..41e722e545 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBE3aSGUlQ44iLCxYcQAvAOJ55lH3qovilR1yLtp4ZpzN1QrmM4D0P3OYFm1JhN87wKvt6RWCEOVxYAgn8FdyzCBDBIRDrDJ9pMXwVh/KviXe70iKuyfJoXN4iB6g2KzwbA== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 new file mode 100644 index 0000000000..7196f46e97 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHbAgEBBEFMadoz4ckEcClfqXa2tiUuYkJdDfwq+/iFQcpt8ESuEd26IY/vm47Q +9UzbPkO4ou8xkNsQ3WvCRQBBWtn5O2kUU6AHBgUrgQQAI6GBiQOBhgAEAde5BRu5 +01/jS0jRk212xsb2DxPrxNpgp6IMCV8TA4Eps+8bSqHB091nLiBcP422HXYfuCd7 +XDjSs8ihcmhp0hCRASLqZR9EzW9W/SOt876May1Huj5X+WSO6RLe7vPn9vmf7kHf +pip6m7M7qp2qGgQ3q2vRwS2K/O6156ohiOlmuuFs +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub new file mode 100644 index 0000000000..8f059120bc --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ecdsa521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHXuQUbudNf40tI0ZNtdsbG9g8T68TaYKeiDAlfEwOBKbPvG0qhwdPdZy4gXD+Nth12H7gne1w40rPIoXJoadIQkQEi6mUfRM1vVv0jrfO+jGstR7o+V/lkjukS3u7z5/b5n+5B36YqepuzO6qdqhoEN6tr0cEtivzuteeqIYjpZrrhbA== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256 new file mode 100644 index 0000000000..2979ea88ed --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49 +AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s +VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub new file mode 100644 index 0000000000..85dc419345 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384 b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384 new file mode 100644 index 0000000000..fb1a862ded --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDArxbDfh3p1okrD9wQw6jJ4d4DdlBPD5GqXE8bIeRJiK41Sh40LgvPw +mkqEDSXK++CgBwYFK4EEACKhZANiAAScl43Ih2lWTDKrSox5ve5uiTXil4smsup3 +CfS1XPjKxgBAmlfBim8izbdrT0BFdQzz2joduNMtpt61wO4rGs6jm0UP7Kim9PC7 +Hneb/99fIYopdMH5NMnk60zGO1uZ2vc= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub new file mode 100644 index 0000000000..428d5fb7d7 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBJyXjciHaVZMMqtKjHm97m6JNeKXiyay6ncJ9LVc+MrGAECaV8GKbyLNt2tPQEV1DPPaOh240y2m3rXA7isazqObRQ/sqKb08Lsed5v/318hiil0wfk0yeTrTMY7W5na9w== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521 b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521 new file mode 100644 index 0000000000..3e51ec2ecd --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIB8O1BFkl2HQjQLRLonEZ97da/h39DMa9/0/hvPZWAI8gUPEQcHxRx +U7b09p3Zh+EBbMFq8+1ae9ds+ZTxE4WFSvKgBwYFK4EEACOhgYkDgYYABAAlWVjq +Bzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/ +vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5 +ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub new file mode 100644 index 0000000000..017a29f4da --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ecdsa_key521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAlWVjqBzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index d8e99799e2..406f8e5960 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -91,7 +91,7 @@ init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; [] end, start_std_daemon(Config, - [{preferred_algorithms, ssh_transport:supported_algorithms()} + [{preferred_algorithms, ssh:default_algorithms()} | Opts]); init_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index e16df6f959..6fa579d78d 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -286,6 +286,7 @@ setup_dsa(DataDir, UserDir) -> file:make_dir(System), file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")), file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")), +ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), setup_dsa_known_host(DataDir, UserDir), setup_dsa_auth_keys(DataDir, UserDir). @@ -294,10 +295,21 @@ setup_rsa(DataDir, UserDir) -> System = filename:join(UserDir, "system"), file:make_dir(System), file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")), - file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key.pub")), + file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")), +ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), setup_rsa_known_host(DataDir, UserDir), setup_rsa_auth_keys(DataDir, UserDir). +setup_ecdsa(Size, DataDir, UserDir) -> + file:copy(filename:join(DataDir, "id_ecdsa"++Size), filename:join(UserDir, "id_ecdsa")), + System = filename:join(UserDir, "system"), + file:make_dir(System), + file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size), filename:join(System, "ssh_host_ecdsa_key")), + file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")), +ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), + setup_ecdsa_known_host(Size, System, UserDir), + setup_ecdsa_auth_keys(Size, UserDir, UserDir). + clean_dsa(UserDir) -> del_dirs(filename:join(UserDir, "system")), file:delete(filename:join(UserDir,"id_dsa")), @@ -349,6 +361,11 @@ setup_rsa_known_host(SystemDir, UserDir) -> [{Key, _}] = public_key:ssh_decode(SshBin, public_key), setup_known_hosts(Key, UserDir). +setup_ecdsa_known_host(_Size, SystemDir, UserDir) -> + {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_ecdsa_key.pub")), + [{Key, _}] = public_key:ssh_decode(SshBin, public_key), + setup_known_hosts(Key, UserDir). + setup_known_hosts(Key, UserDir) -> {ok, Hostname} = inet:gethostname(), {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet), @@ -376,6 +393,19 @@ setup_rsa_auth_keys(Dir, UserDir) -> PKey = #'RSAPublicKey'{publicExponent = E, modulus = N}, setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir). +setup_ecdsa_auth_keys(Size, Dir, UserDir) -> + {ok, Pem} = file:read_file(filename:join(Dir, "id_ecdsa")), + ECDSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))), + #'ECPrivateKey'{publicKey = Q, + parameters = {namedCurve,Id0}} = ECDSA, + PKey = #'ECPoint'{point = Q}, + Id = case pubkey_cert_records:namedCurves(Id0) of + secp256r1 when Size=="256" -> <<"nistp256">>; + secp384r1 when Size=="384" -> <<"nistp384">>; + secp521r1 when Size=="521" -> <<"nistp521">> + end, + setup_auth_keys([{ {PKey,Id}, [{comment, "Test"}]}], UserDir). + setup_auth_keys(Keys, Dir) -> AuthKeys = public_key:ssh_encode(Keys, auth_keys), AuthKeysFile = filename:join(Dir, "authorized_keys"), diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index bc51ae0724..c0dee6a1d3 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -389,7 +389,7 @@ erlang_server_openssh_client_kexs(Config) when is_list(Config) -> {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {failfun, fun ssh_test_lib:failfun/2}, {preferred_algorithms, - [{kex,ssh_transport:supported_algorithms(kex)}]} + [{kex,ssh_transport:default_algorithms(kex)}]} ]), ct:sleep(500), -- cgit v1.2.3 From 437448c16ac18208838a638717309ee0294b004e Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 28 Sep 2015 12:10:06 +0200 Subject: public_key: Add ssh2 ECDSA pub key handling + test case Added encode/decode for ecdsa public keys in openssh and rfc4716 format. This is for the ssh public key algorithm ecdsa-sha2-*. --- lib/public_key/src/pubkey_ssh.erl | 49 +++++++++++++++++++--- lib/public_key/test/public_key_SUITE.erl | 32 +++++++++++++- .../test/public_key_SUITE_data/openssh_ecdsa_pub | 1 + .../test/public_key_SUITE_data/ssh2_ecdsa_pub | 6 +++ 4 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 lib/public_key/test/public_key_SUITE_data/openssh_ecdsa_pub create mode 100644 lib/public_key/test/public_key_SUITE_data/ssh2_ecdsa_pub (limited to 'lib') diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl index 7680d0ce59..26fbeb68ce 100644 --- a/lib/public_key/src/pubkey_ssh.erl +++ b/lib/public_key/src/pubkey_ssh.erl @@ -24,6 +24,8 @@ -export([decode/2, encode/2]). -define(UINT32(X), X:32/unsigned-big-integer). +-define(STRING(X), ?UINT32((size(X))), (X)/binary). + %% Max encoded line length is 72, but conformance examples use 68 %% Comment from rfc 4716: "The following are some examples of public %% key files that are compliant (note that the examples all wrap @@ -130,7 +132,13 @@ rfc4716_pubkey_decode(<>) when Type == <<"ecdsa-sha2-nistp256">>; + Type == <<"ecdsa-sha2-nistp384">>; + Type == <<"ecdsa-sha2-nistp521">> -> + {#'ECPoint'{point = Q}, Id}. openssh_decode(Bin, FileType) -> Lines = binary:split(Bin, <<"\n">>, [global]), @@ -186,12 +194,18 @@ do_openssh_decode(known_hosts = FileType, [Line | Lines], Acc) -> do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) -> case split_n(2, Line, []) of [KeyType, Base64Enc] when KeyType == <<"ssh-rsa">>; - KeyType == <<"ssh-dss">> -> + KeyType == <<"ssh-dss">>; + KeyType == <<"ecdsa-sha2-nistp256">>; + KeyType == <<"ecdsa-sha2-nistp384">>; + KeyType == <<"ecdsa-sha2-nistp521">> -> do_openssh_decode(FileType, Lines, [{openssh_pubkey_decode(KeyType, Base64Enc), []} | Acc]); [KeyType, Base64Enc | Comment0] when KeyType == <<"ssh-rsa">>; - KeyType == <<"ssh-dss">> -> + KeyType == <<"ssh-dss">>; + KeyType == <<"ecdsa-sha2-nistp256">>; + KeyType == <<"ecdsa-sha2-nistp384">>; + KeyType == <<"ecdsa-sha2-nistp521">> -> Comment = string:strip(string_decode(iolist_to_binary(Comment0)), right, $\n), do_openssh_decode(FileType, Lines, [{openssh_pubkey_decode(KeyType, Base64Enc), @@ -203,6 +217,7 @@ decode_comment([]) -> decode_comment(Comment) -> [{comment, string_decode(iolist_to_binary(Comment))}]. + openssh_pubkey_decode(<<"ssh-rsa">>, Base64Enc) -> <>, Base64Enc) -> #'Dss-Parms'{p = erlint(SizeP, P), q = erlint(SizeQ, Q), g = erlint(SizeG, G)}}; + +openssh_pubkey_decode(<<"ecdsa-sha2-", Id/binary>>, Base64Enc) -> + %% rfc5656#section-3.1 + <> + = base64:mime_decode(Base64Enc), + {#'ECPoint'{point = Q}, Id}; + openssh_pubkey_decode(KeyType, Base64Enc) -> {KeyType, base64:mime_decode(Base64Enc)}. + erlint(MPIntSize, MPIntValue) -> Bits= MPIntSize * 8, <> = MPIntValue, @@ -350,7 +375,9 @@ line_end(Comment) -> key_type(#'RSAPublicKey'{}) -> <<"ssh-rsa">>; key_type({_, #'Dss-Parms'{}}) -> - <<"ssh-dss">>. + <<"ssh-dss">>; +key_type({#'ECPoint'{}, Id}) -> + <<"ecdsa-sha2-",Id/binary>>. comma_list_encode([Option], []) -> Option; @@ -380,7 +407,13 @@ ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> PBin/binary, QBin/binary, GBin/binary, - YBin/binary>>. + YBin/binary>>; +ssh2_pubkey_encode({#'ECPoint'{point = Q}, Id}) -> + TypeStr = <<"ecdsa-sha2-", Id/binary>>, + StrLen = size(TypeStr), + <>. is_key_field(<<"ssh-dss">>) -> true; @@ -507,3 +540,9 @@ int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 -> list_to_binary(Ds); int_to_bin_neg(X,Ds) -> int_to_bin_neg(X bsr 8, [(X band 255)|Ds]). + + +string(X) when is_binary(X) -> + << ?STRING(X) >>; +string(X) -> + << ?STRING(list_to_binary(X)) >>. diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index 6f142c951c..5e677f31d6 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -49,8 +49,10 @@ groups() -> [{pem_decode_encode, [], [dsa_pem, rsa_pem, encrypted_pem, dh_pem, cert_pem, pkcs7_pem, pkcs10_pem]}, {ssh_public_key_decode_encode, [], - [ssh_rsa_public_key, ssh_dsa_public_key, ssh_rfc4716_rsa_comment, - ssh_rfc4716_dsa_comment, ssh_rfc4716_rsa_subject, ssh_known_hosts, + [ssh_rsa_public_key, ssh_dsa_public_key, ssh_ecdsa_public_key, + ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment, + ssh_rfc4716_rsa_subject, + ssh_known_hosts, ssh_auth_keys, ssh1_known_hosts, ssh1_auth_keys, ssh_openssh_public_key_with_comment, ssh_openssh_public_key_long_header]}, {sign_verify, [], [rsa_sign_verify, dsa_sign_verify]} @@ -290,6 +292,32 @@ ssh_dsa_public_key(Config) when is_list(Config) -> [{PubKey, Attributes2}] = public_key:ssh_decode(EncodedOpenSsh, public_key). +%%-------------------------------------------------------------------- + +ssh_ecdsa_public_key() -> + [{doc, "ssh ecdsa public key decode/encode"}]. +ssh_ecdsa_public_key(Config) when is_list(Config) -> + Datadir = ?config(data_dir, Config), + + {ok, ECDSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_ecdsa_pub")), + [{PubKey, Attributes1}] = public_key:ssh_decode(ECDSARawSsh2, public_key), + [{PubKey, Attributes1}] = public_key:ssh_decode(ECDSARawSsh2, rfc4716_public_key), + + {ok, ECDSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_ecdsa_pub")), + [{PubKey, Attributes2}] = public_key:ssh_decode(ECDSARawOpenSsh, public_key), + [{PubKey, Attributes2}] = public_key:ssh_decode(ECDSARawOpenSsh, openssh_public_key), + + %% Can not check EncodedSSh == ECDSARawSsh2 and EncodedOpenSsh + %% = ECDSARawOpenSsh as line breakpoints may differ + + EncodedSSh = public_key:ssh_encode([{PubKey, Attributes1}], rfc4716_public_key), + EncodedOpenSsh = public_key:ssh_encode([{PubKey, Attributes2}], openssh_public_key), + + [{PubKey, Attributes1}] = + public_key:ssh_decode(EncodedSSh, public_key), + [{PubKey, Attributes2}] = + public_key:ssh_decode(EncodedOpenSsh, public_key). + %%-------------------------------------------------------------------- ssh_rfc4716_rsa_comment() -> [{doc, "Test comment header and rsa key"}]. diff --git a/lib/public_key/test/public_key_SUITE_data/openssh_ecdsa_pub b/lib/public_key/test/public_key_SUITE_data/openssh_ecdsa_pub new file mode 100644 index 0000000000..a49b4264b8 --- /dev/null +++ b/lib/public_key/test/public_key_SUITE_data/openssh_ecdsa_pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIJrVlKYIT+MlxxRx5BFXisHHkcGMAAKv2dguUeOsutsYyzs9JAczvl6c+Sypra5+qOi2LHPXw6GGluuXcOssOM= uabhnil@elxadlj3q32 diff --git a/lib/public_key/test/public_key_SUITE_data/ssh2_ecdsa_pub b/lib/public_key/test/public_key_SUITE_data/ssh2_ecdsa_pub new file mode 100644 index 0000000000..702e5c4fde --- /dev/null +++ b/lib/public_key/test/public_key_SUITE_data/ssh2_ecdsa_pub @@ -0,0 +1,6 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Comment: "256-bit ECDSA, converted by uabhnil@elxadlj3q32 from OpenSSH" +AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIJrVlKYIT+MlxxRx5 +BFXisHHkcGMAAKv2dguUeOsutsYyzs9JAczvl6c+Sypra5+qOi2LHPXw6GGluuXcOssOM= + +---- END SSH2 PUBLIC KEY ---- -- cgit v1.2.3 From 23bdf367342d15cb3e9064df82faa285d021202d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 28 Sep 2015 13:09:01 +0200 Subject: ssh: ECDSA public key implemented --- lib/ssh/src/ssh_auth.erl | 84 ++++++++++++++++++++++------------ lib/ssh/src/ssh_auth.hrl | 2 - lib/ssh/src/ssh_connection_handler.erl | 12 ++--- lib/ssh/src/ssh_file.erl | 63 +++++++++++++++---------- lib/ssh/src/ssh_message.erl | 32 +++++++++++-- lib/ssh/src/ssh_transport.erl | 64 +++++++++++++++++++------- 6 files changed, 174 insertions(+), 83 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 726f52132f..0c16e19701 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -31,8 +31,7 @@ -export([publickey_msg/1, password_msg/1, keyboard_interactive_msg/1, service_request_msg/1, init_userauth_request_msg/1, userauth_request_msg/1, handle_userauth_request/3, - handle_userauth_info_request/3, handle_userauth_info_response/2, - default_public_key_algorithms/0 + handle_userauth_info_request/3, handle_userauth_info_response/2 ]). %%-------------------------------------------------------------------- @@ -42,27 +41,29 @@ publickey_msg([Alg, #ssh{user = User, session_id = SessionId, service = Service, opts = Opts} = Ssh]) -> - Hash = sha, %% Maybe option?! KeyCb = proplists:get_value(key_cb, Opts, ssh_file), - case KeyCb:user_key(Alg, Opts) of {ok, Key} -> StrAlgo = algorithm_string(Alg), - PubKeyBlob = encode_public_key(Key), - SigData = build_sig_data(SessionId, - User, Service, PubKeyBlob, StrAlgo), - Sig = ssh_transport:sign(SigData, Hash, Key), - SigBlob = list_to_binary([?string(StrAlgo), ?binary(Sig)]), - ssh_transport:ssh_packet( - #ssh_msg_userauth_request{user = User, - service = Service, - method = "publickey", - data = [?TRUE, - ?string(StrAlgo), - ?binary(PubKeyBlob), - ?binary(SigBlob)]}, - Ssh); + case encode_public_key(StrAlgo, Key) of + not_ok -> + not_ok; + PubKeyBlob -> + SigData = build_sig_data(SessionId, + User, Service, PubKeyBlob, StrAlgo), + Sig = ssh_transport:sign(SigData, Hash, Key), + SigBlob = list_to_binary([?string(StrAlgo), ?binary(Sig)]), + ssh_transport:ssh_packet( + #ssh_msg_userauth_request{user = User, + service = Service, + method = "publickey", + data = [?TRUE, + ?string(StrAlgo), + ?binary(PubKeyBlob), + ?binary(SigBlob)]}, + Ssh) + end; _Error -> not_ok end. @@ -121,7 +122,7 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) -> Algs = proplists:get_value(public_key, proplists:get_value(preferred_algorithms, Opts, []), - default_public_key_algorithms()), + ssh_transport:default_algorithms(public_key)), Prefs = method_preference(Algs), ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User, userauth_preference = Prefs, @@ -355,8 +356,6 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{}, language = "en"}). -default_public_key_algorithms() -> ?PREFERRED_PK_ALGS. - %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -431,10 +430,13 @@ build_sig_data(SessionId, User, Service, KeyBlob, Alg) -> ?binary(KeyBlob)], list_to_binary(Sig). -algorithm_string('ssh-rsa') -> - "ssh-rsa"; -algorithm_string('ssh-dss') -> - "ssh-dss". +algorithm_string('ssh-rsa') -> "ssh-rsa"; +algorithm_string('ssh-dss') -> "ssh-dss"; +algorithm_string('ecdsa-sha2-nistp256') -> "ecdsa-sha2-nistp256"; +algorithm_string('ecdsa-sha2-nistp384') -> "ecdsa-sha2-nistp384"; +algorithm_string('ecdsa-sha2-nistp521') -> "ecdsa-sha2-nistp521". + + decode_keyboard_interactive_prompts(_NumPrompts, Data) -> ssh_message:decode_keyboard_interactive_prompts(Data, []). @@ -497,11 +499,35 @@ decode_public_key_v2(<> , "ssh-dss") -> {ok, {Y, #'Dss-Parms'{p = P, q = Q, g = G}}}; - +decode_public_key_v2(<> for example + ?UINT32(Len2), Blob:Len2/binary>>, + Curve) -> + Id = + case Curve of + "ecdsa-sha2-nistp256" -> <<"nistp256">>; + "ecdsa-sha2-nistp384" -> <<"nistp384">>; + "ecdsa-sha2-nistp521" -> <<"nistp521">> + end, + {ok, {#'ECPoint'{point=Blob}, Id}}; decode_public_key_v2(_, _) -> {error, bad_format}. -encode_public_key(#'RSAPrivateKey'{publicExponent = E, modulus = N}) -> +encode_public_key("ssh-rsa", #'RSAPrivateKey'{publicExponent = E, modulus = N}) -> ssh_bits:encode(["ssh-rsa",E,N], [string,mpint,mpint]); -encode_public_key(#'DSAPrivateKey'{p = P, q = Q, g = G, y = Y}) -> - ssh_bits:encode(["ssh-dss",P,Q,G,Y], [string,mpint,mpint,mpint,mpint]). +encode_public_key("ssh-dss", #'DSAPrivateKey'{p = P, q = Q, g = G, y = Y}) -> + ssh_bits:encode(["ssh-dss",P,Q,G,Y], [string,mpint,mpint,mpint,mpint]); +encode_public_key("ecdsa-sha2-"++Curve, #'ECPrivateKey'{parameters = Params, + publicKey = Pub}) -> + Id = ecdsa_id(Params), + if + Id =/= Curve -> + not_ok; + true -> + ssh_bits:encode(["ecdsa-sha2-"++Id, Id, Pub], + [string, string, binary]) + end. + +ecdsa_id({namedCurve,?'secp256r1'}) -> "nistp256"; +ecdsa_id({namedCurve,?'secp384r1'}) -> "nistp384"; +ecdsa_id({namedCurve,?'secp521r1'}) -> "nistp521". diff --git a/lib/ssh/src/ssh_auth.hrl b/lib/ssh/src/ssh_auth.hrl index 71f222f6d7..5197a42fa4 100644 --- a/lib/ssh/src/ssh_auth.hrl +++ b/lib/ssh/src/ssh_auth.hrl @@ -24,8 +24,6 @@ -define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password"). --define(PREFERRED_PK_ALGS, ['ssh-rsa','ssh-dss']). - -define(SSH_MSG_USERAUTH_REQUEST, 50). -define(SSH_MSG_USERAUTH_FAILURE, 51). -define(SSH_MSG_USERAUTH_SUCCESS, 52). diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index ee1dd5c9ce..7fb86c1108 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1266,9 +1266,9 @@ supported_host_keys(client, _, Options) -> proplists:get_value(preferred_algorithms,Options,[]) ) of undefined -> - ssh_auth:default_public_key_algorithms(); + ssh_transport:default_algorithms(public_key); L -> - L -- (L--ssh_auth:default_public_key_algorithms()) + L -- (L--ssh_transport:default_algorithms(public_key)) end of [] -> @@ -1280,21 +1280,17 @@ supported_host_keys(client, _, Options) -> {stop, {shutdown, Reason}} end; supported_host_keys(server, KeyCb, Options) -> - Algs= [atom_to_list(A) || A <- proplists:get_value(public_key, proplists:get_value(preferred_algorithms,Options,[]), - ssh_auth:default_public_key_algorithms() + ssh_transport:default_algorithms(public_key) ), available_host_key(KeyCb, A, Options) - ], - Algs. - + ]. %% Alg :: atom() available_host_key(KeyCb, Alg, Opts) -> element(1, catch KeyCb:host_key(Alg, Opts)) == ok. - send_msg(Msg, #state{socket = Socket, transport_cb = Transport}) -> Transport:send(Socket, Msg). diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index b98a8a8410..4e6d58cbff 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -52,8 +52,20 @@ host_key(Algorithm, Opts) -> %% so probably we could hardcod Password = ignore, but %% we keep it as an undocumented option for now. Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore), - decode(File, Password). - + case decode(File, Password) of + {ok,Key} -> + case {Key,Algorithm} of + {#'RSAPrivateKey'{}, 'ssh-rsa'} -> {ok,Key}; + {#'DSAPrivateKey'{}, 'ssh-dss'} -> {ok,Key}; + {#'ECPrivateKey'{parameters = {namedCurve, ?'secp256r1'}}, 'ecdsa-sha2-nistp256'} -> {ok,Key}; + {#'ECPrivateKey'{parameters = {namedCurve, ?'secp384r1'}}, 'ecdsa-sha2-nistp384'} -> {ok,Key}; + {#'ECPrivateKey'{parameters = {namedCurve, ?'secp521r1'}}, 'ecdsa-sha2-nistp521'} -> {ok,Key}; + _ -> + {error,bad_keytype_in_file} + end; + Other -> + Other + end. is_auth_key(Key, User,Opts) -> case lookup_user_key(Key, User, Opts) of @@ -81,16 +93,15 @@ user_key(Algorithm, Opts) -> %% Internal functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -file_base_name('ssh-rsa') -> - "ssh_host_rsa_key"; -file_base_name('ssh-dss') -> - "ssh_host_dsa_key"; -file_base_name(_) -> - "ssh_host_key". +file_base_name('ssh-rsa' ) -> "ssh_host_rsa_key"; +file_base_name('ssh-dss' ) -> "ssh_host_dsa_key"; +file_base_name('ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key"; +file_base_name('ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key"; +file_base_name('ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key"; +file_base_name(_ ) -> "ssh_host_key". decode(File, Password) -> - try - {ok, decode_ssh_file(read_ssh_file(File), Password)} + try {ok, decode_ssh_file(read_ssh_file(File), Password)} catch throw:Reason -> {error, Reason}; @@ -215,20 +226,18 @@ do_lookup_host_key(KeyToMatch, Host, Alg, Opts) -> Error -> Error end. -identity_key_filename('ssh-dss') -> - "id_dsa"; -identity_key_filename('ssh-rsa') -> - "id_rsa". - -identity_pass_phrase("ssh-dss") -> - dsa_pass_phrase; -identity_pass_phrase('ssh-dss') -> - dsa_pass_phrase; -identity_pass_phrase('ssh-rsa') -> - rsa_pass_phrase; -identity_pass_phrase("ssh-rsa") -> - rsa_pass_phrase. - +identity_key_filename('ssh-dss' ) -> "id_dsa"; +identity_key_filename('ssh-rsa' ) -> "id_rsa"; +identity_key_filename('ecdsa-sha2-nistp256') -> "id_ecdsa"; +identity_key_filename('ecdsa-sha2-nistp384') -> "id_ecdsa"; +identity_key_filename('ecdsa-sha2-nistp521') -> "id_ecdsa". + +identity_pass_phrase("ssh-dss" ) -> dsa_pass_phrase; +identity_pass_phrase("ssh-rsa" ) -> rsa_pass_phrase; +identity_pass_phrase("ecdsa-sha2-"++_) -> ecdsa_pass_phrase; +identity_pass_phrase(P) when is_atom(P) -> + identity_pass_phrase(atom_to_list(P)). + lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) -> case io:get_line(Fd, '') of eof -> @@ -267,6 +276,12 @@ key_match(#'RSAPublicKey'{}, 'ssh-rsa') -> true; key_match({_, #'Dss-Parms'{}}, 'ssh-dss') -> true; +key_match({#'ECPoint'{},<<"nistp256">>}, 'ecdsa-sha2-nistp256') -> + true; +key_match({#'ECPoint'{},<<"nistp384">>}, 'ecdsa-sha2-nistp384') -> + true; +key_match({#'ECPoint'{},<<"nistp521">>}, 'ecdsa-sha2-nistp521') -> + true; key_match(_, _) -> false. diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index cb1dcb67c5..cfa11903fb 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -564,9 +564,11 @@ decode_kex_init(<>, Acc, N) -> decode_sign(<>) -> Signature. + decode_host_key(<>) -> decode_host_key(Alg, Rest). + decode_host_key(<<"ssh-rsa">>, <>) -> #'RSAPublicKey'{publicExponent = E, @@ -579,19 +581,43 @@ decode_host_key(<<"ssh-dss">>, ?UINT32(Len3), Y:Len3/big-signed-integer-unit:8>>) -> {Y, #'Dss-Parms'{p = P, q = Q, - g = G}}. + g = G}}; + +decode_host_key(<<"ecdsa-sha2-",Id/binary>>, + <> for example + ?UINT32(Len1), Blob:Len1/binary>>) -> + {#'ECPoint'{point=Blob}, Id}. + encode_host_key(#'RSAPublicKey'{modulus = N, publicExponent = E}) -> ssh_bits:encode(["ssh-rsa", E, N], [string, mpint, mpint]); encode_host_key({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> ssh_bits:encode(["ssh-dss", P, Q, G, Y], [string, mpint, mpint, mpint, mpint]); +encode_host_key({#'ECPoint'{point = Q}, Id}) -> + ssh_bits:encode([<<"ecdsa-sha2-",Id/binary>>,Id,Q], [binary,binary,binary]); + encode_host_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) -> ssh_bits:encode(["ssh-rsa", E, N], [string, mpint, mpint]); encode_host_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) -> ssh_bits:encode(["ssh-dss", P, Q, G, Y], - [string, mpint, mpint, mpint, mpint]). + [string, mpint, mpint, mpint, mpint]); +encode_host_key(#'ECPrivateKey'{parameters = Params, %{namedCurve,{1,2,840,10045,3,1,7}}, + publicKey = Pub}) -> + Id = ecdsa_id(Params), + ssh_bits:encode(["ecdsa-sha2-"++Id, Id, Pub], + [string, string, binary]). + + encode_sign(#'RSAPrivateKey'{}, Signature) -> ssh_bits:encode(["ssh-rsa", Signature],[string, binary]); encode_sign(#'DSAPrivateKey'{}, Signature) -> - ssh_bits:encode(["ssh-dss", Signature],[string, binary]). + ssh_bits:encode(["ssh-dss", Signature],[string, binary]); +encode_sign(#'ECPrivateKey'{parameters = Params}, Signature) -> + Id = "ecdsa-sha2-" ++ ecdsa_id(Params), + ssh_bits:encode([Id, Signature],[string, binary]). + + +ecdsa_id({namedCurve,?'secp256r1'}) -> "nistp256"; +ecdsa_id({namedCurve,?'secp384r1'}) -> "nistp384"; +ecdsa_id({namedCurve,?'secp521r1'}) -> "nistp521". diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 840564e246..8030c1dc25 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -65,7 +65,8 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()]. algo_classes() -> [kex, public_key, cipher, mac, compression]. -default_algorithms(kex) -> supported_algorithms(kex, []); %% Just to have a call... +default_algorithms(kex) -> + supported_algorithms(kex, []); %% Just to have a call to supported_algorithms/2 default_algorithms(Alg) -> supported_algorithms(Alg). @@ -84,7 +85,14 @@ supported_algorithms(kex) -> {'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]} ]); supported_algorithms(public_key) -> - ssh_auth:default_public_key_algorithms(); + select_crypto_supported( + [{'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]}, + {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {ec_curve,secp384r1}]}, + {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {ec_curve,secp521r1}]}, + {'ssh-rsa', [{public_keys,rsa}, {hashs,sha} ]}, + {'ssh-dss', [{public_keys,dss}, {hashs,sha} ]} + ]); + supported_algorithms(cipher) -> same( select_crypto_supported( @@ -640,33 +648,40 @@ get_host_key(SSH) -> #ssh{key_cb = Mod, opts = Opts, algorithms = ALG} = SSH, case Mod:host_key(ALG#alg.hkey, Opts) of - {ok, #'RSAPrivateKey'{} = Key} -> - Key; - {ok, #'DSAPrivateKey'{} = Key} -> - Key; + {ok, #'RSAPrivateKey'{} = Key} -> Key; + {ok, #'DSAPrivateKey'{} = Key} -> Key; + {ok, #'ECPrivateKey'{} = Key} -> Key; Result -> exit({error, {Result, unsupported_key_type}}) end. -sign_host_key(_Ssh, #'RSAPrivateKey'{} = Private, H) -> - Hash = sha, - _Signature = sign(H, Hash, Private); -sign_host_key(_Ssh, #'DSAPrivateKey'{} = Private, H) -> - Hash = sha, - _RawSignature = sign(H, Hash, Private). +sign_host_key(_Ssh, PrivateKey, H) -> + sign(H, sign_host_key_sha(PrivateKey), PrivateKey). + +sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve, ?'secp256r1'}}) -> sha256; +sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve, ?'secp384r1'}}) -> sha384; +sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve, ?'secp521r1'}}) -> sha512; +sign_host_key_sha(#'RSAPrivateKey'{}) -> sha; +sign_host_key_sha(#'DSAPrivateKey'{}) -> sha. + verify_host_key(SSH, PublicKey, Digest, Signature) -> - case verify(Digest, sha, Signature, PublicKey) of + case verify(Digest, host_key_sha(PublicKey), Signature, PublicKey) of false -> {error, bad_signature}; true -> known_host_key(SSH, PublicKey, public_algo(PublicKey)) end. -public_algo(#'RSAPublicKey'{}) -> - 'ssh-rsa'; -public_algo({_, #'Dss-Parms'{}}) -> - 'ssh-dss'. +host_key_sha(#'RSAPublicKey'{}) -> sha; +host_key_sha({_, #'Dss-Parms'{}}) -> sha; +host_key_sha({#'ECPoint'{},Id}) -> sha(list_to_atom(binary_to_list(Id))). + + +public_algo(#'RSAPublicKey'{}) -> 'ssh-rsa'; +public_algo({_, #'Dss-Parms'{}}) -> 'ssh-dss'; +public_algo({#'ECPoint'{},Id}) -> list_to_atom("ecdsa-sha2-" ++ binary_to_list(Id)). + accepted_host(Ssh, PeerName, Opts) -> case proplists:get_value(silently_accept_hosts, Opts, false) of @@ -906,6 +921,10 @@ sign(SigData, Hash, #'DSAPrivateKey'{} = Key) -> DerSignature = public_key:sign(SigData, Hash, Key), #'Dss-Sig-Value'{r = R, s = S} = public_key:der_decode('Dss-Sig-Value', DerSignature), <>; +sign(SigData, Hash, Key = #'ECPrivateKey'{}) -> + DerEncodedSign = public_key:sign(SigData, Hash, Key), + #'ECDSA-Sig-Value'{r=R, s=S} = public_key:der_decode('ECDSA-Sig-Value', DerEncodedSign), + ssh_bits:encode([R,S], [mpint,mpint]); sign(SigData, Hash, Key) -> public_key:sign(SigData, Hash, Key). @@ -913,6 +932,17 @@ verify(PlainText, Hash, Sig, {_, #'Dss-Parms'{}} = Key) -> <> = Sig, Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}), public_key:verify(PlainText, Hash, Signature, Key); +verify(PlainText, Hash, Sig, {ECPoint=#'ECPoint'{}, Param}) -> + C = case Param of + <<"nistp256">> -> {namedCurve, ?'secp256r1'}; + <<"nistp384">> -> {namedCurve, ?'secp384r1'}; + <<"nistp521">> -> {namedCurve, ?'secp521r1'} + end, + <> = Sig, + Sval = #'ECDSA-Sig-Value'{r=R, s=S}, + DerEncodedSig = public_key:der_encode('ECDSA-Sig-Value',Sval), + public_key:verify(PlainText, Hash, DerEncodedSig, {ECPoint,C}); verify(PlainText, Hash, Sig, Key) -> public_key:verify(PlainText, Hash, Sig, Key). -- cgit v1.2.3 From 4a356cf070e197cec375b562891af8fe9634c306 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 1 Oct 2015 12:10:03 +0200 Subject: ssh: document new pub key algorithms --- lib/ssh/doc/src/ssh.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 93bea09e4e..c7a09d65a8 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -40,7 +40,7 @@ For application dependencies see ssh(6) Supported SSH version is 2.0. - Supported public key algorithms: ssh-rsa and ssh-dss. + Supported public key algorithms:ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa and ssh-dss. Supported MAC algorithms: hmac-sha2-512, hmac-sha2-256 and hmac-sha1. Supported MAC algorithms: hmac-sha2-256 and hmac-sha1. Supported encryption algorithms: aes256-ctr, aes192-ctr, aes128-ctr, aes128-cb and 3des-cbc. -- cgit v1.2.3 From 84df3d4d0278e21a36a453bfee94799f0df67c2a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 6 Oct 2015 21:18:23 +0200 Subject: ssh: Option max_channels added. It actually counts the number of subsystem alive. Allocating a channel does not consume any resources (except some cpu cycles), but the subsystem start spawns processes. --- lib/ssh/doc/src/ssh.xml | 9 +++++ lib/ssh/src/ssh.erl | 4 ++ lib/ssh/src/ssh_connection.erl | 27 ++++++++++--- lib/ssh/test/ssh_connection_SUITE.erl | 75 ++++++++++++++++++++++++++++++++++- 4 files changed, 108 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index cf5e8f1aff..37ed016099 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -501,6 +501,15 @@ kex is implicit but public_key is set explicitly.

+ + +

The maximum number of channels with active remote subsystem that are accepted for + each connection to this daemon

+

By default, this option is not set. This means that the number is not limited. +

+
+ +

If set to false (the default value), only one login is handled at a time. diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 132de71aed..ee44324c12 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -385,6 +385,8 @@ handle_option([{rekey_limit, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{max_sessions, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{max_channels, _} = Opt|Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{negotiation_timeout, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{parallel_login, _} = Opt|Rest], SocketOptions, SshOptions) -> @@ -443,6 +445,8 @@ handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value Opt; handle_ssh_option({max_sessions, Value} = Opt) when is_integer(Value), Value>0 -> Opt; +handle_ssh_option({max_channels, Value} = Opt) when is_integer(Value), Value>0 -> + Opt; handle_ssh_option({negotiation_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; handle_ssh_option({parallel_login, Value} = Opt) when Value==true ; Value==false -> diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl index 64d2113125..266c64fd4f 100644 --- a/lib/ssh/src/ssh_connection.erl +++ b/lib/ssh/src/ssh_connection.erl @@ -935,14 +935,27 @@ encode_ip(Addr) when is_list(Addr) -> end end. -start_channel(Cb, Id, Args, SubSysSup) -> - start_channel(Cb, Id, Args, SubSysSup, undefined). +start_channel(Cb, Id, Args, SubSysSup, Opts) -> + start_channel(Cb, Id, Args, SubSysSup, undefined, Opts). -start_channel(Cb, Id, Args, SubSysSup, Exec) -> +start_channel(Cb, Id, Args, SubSysSup, Exec, Opts) -> ChildSpec = child_spec(Cb, Id, Args, Exec), ChannelSup = ssh_subsystem_sup:channel_supervisor(SubSysSup), + assert_limit_num_channels_not_exceeded(ChannelSup, Opts), ssh_channel_sup:start_child(ChannelSup, ChildSpec). +assert_limit_num_channels_not_exceeded(ChannelSup, Opts) -> + MaxNumChannels = proplists:get_value(max_channels, Opts, infinity), + NumChannels = length([x || {_,_,worker,[ssh_channel]} <- + supervisor:which_children(ChannelSup)]), + if + %% Note that NumChannels is BEFORE starting a new one + NumChannels < MaxNumChannels -> + ok; + true -> + throw(max_num_channels_exceeded) + end. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -998,9 +1011,11 @@ child_spec(Callback, Id, Args, Exec) -> start_cli(#connection{cli_spec = no_cli}, _) -> {error, cli_disabled}; -start_cli(#connection{cli_spec = {CbModule, Args}, exec = Exec, +start_cli(#connection{options = Options, + cli_spec = {CbModule, Args}, + exec = Exec, sub_system_supervisor = SubSysSup}, ChannelId) -> - start_channel(CbModule, ChannelId, Args, SubSysSup, Exec). + start_channel(CbModule, ChannelId, Args, SubSysSup, Exec, Options). start_subsytem(BinName, #connection{options = Options, sub_system_supervisor = SubSysSup}, @@ -1008,7 +1023,7 @@ start_subsytem(BinName, #connection{options = Options, Name = binary_to_list(BinName), case check_subsystem(Name, Options) of {Callback, Opts} when is_atom(Callback), Callback =/= none -> - start_channel(Callback, ChannelId, Opts, SubSysSup); + start_channel(Callback, ChannelId, Opts, SubSysSup, Options); {Other, _} when Other =/= none -> {error, legacy_option_not_supported} end. diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index fbcf06290a..37bba07440 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -48,7 +48,8 @@ all() -> gracefull_invalid_long_start, gracefull_invalid_long_start_no_nl, stop_listener, - start_subsystem_on_closed_channel + start_subsystem_on_closed_channel, + max_channels_option ]. groups() -> [{openssh, [], payload() ++ ptty()}]. @@ -605,6 +606,78 @@ start_subsystem_on_closed_channel(Config) -> ssh:close(ConnectionRef), ssh:stop_daemon(Pid). +%%-------------------------------------------------------------------- +max_channels_option() -> + [{doc, "Test max_channels option"}]. + +max_channels_option(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, UserDir}, + {password, "morot"}, + {max_channels, 3}, + {subsystems, [{"echo_n", {ssh_echo_server, [4000000]}}]} + ]), + + ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, true}, + {user_dir, UserDir}]), + + {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId2} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId3} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId4} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, ChannelId5} = ssh_connection:session_channel(ConnectionRef, infinity), + {ok, _ChannelId6} = ssh_connection:session_channel(ConnectionRef, infinity), + + %%%---- shell + ok = ssh_connection:shell(ConnectionRef,ChannelId0), + receive + {ssh_cm,ConnectionRef, {data, ChannelId0, 0, <<"Eshell",_/binary>>}} -> + ok + after 5000 -> + ct:fail("CLI Timeout") + end, + + %%%---- subsystem "echo_n" + success = ssh_connection:subsystem(ConnectionRef, ChannelId1, "echo_n", infinity), + + %%%---- exec #1 + success = ssh_connection:exec(ConnectionRef, ChannelId2, "testing1.\n", infinity), + receive + {ssh_cm, ConnectionRef, {data, ChannelId2, 0, <<"testing1",_/binary>>}} -> + ok + after 5000 -> + ct:fail("Exec #1 Timeout") + end, + + %%%---- ptty + success = ssh_connection:ptty_alloc(ConnectionRef, ChannelId3, []), + + %%%---- exec #2 + failure = ssh_connection:exec(ConnectionRef, ChannelId4, "testing2.\n", infinity), + + %%%---- close the shell + ok = ssh_connection:send(ConnectionRef, ChannelId0, "exit().\n", 5000), + + %%%---- exec #3 + success = ssh_connection:exec(ConnectionRef, ChannelId5, "testing3.\n", infinity), + receive + {ssh_cm, ConnectionRef, {data, ChannelId5, 0, <<"testing3",_/binary>>}} -> + ok + after 5000 -> + ct:fail("Exec #3 Timeout") + end, + + ssh:close(ConnectionRef), + ssh:stop_daemon(Pid). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- -- cgit v1.2.3 From e5d5c462c09b631af417347154a04378f6186778 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 8 Oct 2015 19:05:43 +0200 Subject: ssh: update vsn.mk --- lib/ssh/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index b305eedcdc..997c544c45 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.1 +SSH_VSN = 4.1.1 APP_VSN = "ssh-$(SSH_VSN)" -- cgit v1.2.3 From 93f5844185a459cbf9efc3843919c463a2eef0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 8 Oct 2015 13:04:40 +0200 Subject: Teach erlang:is_builtin/3 that erlang:apply/3 is built-in erlang:is_builtin(erlang, apply, 3) returns 'false'. That seems to be an oversight in the implementation of erlang:is_builtin/3 rather than a conscious design decision. Part of apply/3 is implemented in C (as a special instruction), and part of it in Erlang (only used if apply/3 is used recursively). That makes apply/3 special compared to all other BIFs. From the viewpoint of the user, apply/3 is a built-in function, since it cannot possibly be implemented in pure Erlang. Noticed-by: Stavros Aronis --- lib/tools/test/xref_SUITE.erl | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index ad47b31443..71c8b1a277 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -1151,17 +1151,13 @@ read_expected(Version) -> {POS8+4,{FF,{a,b,1}}}, {POS8+4,{FF,{erlang,apply,2}}}, {POS8+5,{FF,{erlang,apply,2}}}, - {POS8+6,{FF,{erlang,apply,3}}}, {POS8+6,{FF,{m,f,1}}}, - {POS8+7,{FF,{erlang,apply,3}}}, - {POS9+1,{FF,{erlang,apply,3}}}, {POS9+1,{FF,{read,bi,0}}}, {POS9+2,{FF,{a,b,1}}}, {POS9+2,{FF,{erlang,apply,2}}}, {POS9+3,{FF,{erlang,apply,2}}}, {POS9+4,{FF,{erlang,apply,2}}}, {POS9+4,{FF,{erlang,not_a_function,1}}}, - {POS9+5,{FF,{erlang,apply,3}}}, {POS9+5,{FF,{mod,func,2}}}, {POS9+6,{FF,{erlang,apply,1}}}, {POS9+7,{FF,{erlang,apply,2}}}, @@ -1169,17 +1165,11 @@ read_expected(Version) -> {POS9+8,{FF,{q,f,1}}}, {POS10+4,{FF,{erlang,apply,2}}}, {POS10+5,{FF,{mod1,fun1,1}}}, - {POS11+1,{FF,{erlang,apply,3}}}, - {POS11+2,{FF,{erlang,apply,3}}}, - {POS11+3,{FF,{erlang,apply,3}}}, - {POS11+4,{FF,{erlang,apply,3}}}, {POS11+6,{FF,{erlang,apply,2}}}, {POS12+1,{FF,{erlang,apply,2}}}, {POS12+4,{FF,{erlang,apply,2}}}, - {POS12+5,{FF,{erlang,apply,3}}}, {POS12+5,{FF,{m3,f3,2}}}, {POS12+7,{FF,{erlang,apply,2}}}, - {POS12+8,{FF,{erlang,apply,3}}}, {POS13+1,{FF,{dm,df,1}}}, {POS13+6,{{read,bi,0},{foo,module_info,0}}}, {POS13+7,{{read,bi,0},{read,module_info,0}}}, @@ -1189,10 +1179,6 @@ read_expected(Version) -> OK = case Version of abstract_v1 -> - [{POS8+3, {FF,{erlang,apply,3}}}, - {POS10+1, {FF,{erlang,apply,3}}}, - {POS10+6, {FF,{erlang,apply,3}}}] - ++ [{0,{FF,{read,'$F_EXPR',178}}}, {0,{FF,{modul,'$F_EXPR',179}}}] ++ O1; @@ -1213,13 +1199,25 @@ read_expected(Version) -> {POS3+3, {FF,{erlang,spawn_link,3}}}, {POS3+4, {FF,{erlang,spawn_link,3}}}, {POS6+4, {FF,{erlang,spawn,3}}}, + {POS8+6,{FF,{erlang,apply,3}}}, + {POS8+7,{FF,{erlang,apply,3}}}, + {POS9+1,{FF,{erlang,apply,3}}}, + {POS9+5,{FF,{erlang,apply,3}}}, + {POS11+1,{FF,{erlang,apply,3}}}, + {POS11+2,{FF,{erlang,apply,3}}}, + {POS11+3,{FF,{erlang,apply,3}}}, + {POS11+4,{FF,{erlang,apply,3}}}, + {POS12+5,{FF,{erlang,apply,3}}}, + {POS12+8,{FF,{erlang,apply,3}}}, {POS13+5, {{read,bi,0},{erlang,length,1}}}, {POS14+3, {{read,bi,0},{erlang,length,1}}}], %% Operators (OTP-8647): OKB = case Version of abstract_v1 -> - []; + [{POS8+3, {FF,{erlang,apply,3}}}, + {POS10+1, {FF,{erlang,apply,3}}}, + {POS10+6, {FF,{erlang,apply,3}}}]; _ -> [{POS13+16, {{read,bi,0},{erlang,'!',2}}}, {POS13+16, {{read,bi,0},{erlang,'-',1}}}, -- cgit v1.2.3 From 973ef43fbb837c7e790d487dbdd7656dc3376717 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 14 Sep 2015 14:41:48 +0200 Subject: Update Compiler A record field type has been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/compiler/src/core_lint.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl index cc54f6e411..7d3513c0ba 100644 --- a/lib/compiler/src/core_lint.erl +++ b/lib/compiler/src/core_lint.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -73,7 +73,7 @@ %% Define the lint state record. -record(lint, {module :: module(), % Current module - func :: fa(), % Current function + func :: fa() | 'undefined', % Current function errors = [] :: [error()], % Errors warnings= [] :: [warning()]}). % Warnings -- cgit v1.2.3 From 3318e2a51b83d1dd4038950f51880ac872076564 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 28 Sep 2015 16:26:02 +0200 Subject: Update Dialyzer Record field types have been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/dialyzer/src/dialyzer.app.src | 2 +- lib/dialyzer/src/dialyzer.hrl | 10 ++++--- lib/dialyzer/src/dialyzer_callgraph.erl | 21 +++++++++----- lib/dialyzer/src/dialyzer_cl.erl | 2 +- lib/dialyzer/src/dialyzer_codeserver.erl | 10 +++---- lib/dialyzer/src/dialyzer_dataflow.erl | 28 ++++++++++++------ lib/dialyzer/src/dialyzer_gui_wx.erl | 9 +++--- lib/dialyzer/src/dialyzer_races.erl | 40 ++++++++++++++------------ lib/dialyzer/src/dialyzer_succ_typings.erl | 3 +- lib/dialyzer/src/dialyzer_typesig.erl | 37 +++++++++++++----------- lib/dialyzer/test/r9c_SUITE_data/results/inets | 2 -- lib/dialyzer/vsn.mk | 2 +- 12 files changed, 93 insertions(+), 73 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src index 8ac6dc1367..7794cb46c6 100644 --- a/lib/dialyzer/src/dialyzer.app.src +++ b/lib/dialyzer/src/dialyzer.app.src @@ -44,7 +44,7 @@ dialyzer_timing, dialyzer_worker]}, {registered, []}, - {applications, [compiler, gs, hipe, kernel, stdlib, wx]}, + {applications, [compiler, hipe, kernel, stdlib, wx]}, {env, []}, {runtime_dependencies, ["wx-1.2","syntax_tools-1.6.14","stdlib-2.5", "kernel-3.0","hipe-3.13","erts-7.0", diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl index de236f91ab..601e2e954b 100644 --- a/lib/dialyzer/src/dialyzer.hrl +++ b/lib/dialyzer/src/dialyzer.hrl @@ -2,7 +2,7 @@ %%% %%% %CopyrightBegin% %%% -%%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %%% %%% Licensed under the Apache License, Version 2.0 (the "License"); %%% you may not use this file except in compliance with the License. @@ -123,10 +123,12 @@ %% Record declarations used by various files %%-------------------------------------------------------------------- --record(analysis, {analysis_pid :: pid(), +-type doc_plt() :: 'undefined' | dialyzer_plt:plt(). + +-record(analysis, {analysis_pid :: pid() | 'undefined', type = succ_typings :: anal_type(), defines = [] :: [dial_define()], - doc_plt :: dialyzer_plt:plt(), + doc_plt :: doc_plt(), files = [] :: [file:filename()], include_dirs = [] :: [file:filename()], start_from = byte_code :: start_from(), @@ -135,7 +137,7 @@ race_detection = false :: boolean(), behaviours_chk = false :: boolean(), timing = false :: boolean() | 'debug', - timing_server :: dialyzer_timing:timing_server(), + timing_server = none :: dialyzer_timing:timing_server(), callgraph_file = "" :: file:filename(), solvers :: [solver()]}). diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl index a1cd2015ca..069c02fa65 100644 --- a/lib/dialyzer/src/dialyzer_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_callgraph.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -96,15 +96,22 @@ %% whenever applicable. %%----------------------------------------------------------------------------- +%% Types with comment 'race' are due to dialyzer_races.erl. -record(callgraph, {digraph = digraph:new() :: digraph:graph(), - active_digraph :: active_digraph(), - esc :: ets:tid(), - letrec_map :: ets:tid(), + active_digraph :: active_digraph() + | 'undefined', % race + esc :: ets:tid() + | 'undefined', % race + letrec_map :: ets:tid() + | 'undefined', % race name_map :: ets:tid(), rev_name_map :: ets:tid(), - rec_var_map :: ets:tid(), - self_rec :: ets:tid(), - calls :: ets:tid(), + rec_var_map :: ets:tid() + | 'undefined', % race + self_rec :: ets:tid() + | 'undefined', % race + calls :: ets:tid() + | 'undefined', % race race_detection = false :: boolean(), race_data_server = new_race_data_server() :: pid()}). diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 4116866916..92134b7b81 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -36,7 +36,7 @@ -include_lib("kernel/include/file.hrl"). % needed for #file_info{} -record(cl_state, - {backend_pid :: pid(), + {backend_pid :: pid() | 'undefined', erlang_mode = false :: boolean(), external_calls = [] :: [mfa()], external_types = [] :: [mfa()], diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl index 978ecd3843..03cd9671af 100644 --- a/lib/dialyzer/src/dialyzer_codeserver.erl +++ b/lib/dialyzer/src/dialyzer_codeserver.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -81,10 +81,10 @@ -record(codeserver, {next_core_label = 0 :: label(), code :: dict_ets(), - exported_types :: set_ets(), % set(mfa()) - records :: dict_ets(), - contracts :: dict_ets(), - callbacks :: dict_ets(), + exported_types :: set_ets() | 'undefined', % set(mfa()) + records :: dict_ets() | 'undefined', + contracts :: dict_ets() | 'undefined', + callbacks :: dict_ets() | 'undefined', fun_meta_info :: dict_ets(), % {mfa(), meta_info()} exports :: 'clean' | set_ets(), % set(mfa()) temp_exported_types :: 'clean' | set_ets(), % set(mfa()) diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index cabc5e9e0d..6e49043551 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -99,19 +99,29 @@ -define(BITS, 128). --record(state, {callgraph :: dialyzer_callgraph:callgraph(), - codeserver :: dialyzer_codeserver:codeserver(), - envs :: env_tab(), - fun_tab :: fun_tab(), - fun_homes :: dict:dict(label(), mfa()), - plt :: dialyzer_plt:plt(), - opaques :: [type()], +%% Types with comment 'race' are due to dialyzer_races.erl. +-record(state, {callgraph :: dialyzer_callgraph:callgraph() + | 'undefined', % race + codeserver :: dialyzer_codeserver:codeserver() + | 'undefined', % race + envs :: env_tab() + | 'undefined', % race + fun_tab :: fun_tab() + | 'undefined', % race + fun_homes :: dict:dict(label(), mfa()) + | 'undefined', % race + plt :: dialyzer_plt:plt() + | 'undefined', % race + opaques :: [type()] + | 'undefined', % race races = dialyzer_races:new() :: dialyzer_races:races(), records = dict:new() :: types(), - tree_map :: dict:dict(label(), cerl:cerl()), + tree_map :: dict:dict(label(), cerl:cerl()) + | 'undefined', % race warning_mode = false :: boolean(), warnings = [] :: [raw_warning()], - work :: {[_], [_], sets:set()}, + work :: {[_], [_], sets:set()} + | 'undefined', % race module :: module(), curr_fun :: curr_fun() }). diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl index ff54a91ce1..9f344d87ff 100644 --- a/lib/dialyzer/src/dialyzer_gui_wx.erl +++ b/lib/dialyzer/src/dialyzer_gui_wx.erl @@ -2,7 +2,7 @@ %%------------------------------------------------------------------------ %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2013. All Rights Reserved. +%% Copyright Ericsson AB 2009-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -52,7 +52,6 @@ add_dir :: wx:wx_object(), add_rec :: wx:wx_object(), chosen_box :: wx:wx_object(), - analysis_pid :: pid(), del_file :: wx:wx_object(), doc_plt :: dialyzer_plt:plt(), clear_chosen :: wx:wx_object(), @@ -72,11 +71,11 @@ stop :: wx:wx_object(), frame :: wx:wx_object(), warnings_box :: wx:wx_object(), - explanation_box :: wx:wx_object(), + explanation_box :: wx:wx_object() | 'undefined', wantedWarnings :: list(), rawWarnings :: list(), - backend_pid :: pid(), - expl_pid :: pid()}). + backend_pid :: pid() | 'undefined', + expl_pid :: pid() | 'undefined'}). %%------------------------------------------------------------------------ diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl index 39de071bde..bb43d1dcb8 100644 --- a/lib/dialyzer/src/dialyzer_races.erl +++ b/lib/dialyzer/src/dialyzer_races.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2014. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -92,27 +92,28 @@ -type race_warn_tag() :: ?WARN_WHEREIS_REGISTER | ?WARN_WHEREIS_UNREGISTER | ?WARN_ETS_LOOKUP_INSERT | ?WARN_MNESIA_DIRTY_READ_WRITE. --record(beg_clause, {arg :: var_to_map1(), - pats :: var_to_map1(), - guard :: cerl:cerl()}). --record(end_clause, {arg :: var_to_map1(), - pats :: var_to_map1(), - guard :: cerl:cerl()}). +-record(beg_clause, {arg :: var_to_map1() | 'undefined', + pats :: var_to_map1() | 'undefined', + guard :: cerl:cerl() | 'undefined'}). +-record(end_clause, {arg :: var_to_map1() | 'undefined', + pats :: var_to_map1() | 'undefined', + guard :: cerl:cerl() | 'undefined'}). -record(end_case, {clauses :: [#end_clause{}]}). --record(curr_fun, {status :: 'in' | 'out', - mfa :: dialyzer_callgraph:mfa_or_funlbl(), - label :: label(), - def_vars :: [core_vars()], - arg_types :: [erl_types:erl_type()], - call_vars :: [core_vars()], - var_map :: dict:dict()}). +-record(curr_fun, {status :: 'in' | 'out' | 'undefined', + mfa :: dialyzer_callgraph:mfa_or_funlbl() + | 'undefined', + label :: label() | 'undefined', + def_vars :: [core_vars()] | 'undefined', + arg_types :: [erl_types:erl_type()] | 'undefined', + call_vars :: [core_vars()] | 'undefined', + var_map :: dict:dict() | 'undefined'}). -record(dep_call, {call_name :: dep_calls(), - args :: args(), + args :: args() | 'undefined', arg_types :: [erl_types:erl_type()], vars :: [core_vars()], state :: dialyzer_dataflow:state(), file_line :: file_line(), - var_map :: dict:dict()}). + var_map :: dict:dict() | 'undefined'}). -record(fun_call, {caller :: dialyzer_callgraph:mfa_or_funlbl(), callee :: dialyzer_callgraph:mfa_or_funlbl(), arg_types :: [erl_types:erl_type()], @@ -121,7 +122,7 @@ arg :: var_to_map1()}). -record(warn_call, {call_name :: warn_calls(), args :: args(), - var_map :: dict:dict()}). + var_map :: dict:dict() | 'undefined'}). -type case_tags() :: 'beg_case' | #beg_clause{} | #end_clause{} | #end_case{}. -type code() :: [#dep_call{} | #fun_call{} | #warn_call{} | @@ -139,8 +140,9 @@ fun_mfa :: dialyzer_callgraph:mfa_or_funlbl(), fun_label :: label()}). --record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl(), - curr_fun_label :: label(), +-record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl() + | 'undefined', + curr_fun_label :: label() | 'undefined', curr_fun_args = 'empty' :: core_args(), new_table = 'no_t' :: table(), race_list = [] :: code(), diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index 18f02e6742..987da3aecf 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%% Copyright Ericsson AB 2006-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -134,7 +134,6 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph, end end. --type doc_plt() :: 'undefined' | dialyzer_plt:plt(). -spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(), doc_plt(), dialyzer_codeserver:codeserver(), dialyzer_timing:timing_server(), [solver()], pid()) -> diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 0b8b244cc9..5f0881bbcd 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -68,7 +68,7 @@ -type type_var() :: erl_types:erl_type(). %% actually: {'c','var',_,_} -record(fun_var, {'fun' :: fun((_) -> erl_types:erl_type()), deps :: [dep()], - origin :: integer()}). + origin :: integer() | 'undefined'}). -type constr_op() :: 'eq' | 'sub'. -type fvar_or_type() :: #fun_var{} | erl_types:erl_type(). @@ -83,9 +83,9 @@ -record(constraint_list, {type :: 'conj' | 'disj', list :: [constr()], deps :: [dep()], - masks :: [{dep(),[non_neg_integer()]}] | - {'d',dict:dict(dep(), [non_neg_integer()])}, - id :: {'list', dep()}}). + masks = [] :: [{dep(),[non_neg_integer()]}] | + {'d',dict:dict(dep(), [non_neg_integer()])}, + id :: {'list', dep()} | 'undefined'}). -type constraint_list() :: #constraint_list{}. @@ -104,7 +104,8 @@ -type dict_or_ets() :: {'d', prop_types()} | {'e', ets:tid()}. --record(state, {callgraph :: dialyzer_callgraph:callgraph(), +-record(state, {callgraph :: dialyzer_callgraph:callgraph() + | 'undefined', cs = [] :: [constr()], cmap = {'d', dict:new()} :: dict_or_ets(), fun_map = [] :: typesig_funmap(), @@ -116,7 +117,8 @@ cerl:c_fun()), next_label = 0 :: label(), self_rec :: 'false' | erl_types:erl_type(), - plt :: dialyzer_plt:plt(), + plt :: dialyzer_plt:plt() + | 'undefined', prop_types = {'d', dict:new()} :: dict_or_ets(), records = dict:new() :: types(), scc = [] :: [type_var()], @@ -1746,7 +1748,10 @@ minimize_state(#state{ fun_arities = FunArities, self_rec = SelfRec, prop_types = {e, ETSPropTypes}, - solvers = Solvers + solvers = Solvers, + callgraph = undefined, + plt = undefined, + mfas = [] }. dispose_state(#state{cmap = {e, ETSCMap}, @@ -2884,8 +2889,7 @@ mk_constraint(Lhs, Op, Rhs) -> case t_is_any(Lhs) orelse constraint_opnd_is_any(Rhs) of false -> Deps = find_constraint_deps([Lhs, Rhs]), - C0 = mk_constraint_1(Lhs, Op, Rhs), - C = C0#constraint{deps = Deps}, + C = mk_constraint_1(Lhs, Op, Rhs, Deps), case Deps =:= [] of true -> %% This constraint is constant. Solve it immediately. @@ -2903,8 +2907,7 @@ mk_constraint(Lhs, Op, Rhs) -> end. mk_constraint_any(Op) -> - C = mk_constraint_1(t_any(), Op, t_any()), - C#constraint{deps = []}. + mk_constraint_1(t_any(), Op, t_any(), []). %% the following function is used so that we do not call %% erl_types:t_is_any/1 with a term other than an erl_type() @@ -2952,12 +2955,12 @@ find_constraint_deps([Type|Tail], Acc) -> find_constraint_deps([], Acc) -> lists:flatten(Acc). -mk_constraint_1(Lhs, eq, Rhs) when Lhs < Rhs -> - #constraint{lhs = Lhs, op = eq, rhs = Rhs}; -mk_constraint_1(Lhs, eq, Rhs) -> - #constraint{lhs = Rhs, op = eq, rhs = Lhs}; -mk_constraint_1(Lhs, Op, Rhs) -> - #constraint{lhs = Lhs, op = Op, rhs = Rhs}. +mk_constraint_1(Lhs, eq, Rhs, Deps) when Lhs < Rhs -> + #constraint{lhs = Lhs, op = eq, rhs = Rhs, deps = Deps}; +mk_constraint_1(Lhs, eq, Rhs, Deps) -> + #constraint{lhs = Rhs, op = eq, rhs = Lhs, deps = Deps}; +mk_constraint_1(Lhs, Op, Rhs, Deps) -> + #constraint{lhs = Lhs, op = Op, rhs = Rhs, deps = Deps}. mk_constraints([Lhs|LhsTail], Op, [Rhs|RhsTail]) -> [mk_constraint(Lhs, Op, Rhs) | diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/inets b/lib/dialyzer/test/r9c_SUITE_data/results/inets index 89be9652e3..d377f34978 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/inets +++ b/lib/dialyzer/test/r9c_SUITE_data/results/inets @@ -37,7 +37,6 @@ mod_cgi.erl:372: The pattern {'http_response', NewAccResponse} can never match t mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom() | {'no_translation',binary()})) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) mod_dir.erl:72: The pattern {'error', Reason} can never match the type {'ok',[[[any()] | char()],...]} mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type -mod_get.erl:150: Record construction #file_info{} violates the declared type of field size::non_neg_integer() and type::'device' | 'directory' | 'other' | 'regular' | 'symlink' and access::'none' | 'read' | 'read_write' | 'write' and atime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mtime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and ctime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mode::non_neg_integer() and links::non_neg_integer() and major_device::non_neg_integer() and minor_device::non_neg_integer() and inode::non_neg_integer() and uid::non_neg_integer() and gid::non_neg_integer() mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type mod_htaccess.erl:460: The pattern {'error', BadData} can never match the type {'ok',_} mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],maybe_improper_list()} @@ -48,7 +47,6 @@ mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type mod_include.erl:716: Function read_error/3 will never be called mod_include.erl:719: Function read_error/4 will never be called -mod_range.erl:308: Record construction #file_info{} violates the declared type of field size::non_neg_integer() and type::'device' | 'directory' | 'other' | 'regular' | 'symlink' and access::'none' | 'read' | 'read_write' | 'write' and atime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mtime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and ctime::non_neg_integer() | {{non_neg_integer(),1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12,1..255},{byte(),byte(),byte()}} and mode::non_neg_integer() and links::non_neg_integer() and major_device::non_neg_integer() and minor_device::non_neg_integer() and inode::non_neg_integer() and uid::non_neg_integer() and gid::non_neg_integer() mod_security_server.erl:386: The variable O can never match since previous clauses completely covered the type [tuple()] mod_security_server.erl:433: The variable Other can never match since previous clauses completely covered the type [tuple()] mod_security_server.erl:585: The variable _ can never match since previous clauses completely covered the type [tuple()] diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index e57caa9ad3..9480f17f51 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.8.1 +DIALYZER_VSN = 2.8.2 -- cgit v1.2.3 From b0ad54fdc41528ddff7c1767403a514a4e0a3f9c Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Fri, 2 Oct 2015 16:18:58 +0200 Subject: Fix errors in dialyzer_{coordinator,worker} specs --- lib/dialyzer/src/dialyzer_coordinator.erl | 21 +++++++++++---------- lib/dialyzer/src/dialyzer_worker.erl | 7 ++++--- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl index 612f379d32..3290161ca1 100644 --- a/lib/dialyzer/src/dialyzer_coordinator.erl +++ b/lib/dialyzer/src/dialyzer_coordinator.erl @@ -38,7 +38,7 @@ %%% Exports for the compilation workers -export([get_next_label/2]). --export_type([coordinator/0, mode/0, init_data/0, result/0]). +-export_type([coordinator/0, mode/0, init_data/0, result/0, job/0]). %%-------------------------------------------------------------------- @@ -52,10 +52,12 @@ -type scc() :: [mfa_or_funlbl()]. -type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'. --type compile_jobs() :: [file:filename()]. --type typesig_jobs() :: [scc()]. --type dataflow_jobs() :: [module()]. --type warnings_jobs() :: [module()]. +-type compile_job() :: file:filename(). +-type typesig_job() :: scc(). +-type dataflow_job() :: module(). +-type warnings_job() :: module(). + +-type job() :: compile_job() | typesig_job() | dataflow_job() | warnings_job(). -type compile_init_data() :: dialyzer_analysis_callgraph:compile_init_data(). -type typesig_init_data() :: dialyzer_succ_typings:typesig_init_data(). @@ -73,7 +75,6 @@ -type result() :: compile_result() | typesig_result() | dataflow_result() | warnings_result(). --type job() :: scc() | module() | file:filename(). -type job_result() :: dialyzer_analysis_callgraph:one_file_result() | typesig_result() | dataflow_result() | warnings_result(). @@ -90,13 +91,13 @@ %%-------------------------------------------------------------------- --spec parallel_job('compile', compile_jobs(), compile_init_data(), timing()) -> +-spec parallel_job('compile', [compile_job()], compile_init_data(), timing()) -> {compile_result(), integer()}; - ('typesig', typesig_jobs(), typesig_init_data(), timing()) -> + ('typesig', [typesig_job()], typesig_init_data(), timing()) -> typesig_result(); - ('dataflow', dataflow_jobs(), dataflow_init_data(), + ('dataflow', [dataflow_job()], dataflow_init_data(), timing()) -> dataflow_result(); - ('warnings', warnings_jobs(), warnings_init_data(), + ('warnings', [warnings_job()], warnings_init_data(), timing()) -> warnings_result(). parallel_job(Mode, Jobs, InitData, Timing) -> diff --git a/lib/dialyzer/src/dialyzer_worker.erl b/lib/dialyzer/src/dialyzer_worker.erl index 4be93c75bf..979e3a621d 100644 --- a/lib/dialyzer/src/dialyzer_worker.erl +++ b/lib/dialyzer/src/dialyzer_worker.erl @@ -31,10 +31,11 @@ -type coordinator() :: dialyzer_coordinator:coordinator(). -type init_data() :: dialyzer_coordinator:init_data(). -type result() :: dialyzer_coordinator:result(). +-type job() :: dialyzer_coordinator:job(). -record(state, { mode :: mode(), - job :: mfa_or_funlbl() | file:filename(), + job :: job(), coordinator :: coordinator(), init_data :: init_data(), depends_on = [] :: list() @@ -52,7 +53,7 @@ %%-------------------------------------------------------------------- --spec launch(mode(), [mfa_or_funlbl()], init_data(), coordinator()) -> worker(). +-spec launch(mode(), job(), init_data(), coordinator()) -> worker(). launch(Mode, Job, InitData, Coordinator) -> State = #state{mode = Mode, @@ -174,7 +175,7 @@ collect_warnings(#state{job = Job, init_data = InitData}) -> -type extra() :: label() | 'unused'. --spec sequential(mode(), [mfa_or_funlbl()], init_data(), extra()) -> result(). +-spec sequential(mode(), job(), init_data(), extra()) -> result(). sequential('compile', Job, InitData, Extra) -> case dialyzer_analysis_callgraph:start_compilation(Job, InitData) of -- cgit v1.2.3 From 9221ddadb0eb879462cd96183d3eaf6352830eb3 Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Mon, 5 Oct 2015 23:53:27 +0200 Subject: Update and cleanup HiPE records The bulk of the changes concerns cleanups and code refactorings concerning record constructions that assigned 'undefined' to record fields whose type did not contain this value. See commit 8ce35b2. While at it, some new type definitions were introduced and type names were used instead of record type notation. Minor code cleaups were also done. --- lib/hipe/cerl/cerl_cconv.erl | 13 ++++++---- lib/hipe/cerl/cerl_hipeify.erl | 12 ++++----- lib/hipe/flow/cfg.hrl | 8 +++--- lib/hipe/icode/hipe_icode.erl | 36 +++++++++++++------------- lib/hipe/icode/hipe_icode.hrl | 3 ++- lib/hipe/icode/hipe_icode_exceptions.erl | 20 ++++++-------- lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl | 6 ++--- lib/hipe/main/hipe.erl | 5 ++-- lib/hipe/main/hipe.hrl.src | 5 ++-- lib/hipe/main/hipe_main.erl | 16 +++++++----- 10 files changed, 65 insertions(+), 59 deletions(-) (limited to 'lib') diff --git a/lib/hipe/cerl/cerl_cconv.erl b/lib/hipe/cerl/cerl_cconv.erl index 0fc28be5f3..ac9d01ab0e 100644 --- a/lib/hipe/cerl/cerl_cconv.erl +++ b/lib/hipe/cerl/cerl_cconv.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -710,7 +710,7 @@ ren__new() -> ren__add(Key, Value, Ren) -> dict:store(Key, Value, Ren). -ren__map(Key, Ren) -> +ren__map(Key, Ren) -> case dict:find(Key, Ren) of {ok, Value} -> Value; @@ -722,11 +722,14 @@ ren__map(Key, Ren) -> %% --------------------------------------------------------------------- %% State --record(state, {module :: module(), function :: {atom(), arity()}, - names, refs, defs = []}). +-record(state, {module :: module(), + function :: {atom(), arity()} | 'undefined', + names = sets:new() :: sets:set(), %% XXX: refine + refs = dict:new() :: dict:dict(), %% XXX: refine + defs = []}). s__new(Module) -> - #state{module = Module, names = sets:new(), refs = dict:new()}. + #state{module = Module}. s__add_function_name(Name, S) -> S#state{names = sets:add_element(Name, S#state.names)}. diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl index 8691e80cac..6611abd204 100644 --- a/lib/hipe/cerl/cerl_hipeify.erl +++ b/lib/hipe/cerl/cerl_hipeify.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -623,12 +623,12 @@ ren__map(Key, Ren) -> %% --------------------------------------------------------------------- %% State -%% pmatch = 'true' | 'false' | 'no_duplicates' | 'duplicate_all' +-type pmatch() :: 'true' | 'false' | 'no_duplicates' | 'duplicate_all'. --record(state, {module::atom(), - function::{atom(), 0..256}, - pmatch=true, - revisit = false}). +-record(state, {module :: module(), + function :: {atom(), arity()} | 'undefined', + pmatch = true :: pmatch(), + revisit = false :: boolean()}). s__new(Module) -> #state{module = Module}. diff --git a/lib/hipe/flow/cfg.hrl b/lib/hipe/flow/cfg.hrl index f79fff4efe..641ec102db 100644 --- a/lib/hipe/flow/cfg.hrl +++ b/lib/hipe/flow/cfg.hrl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2014. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -34,11 +34,13 @@ %% -record(cfg_info, {'fun' :: mfa(), start_label :: cfg_lbl(), + %% TODO: merge is_closure and closure_arity into one field is_closure :: boolean(), - closure_arity :: arity(), + closure_arity = none :: 'none' | arity(), is_leaf :: boolean(), params, % :: list() info = []}). %% this field seems not needed; take out?? +-type cfg_info() :: #cfg_info{}. %% %% Data is a triple with a dict of constants, a list of labels and an integer @@ -49,6 +51,6 @@ %% The following is to be used by other modules %% -record(cfg, {table = gb_trees:empty() :: gb_trees:tree(), - info :: #cfg_info{}, + info :: cfg_info(), data :: cfg_data()}). -type cfg() :: #cfg{}. diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl index 5c7003b0ed..9692eebb10 100644 --- a/lib/hipe/icode/hipe_icode.erl +++ b/lib/hipe/icode/hipe_icode.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -631,59 +631,59 @@ mk_icode(Fun, Params, IsClosure, IsLeaf, Code, VarRange, LabelRange) -> -spec mk_icode(mfa(), [icode_var()], boolean(), boolean(), [icode_instr()], hipe_consttab(), {non_neg_integer(),non_neg_integer()}, - {icode_lbl(),icode_lbl()}) -> #icode{}. + {icode_lbl(),icode_lbl()}) -> icode(). mk_icode(Fun, Params, IsClosure, IsLeaf, Code, Data, VarRange, LabelRange) -> #icode{'fun'=Fun, params=Params, code=Code, data=Data, is_closure=IsClosure, is_leaf=IsLeaf, var_range=VarRange, label_range=LabelRange}. --spec icode_fun(#icode{}) -> mfa(). +-spec icode_fun(icode()) -> mfa(). icode_fun(#icode{'fun' = MFA}) -> MFA. --spec icode_params(#icode{}) -> [icode_var()]. +-spec icode_params(icode()) -> [icode_var()]. icode_params(#icode{params = Params}) -> Params. --spec icode_params_update(#icode{}, [icode_var()]) -> #icode{}. +-spec icode_params_update(icode(), [icode_var()]) -> icode(). icode_params_update(Icode, Params) -> Icode#icode{params = Params}. --spec icode_is_closure(#icode{}) -> boolean(). +-spec icode_is_closure(icode()) -> boolean(). icode_is_closure(#icode{is_closure = Closure}) -> Closure. --spec icode_is_leaf(#icode{}) -> boolean(). +-spec icode_is_leaf(icode()) -> boolean(). icode_is_leaf(#icode{is_leaf = Leaf}) -> Leaf. --spec icode_code(#icode{}) -> icode_instrs(). +-spec icode_code(icode()) -> icode_instrs(). icode_code(#icode{code = Code}) -> Code. --spec icode_code_update(#icode{}, icode_instrs()) -> #icode{}. +-spec icode_code_update(icode(), icode_instrs()) -> icode(). icode_code_update(Icode, NewCode) -> Vmax = highest_var(NewCode), Lmax = highest_label(NewCode), Icode#icode{code = NewCode, var_range = {0,Vmax}, label_range = {0,Lmax}}. --spec icode_data(#icode{}) -> hipe_consttab(). +-spec icode_data(icode()) -> hipe_consttab(). icode_data(#icode{data=Data}) -> Data. -%% %% -spec icode_data_update(#icode{}, hipe_consttab()) -> #icode{}. +%% %% -spec icode_data_update(icode(), hipe_consttab()) -> icode(). %% icode_data_update(Icode, NewData) -> Icode#icode{data=NewData}. --spec icode_var_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}. +-spec icode_var_range(icode()) -> {non_neg_integer(), non_neg_integer()}. icode_var_range(#icode{var_range = VarRange}) -> VarRange. --spec icode_label_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}. +-spec icode_label_range(icode()) -> {non_neg_integer(), non_neg_integer()}. icode_label_range(#icode{label_range = LabelRange}) -> LabelRange. --spec icode_info(#icode{}) -> icode_info(). +-spec icode_info(icode()) -> icode_info(). icode_info(#icode{info = Info}) -> Info. --spec icode_info_update(#icode{}, icode_info()) -> #icode{}. +-spec icode_info_update(icode(), icode_info()) -> icode(). icode_info_update(Icode, Info) -> Icode#icode{info = Info}. --spec icode_closure_arity(#icode{}) -> arity(). +-spec icode_closure_arity(icode()) -> arity(). icode_closure_arity(#icode{closure_arity = Arity}) -> Arity. --spec icode_closure_arity_update(#icode{}, arity()) -> #icode{}. +-spec icode_closure_arity_update(icode(), arity()) -> icode(). icode_closure_arity_update(Icode, Arity) -> Icode#icode{closure_arity = Arity}. @@ -1709,7 +1709,7 @@ mk_new_label() -> %% @doc Removes comments from Icode. %% --spec strip_comments(#icode{}) -> #icode{}. +-spec strip_comments(icode()) -> icode(). strip_comments(ICode) -> icode_code_update(ICode, no_comments(icode_code(ICode))). diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl index 9b24c4914e..3bb7bae019 100644 --- a/lib/hipe/icode/hipe_icode.hrl +++ b/lib/hipe/icode/hipe_icode.hrl @@ -170,8 +170,9 @@ -record(icode, {'fun' :: mfa(), params :: [icode_var()], + %% TODO: merge is_closure and closure_arity into one field is_closure :: boolean(), - closure_arity :: arity(), + closure_arity = none :: 'none' | arity(), is_leaf :: boolean(), code = [] :: icode_instrs(), data :: hipe_consttab(), diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl index 41556ab80f..f03ce2faaa 100644 --- a/lib/hipe/icode/hipe_icode_exceptions.erl +++ b/lib/hipe/icode/hipe_icode_exceptions.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2014. All Rights Reserved. +%% Copyright Ericsson AB 2004-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -85,7 +85,7 @@ %%---------------------------------------------------------------------------- --spec fix_catches(#cfg{}) -> #cfg{}. +-spec fix_catches(cfg()) -> cfg(). fix_catches(CFG) -> {Map, State} = build_mapping(find_catches(init_state(CFG))), @@ -393,10 +393,10 @@ get_renaming(C, Map) -> %%--------------------------------------------------------------------- %% State abstraction --record(state, {cfg :: #cfg{}, +-record(state, {cfg :: cfg(), changed = false :: boolean(), - succ :: #cfg{}, - pred :: #cfg{}, + succ :: cfg(), + pred :: cfg(), start_labels :: [icode_lbl(),...], visited = hipe_icode_cfg:none_visited() :: gb_sets:set(), out = gb_trees:empty() :: gb_trees:tree(), @@ -404,13 +404,8 @@ get_renaming(C, Map) -> }). init_state(CFG) -> - State = #state{cfg = CFG}, - refresh_state_cache(State). - -refresh_state_cache(State) -> - CFG = State#state.cfg, SLs = [hipe_icode_cfg:start_label(CFG)], - State#state{succ = CFG, pred = CFG, start_labels = SLs}. + #state{cfg = CFG, succ = CFG, pred = CFG, start_labels = SLs}. get_cfg(State) -> State#state.cfg. @@ -466,7 +461,8 @@ get_bb_code(L, State) -> set_bb_code(L, Code, State) -> CFG = State#state.cfg, CFG1 = hipe_icode_cfg:bb_add(CFG, L, hipe_bb:mk_bb(Code)), - refresh_state_cache(State#state{cfg = CFG1}). + SLs = [hipe_icode_cfg:start_label(CFG1)], + State#state{cfg = CFG1, succ = CFG1, pred = CFG1, start_labels = SLs}. get_new_catches_in(L, State) -> Ps = get_pred(L, State), diff --git a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl index e350a6ff18..7613024787 100644 --- a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl +++ b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2014. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -314,7 +314,7 @@ node_create(Label, Pred, Succ) -> %% tree - the tree of nodes, with labels as keys and node records as values -record(nodes, { - domtree :: hipe_dominators:domTree(), + domtree = none :: 'none' | hipe_dominators:domTree(), labels = none :: 'none' | [icode_lbl()], postorder = none :: 'none' | [icode_lbl()], start_label = none :: 'none' | icode_lbl(), @@ -390,7 +390,7 @@ update_del_red_test_set(Update) -> %%----------------------------------------------------------------------------- %% Main function called from the hipe_main module --spec struct_reuse(#cfg{}) -> #cfg{}. +-spec struct_reuse(cfg()) -> cfg(). struct_reuse(CFG) -> %% debug_init_case_count(?SR_INSTR_TYPE), diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index 1a4bbf179f..0e32da1d36 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -764,7 +764,8 @@ finalize(OrigList, Mod, Exports, WholeModule, Opts) -> finalize_fun(MfaIcodeList, Exports, Opts) -> case proplists:get_value(concurrent_comp, Opts) of FalseVal when (FalseVal =:= undefined) orelse (FalseVal =:= false) -> - [finalize_fun_sequential(MFAIcode, Opts, #comp_servers{}) + NoServers = #comp_servers{pp_server = none, range = none, type = none}, + [finalize_fun_sequential(MFAIcode, Opts, NoServers) || {_MFA, _Icode} = MFAIcode <- MfaIcodeList]; TrueVal when (TrueVal =:= true) orelse (TrueVal =:= debug) -> finalize_fun_concurrent(MfaIcodeList, Exports, Opts) diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src index ba27878a84..3be824ac34 100644 --- a/lib/hipe/main/hipe.hrl.src +++ b/lib/hipe/main/hipe.hrl.src @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -299,7 +299,8 @@ %% Records defined in the hipe module used in other parts of the compiler %%---------------------------------------------------------------------------- --record(comp_servers, {pp_server :: pid(), range :: pid(), type :: pid()}). +-type mpid() :: 'none' | pid(). +-record(comp_servers, {pp_server :: mpid(), range :: mpid(), type :: mpid()}). %%---------------------------------------------------------------------------- %% Basic types of the 'hipe' application used in other parts of the system diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl index 5753169961..be5050e155 100644 --- a/lib/hipe/main/hipe_main.erl +++ b/lib/hipe/main/hipe_main.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ %%===================================================================== %% @spec compile_icode(MFA::mfa(), -%% LinearIcode::#icode{}, +%% LinearIcode::icode(), %% CompilerOptions::comp_options(), %% CompServers::#comp_servers()) -> %% {native,Platform,{unprofiled,NativeCode}} | {rtl,RTLCode} @@ -69,7 +69,7 @@ %% generated). The compiler options must have already been expanded %% (cf. `hipe:expand_options').

--spec compile_icode(mfa(), #icode{}, comp_options(), #comp_servers{}) -> +-spec compile_icode(mfa(), icode(), comp_options(), #comp_servers{}) -> comp_icode_ret(). compile_icode(MFA, LinearIcode, Options, Servers) -> @@ -230,10 +230,12 @@ get_pp_module(icode_liveness) -> hipe_icode_liveness; get_pp_module(rtl_liveness) -> hipe_rtl_liveness. perform_io(no_fun, _) -> ok; -perform_io(Fun,PPServer) when is_pid(PPServer) -> - PPServer ! {print,Fun}; -perform_io(Fun, undefined) -> - Fun(). +perform_io(Fun, PPServer) when is_pid(PPServer) -> + PPServer ! {print, Fun}, + ok; +perform_io(Fun, none) -> + Fun(), + ok. %%-------------------------------------------------------------------- -- cgit v1.2.3 From 3b2a4ad2db8115e9c4b982a7400692cf9847869b Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 09:25:54 +0200 Subject: Update Tools Record field types have been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/tools/src/lcnt.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl index e8b3d242e4..9ee75a688a 100644 --- a/lib/tools/src/lcnt.erl +++ b/lib/tools/src/lcnt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -94,12 +94,12 @@ -record(stats, { file :: atom(), - line :: non_neg_integer(), + line :: non_neg_integer() | 'undefined', tries :: non_neg_integer(), colls :: non_neg_integer(), time :: non_neg_integer(), % us nt :: non_neg_integer(), % #timings collected - hist :: tuple() % histogram + hist :: tuple() | 'undefined' % histogram }). -record(lock, { @@ -757,7 +757,7 @@ list2lock([F|Fs], Ls) -> stats2stats([]) -> []; stats2stats([Stat|Stats]) -> - Sz = tuple_size(#stats{}), + Sz = record_info(size, stats), [stat2stat(Stat,Sz)|stats2stats(Stats)]. stat2stat(Stat,Sz) when tuple_size(Stat) =:= Sz -> Stat; -- cgit v1.2.3 From 99dd169e4c499c78dd85c6e34296fdc150e47d24 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 09:41:06 +0200 Subject: Update Syntax Tools Record field types have been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/syntax_tools/src/erl_tidy.erl | 10 +++++----- lib/syntax_tools/src/igor.erl | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl index db7f0939a3..f2de12b410 100644 --- a/lib/syntax_tools/src/erl_tidy.erl +++ b/lib/syntax_tools/src/erl_tidy.erl @@ -937,7 +937,7 @@ hidden_uses_2(Tree, Used) -> -record(env, {file :: file:filename(), module :: atom(), - current :: fa(), + current :: fa() | 'undefined', imports = dict:new() :: dict:dict(atom(), atom()), context = normal :: context(), verbosity = 1 :: 0 | 1 | 2, @@ -949,10 +949,10 @@ hidden_uses_2(Tree, Used) -> new_guard_tests = true :: boolean(), old_guard_tests = false :: boolean()}). --record(st, {varc :: non_neg_integer(), +-record(st, {varc :: non_neg_integer() | 'undefined', used = sets:new() :: sets:set({atom(), arity()}), imported :: sets:set({atom(), arity()}), - vars :: sets:set(atom()), + vars :: sets:set(atom()) | 'undefined', functions :: sets:set({atom(), arity()}), new_forms = [] :: [erl_syntax:syntaxTree()], rename :: dict:dict(mfa(), {atom(), atom()})}). @@ -1064,13 +1064,13 @@ visit_clause(Tree, Env, St0) -> visit_infix_expr(Tree, #env{context = guard_test}, St0) -> %% Detect transition from guard test to guard expression. - visit_other(Tree, #env{context = guard_expr}, St0); + visit_other(Tree, #env{context = guard_expr, file = ""}, St0); visit_infix_expr(Tree, Env, St0) -> visit_other(Tree, Env, St0). visit_prefix_expr(Tree, #env{context = guard_test}, St0) -> %% Detect transition from guard test to guard expression. - visit_other(Tree, #env{context = guard_expr}, St0); + visit_other(Tree, #env{context = guard_expr, file = ""}, St0); visit_prefix_expr(Tree, Env, St0) -> visit_other(Tree, Env, St0). diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl index eac5af5540..4557678f9d 100644 --- a/lib/syntax_tools/src/igor.erl +++ b/lib/syntax_tools/src/igor.erl @@ -1594,10 +1594,11 @@ alias_expansions_2(Modules, Table) -> preserved :: boolean(), no_headers :: boolean(), notes :: notes(), - map :: map_fun(), + map :: map_fun() | 'undefined', renaming :: fun((atom()) -> map_fun()), expand :: dict:dict({atom(), integer()}, - {atom(), {atom(), integer()}}), + {atom(), {atom(), integer()}}) + | 'undefined', redirect :: dict:dict(atom(), atom()) }). -- cgit v1.2.3 From 358d162cef263cc7e9d4d072aef259a41835e9d8 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 09:41:31 +0200 Subject: Update Test Server A record field type has been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/test_server/src/test_server_gl.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/test_server/src/test_server_gl.erl b/lib/test_server/src/test_server_gl.erl index c5ec3ccbe6..31098d9726 100644 --- a/lib/test_server/src/test_server_gl.erl +++ b/lib/test_server/src/test_server_gl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012-2013. All Rights Reserved. +%% Copyright Ericsson AB 2012-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ -export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2]). -record(st, {tc_supervisor :: 'none'|pid(), %Test case supervisor - tc :: mfa(), %Current test case MFA + tc :: mfa() | 'undefined', %Current test case MFA minor :: 'none'|pid(), %Minor fd minor_monitor, %Monitor ref for minor fd capture :: 'none'|pid(), %Capture output -- cgit v1.2.3 From 1c639b17643da67905717b05d1af66fe6e3b7c37 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 10:12:12 +0200 Subject: Update SSL Record field types have been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/ssl/src/ssl_connection.hrl | 23 ++++++++++++----------- lib/ssl/src/ssl_internal.hrl | 14 +++++++------- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index 9a58f2b8f7..bb41ef2b62 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -48,27 +48,28 @@ socket_options :: #socket_options{}, connection_states :: #connection_states{} | secret_printout(), protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl - tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout(), - cert_db :: reference(), + tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout() + | 'undefined', + cert_db :: reference() | 'undefined', session :: #session{} | secret_printout(), session_cache :: db_handle(), session_cache_cb :: atom(), crl_db :: term(), - negotiated_version :: ssl_record:ssl_version(), + negotiated_version :: ssl_record:ssl_version() | 'undefined', client_certificate_requested = false :: boolean(), key_algorithm :: ssl_cipher:key_algo(), hashsign_algorithm = {undefined, undefined}, cert_hashsign_algorithm, - public_key_info :: ssl_handshake:public_key_info(), - private_key :: public_key:private_key() | secret_printout(), + public_key_info :: ssl_handshake:public_key_info() | 'undefined', + private_key :: public_key:private_key() | secret_printout() | 'undefined', diffie_hellman_params:: #'DHParameter'{} | undefined | secret_printout(), diffie_hellman_keys :: {PublicKey :: binary(), PrivateKey :: binary()} | #'ECPrivateKey'{} | undefined | secret_printout(), - psk_identity :: binary(), % server psk identity hint - srp_params :: #srp_user{} | secret_printout(), - srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout(), - premaster_secret :: binary() | secret_printout() , + psk_identity :: binary() | 'undefined', % server psk identity hint + srp_params :: #srp_user{} | secret_printout() | 'undefined', + srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout() | 'undefined', + premaster_secret :: binary() | secret_printout() | 'undefined', file_ref_db :: db_handle(), - cert_db_ref :: certdb_ref(), + cert_db_ref :: certdb_ref() | 'undefined', bytes_to_read :: undefined | integer(), %% bytes to read in passive mode user_data_buffer :: undefined | binary() | secret_printout(), renegotiation :: undefined | {boolean(), From::term() | internal | peer}, @@ -81,7 +82,7 @@ expecting_finished = false ::boolean(), negotiated_protocol = undefined :: undefined | binary(), client_ecc, % {Curves, PointFmt} - tracker :: pid(), %% Tracker process for listen socket + tracker :: pid() | 'undefined', %% Tracker process for listen socket sni_hostname = undefined }). diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index 3851b2bc6e..007723c982 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -90,16 +90,16 @@ validate_extensions_fun, depth :: integer(), certfile :: binary(), - cert :: public_key:der_encoded() | secret_printout(), + cert :: public_key:der_encoded() | secret_printout() | 'undefined', keyfile :: binary(), - key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()} | secret_printout(), - password :: string() | secret_printout(), - cacerts :: [public_key:der_encoded()] | secret_printout(), + key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()} | secret_printout() | 'undefined', + password :: string() | secret_printout() | 'undefined', + cacerts :: [public_key:der_encoded()] | secret_printout() | 'undefined', cacertfile :: binary(), dh :: public_key:der_encoded() | secret_printout(), - dhfile :: binary() | secret_printout(), + dhfile :: binary() | secret_printout() | 'undefined', user_lookup_fun, % server option, fun to lookup the user - psk_identity :: binary() | secret_printout() , + psk_identity :: binary() | secret_printout() | 'undefined', srp_identity, % client option {User, Password} ciphers, % %% Local policy for the server if it want's to reuse the session @@ -115,7 +115,7 @@ %% undefined if not hibernating, or number of ms of %% inactivity after which ssl_connection will go into %% hibernation - hibernate_after :: boolean(), + hibernate_after :: boolean() | 'undefined', %% This option should only be set to true by inet_tls_dist erl_dist = false :: boolean(), alpn_advertised_protocols = undefined :: [binary()] | undefined , -- cgit v1.2.3 From 93e1b6fc08c688b03d35a30db4bf3d3c464f330a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 12:33:40 +0200 Subject: Update Reltool Record field types have been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/reltool/src/reltool.hrl | 46 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl index 4c3f76bdc6..9ac22b9450 100644 --- a/lib/reltool/src/reltool.hrl +++ b/lib/reltool/src/reltool.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -141,15 +141,15 @@ app_name :: '_' | app_name(), incl_cond :: '_' | incl_cond() | undefined, debug_info :: '_' | debug_info() | undefined, - is_app_mod :: '_' | boolean(), - is_ebin_mod :: '_' | boolean(), - uses_mods :: '$2' | [mod_name()], - exists :: '_' | boolean(), + is_app_mod :: '_' | boolean() | undefined, + is_ebin_mod :: '_' | boolean() | undefined, + uses_mods :: '$2' | [mod_name()] | undefined, + exists :: '_' | boolean() | undefined, %% Dynamic - status :: '_' | status(), - used_by_mods :: '_' | [mod_name()], - is_pre_included :: '_' | boolean() | undefined, - is_included :: '_' | boolean() | undefined + status = ok :: '_' | status(), + used_by_mods = [] :: '_' | [mod_name()], + is_pre_included :: '_' | boolean() | undefined, + is_included :: '_' | boolean() | undefined }). -record(app_info, @@ -177,10 +177,10 @@ name :: '_' | app_name(), is_escript :: '_' | boolean() | {inlined, escript_app_name()}, use_selected_vsn :: '_' | vsn | dir | undefined, - active_dir :: '_' | dir(), + active_dir :: '_' | dir() | undefined, sorted_dirs :: '_' | [dir()], - vsn :: '_' | app_vsn(), - label :: '_' | app_label(), + vsn :: '_' | app_vsn() | undefined, + label :: '_' | app_label() | undefined, info :: '_' | #app_info{} | undefined, mods :: '_' | [#mod{}], @@ -192,21 +192,21 @@ debug_info :: '_' | debug_info() | undefined, app_file :: '_' | app_file() | undefined, app_type :: '_' | app_type() | undefined, - incl_app_filters :: '_' | [#regexp{}], - excl_app_filters :: '_' | [#regexp{}], - incl_archive_filters :: '_' | [#regexp{}], - excl_archive_filters :: '_' | [#regexp{}], - archive_opts :: '_' | [archive_opt()], + incl_app_filters :: '_' | [#regexp{}] | undefined, + excl_app_filters :: '_' | [#regexp{}] | undefined, + incl_archive_filters :: '_' | [#regexp{}] | undefined, + excl_archive_filters :: '_' | [#regexp{}] | undefined, + archive_opts :: '_' | [archive_opt()] | undefined, %% Dynamic status :: '_' | status(), - uses_mods :: '_' | [mod_name()], - used_by_mods :: '_' | [mod_name()], - uses_apps :: '_' | [app_name()], - used_by_apps :: '_' | [app_name()], + uses_mods :: '_' | [mod_name()] | undefined, + used_by_mods :: '_' | [mod_name()] | undefined, + uses_apps :: '_' | [app_name()] | undefined, + used_by_apps :: '_' | [app_name()] | undefined, is_pre_included :: '_' | '$2' | boolean() | undefined, is_included :: '_' | '$1' | boolean() | undefined, - rels :: '_' | [rel_name()] + rels :: '_' | [rel_name()] | undefined }). -record(rel_app, @@ -237,7 +237,7 @@ rels :: [#rel{}], emu_name :: emu_name(), profile :: profile(), - excl_lib :: excl_lib(), + excl_lib :: excl_lib() | undefined, incl_sys_filters :: [#regexp{}], excl_sys_filters :: [#regexp{}], incl_app_filters :: [#regexp{}], -- cgit v1.2.3 From 18042b7fd5510cfa355cc6ce057ba5b936a7c498 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 12:39:26 +0200 Subject: Update Inets A record field type has been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/inets/src/tftp/tftp_engine.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/tftp/tftp_engine.erl b/lib/inets/src/tftp/tftp_engine.erl index d0510e795b..282a97e720 100644 --- a/lib/inets/src/tftp/tftp_engine.erl +++ b/lib/inets/src/tftp/tftp_engine.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -63,7 +63,8 @@ -record(file_info, {peer_req, pid}). -record(sys_misc, {module, function, arguments}). -record(error, {where, code, text, filename}). --record(prepared, {status :: prep_status(), result, block_no, next_data, prev_data}). +-record(prepared, {status :: prep_status() | 'undefined', + result, block_no, next_data, prev_data}). -record(transfer_res, {status, decoded_msg, prepared}). -define(ERROR(Where, Code, Text, Filename), #error{where = Where, code = Code, text = Text, filename = Filename}). -- cgit v1.2.3 From b3bf0e29bb884ff5296fa61012066ae619d531f6 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 12:46:21 +0200 Subject: Update Eunit A record field type has been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/eunit/src/eunit_surefire.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl index f3e58a3d1c..1b468551d8 100644 --- a/lib/eunit/src/eunit_surefire.erl +++ b/lib/eunit/src/eunit_surefire.erl @@ -56,7 +56,11 @@ { name :: chars(), description :: chars(), - result :: ok | {failed, tuple()} | {aborted, tuple()} | {skipped, term()}, + result :: ok + | {failed, tuple()} + | {aborted, tuple()} + | {skipped, term()} + | undefined, time :: integer(), output :: binary() }). -- cgit v1.2.3 From fb18a3f184ac47b07c801b88b9d166ae52ba757d Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 29 Sep 2015 14:24:57 +0200 Subject: Update Diameter Record field types have been modified due to commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/diameter/src/base/diameter_peer_fsm.erl | 2 +- lib/diameter/src/base/diameter_service.erl | 2 +- lib/diameter/src/transport/diameter_sctp.erl | 12 +++++++----- lib/diameter/src/transport/diameter_tcp.erl | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl index 2b23183d18..fb874013a3 100644 --- a/lib/diameter/src/base/diameter_peer_fsm.erl +++ b/lib/diameter/src/base/diameter_peer_fsm.erl @@ -117,7 +117,7 @@ parent :: pid(), %% watchdog process transport :: pid(), %% transport process dictionary :: module(), %% common dictionary - service :: #diameter_service{}, + service :: #diameter_service{} | undefined, dpr = false :: false | true %% DPR received, DPA sent | {boolean(), uint32(), uint32()}, diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 13508321c3..86781c02bf 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -137,7 +137,7 @@ %% Record representing an RFC 3539 watchdog process implemented by %% diameter_watchdog. -record(watchdog, - {pid :: match(pid()), + {pid :: match(pid()) | undefined, type :: match(connect | accept), ref :: match(reference()), %% key into diameter_config options :: match([diameter:transport_opt()]),%% from start_transport diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 678dc9b5d6..8a80ce630a 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -84,16 +84,18 @@ %% Accepting/connecting transport process state. -record(transport, - {parent :: pid(), + {parent :: pid() | undefined, mode :: {accept, pid()} | accept | {connect, {[inet:ip_address()], uint(), list()}} %% {RAs, RP, Errors} | connect, - socket :: gen_sctp:sctp_socket(), + socket :: gen_sctp:sctp_socket() | undefined, assoc_id :: gen_sctp:assoc_id(), %% association identifier - peer :: {[inet:ip_address()], uint()}, %% {RAs, RP} - streams :: {uint(), uint()}, %% {InStream, OutStream} counts + peer :: {[inet:ip_address()], uint()} %% {RAs, RP} + | undefined, + streams :: {uint(), uint()} %% {InStream, OutStream} counts + | undefined, os = 0 :: uint()}). %% next output stream %% Listener process state. @@ -102,7 +104,7 @@ socket :: gen_sctp:sctp_socket(), count = 0 :: uint(), %% attached transport processes pending = {0, queue:new()}, - tref :: reference(), + tref :: reference() | undefined, accept :: [match()]}). %% Field pending implements two queues: the first of transport-to-be %% processes to which an association has been assigned but for which diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index 005b2442c0..c79d85820b 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -73,7 +73,7 @@ %% Listener process state. -record(listener, {socket :: inet:socket(), count = 1 :: non_neg_integer(), - tref :: reference()}). + tref :: reference() | undefined}). %% Monitor process state. -record(monitor, -- cgit v1.2.3 From 13c39e40ff18ab1ab5ddeb0a5bde99658e3fab74 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 30 Sep 2015 12:07:23 +0200 Subject: Update Debugger The update was motivated by commit 8ce35b2: "Take out automatic insertion of 'undefined' from typed record fields". --- lib/debugger/src/dbg_wx_win.erl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/debugger/src/dbg_wx_win.erl b/lib/debugger/src/dbg_wx_win.erl index 63f74392b5..1ff8818bbe 100644 --- a/lib/debugger/src/dbg_wx_win.erl +++ b/lib/debugger/src/dbg_wx_win.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -95,10 +95,9 @@ create_menu_item(Menu, [{Name, _N, cascade, Items}|Is], Win, Id0,Connect) -> false -> Acc end end, - Filter = fun(_,_) -> + Filter = fun(Ev,_) -> Enabled = lists:foldl(IsChecked, [], Butts), - Self ! #wx{userData={Name, Enabled}, - event=#wxCommand{type=command_menu_selected}} + Self ! Ev#wx{userData={Name, Enabled}} end, wxMenu:connect(Win, command_menu_selected, [{id,Id0},{lastId, Id-1},{callback,Filter}]), -- cgit v1.2.3 From 38be5f936a3ed12a01f4f4441dbaa6b4d084d01f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 9 Oct 2015 12:42:32 +0200 Subject: ssh: added 'after' to receive stmts in test/ --- lib/ssh/test/ssh_basic_SUITE.erl | 20 +++++++++++++++++-- lib/ssh/test/ssh_connection_SUITE.erl | 36 ++++++++++++++++++++++++++++++++++- lib/ssh/test/ssh_options_SUITE.erl | 14 +++++++++++--- lib/ssh/test/ssh_protocol_SUITE.erl | 2 ++ lib/ssh/test/ssh_sftp_SUITE.erl | 6 ++++++ lib/ssh/test/ssh_sftpd_SUITE.erl | 2 ++ lib/ssh/test/ssh_test_lib.erl | 6 +++++- lib/ssh/test/ssh_to_openssh_SUITE.erl | 10 +++++++++- 8 files changed, 88 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 7f1a64f094..24d8a4e53c 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -473,6 +473,8 @@ shell(Config) when is_list(Config) -> ErlShellStart -> ct:log("Erlang shell start: ~p~n", [ErlShellStart]), do_shell(IO, Shell) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -501,11 +503,15 @@ cli(Config) when is_list(Config) -> {ssh_cm, ConnectionRef, {data,0,0, <<"\r\nYou are accessing a dummy, type \"q\" to exit\r\n\n">>}} -> ok = ssh_connection:send(ConnectionRef, ChannelId, <<"q">>) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId}} -> ok + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -644,7 +650,7 @@ peername_sockname(Config) when is_list(Config) -> host_equal(HostSockSrv, Host), PortSockSrv = Port after 10000 -> - throw(timeout) + ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. host_equal(H1, H2) -> @@ -678,7 +684,7 @@ close(Config) when is_list(Config) -> {ssh_cm, Client,{closed, ChannelId}} -> ok after 5000 -> - ct:fail(timeout) + ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -876,22 +882,32 @@ do_shell(IO, Shell) -> receive Echo0 -> ct:log("Echo: ~p ~n", [Echo0]) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive ?NEWLINE -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive Result0 = <<"2">> -> ct:log("Result: ~p~n", [Result0]) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive ?NEWLINE -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive ErlPrompt1 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt1]) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, exit(Shell, kill). %%Does not seem to work in the testserver! diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index fbcf06290a..dc7476f761 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -119,20 +119,28 @@ simple_exec(Config) when is_list(Config) -> receive {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"testing\n">>}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, %% receive close messages receive {ssh_cm, ConnectionRef, {eof, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -154,20 +162,28 @@ small_cat(Config) when is_list(Config) -> receive {ssh_cm, ConnectionRef, {data, ChannelId0, 0, Data}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, %% receive close messages receive {ssh_cm, ConnectionRef, {eof, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- big_cat() -> @@ -211,11 +227,15 @@ big_cat(Config) when is_list(Config) -> %% receive close messages (eof already consumed) receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}} -> - ok + ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- @@ -234,14 +254,20 @@ send_after_exit(Config) when is_list(Config) -> receive {ssh_cm, ConnectionRef, {eof, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef, {exit_status, ChannelId0, _ExitStatus}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, receive {ssh_cm, ConnectionRef,{closed, ChannelId0}} -> ok + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, case ssh_connection:send(ConnectionRef, ChannelId0, Data, 2000) of {error, closed} -> ok; @@ -455,6 +481,8 @@ gracefull_invalid_version(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. gracefull_invalid_start(Config) when is_list(Config) -> @@ -475,6 +503,8 @@ gracefull_invalid_start(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. gracefull_invalid_long_start(Config) when is_list(Config) -> @@ -495,6 +525,8 @@ gracefull_invalid_long_start(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. @@ -516,6 +548,8 @@ gracefull_invalid_long_start_no_nl(Config) when is_list(Config) -> {tcp_closed, S} -> ok end + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. stop_listener() -> diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index d64c78da35..cf15ca4253 100644 --- a/lib/ssh/test/ssh_options_SUITE.erl +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -656,6 +656,8 @@ ssh_connect_arg4_timeout(_Config) -> %% Get listening port Port = receive {port,Server,ServerPort} -> ServerPort + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, %% try to connect with a timeout, but "supervise" it @@ -861,6 +863,8 @@ ssh_connect_nonegtimeout_connected(Config, Parallel) -> ct:sleep(round(Factor * NegTimeOut)), one_shell_op(IO, NegTimeOut) + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, exit(Shell, kill). @@ -869,13 +873,13 @@ one_shell_op(IO, TimeOut) -> ct:log("One shell op: Waiting for prompter"), receive ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0]) - after TimeOut -> ct:fail("Timeout waiting for promter") + after TimeOut -> ct:fail("Timeout waiting for promter") end, IO ! {input, self(), "2*3*7.\r\n"}, receive Echo0 -> ct:log("Echo: ~p ~n", [Echo0]) - after TimeOut -> ct:fail("Timeout waiting for echo") + after TimeOut -> ct:fail("Timeout waiting for echo") end, receive @@ -888,7 +892,7 @@ one_shell_op(IO, TimeOut) -> receive Result0 -> ct:log("Result: ~p~n", [Result0]) - after TimeOut -> ct:fail("Timeout waiting for result") + after TimeOut -> ct:fail("Timeout waiting for result") end. %%-------------------------------------------------------------------- @@ -1016,9 +1020,13 @@ fake_daemon(_Config) -> {ok,S} = Rsa, receive {tcp, S, Id} -> Parent ! {id,self(),Id} + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end end), %% Get listening host and port receive {sockname,Server,ServerHost,ServerPort} -> {Server, ServerHost, ServerPort} + after + 10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 406f8e5960..743282ce9c 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -327,6 +327,8 @@ no_common_alg_client_disconnects(Config) -> X -> ct:log("¤¤¤¤¤"), ct:fail(X) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 32fdec9842..698af259c8 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -526,6 +526,8 @@ async_read(Config) when is_list(Config) -> ok; Msg -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. %%-------------------------------------------------------------------- async_write() -> @@ -593,6 +595,8 @@ pos_read(Config) when is_list(Config) -> ok; Msg -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, NewData1 = "hopp", @@ -618,6 +622,8 @@ pos_write(Config) when is_list(Config) -> ok; Msg -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end, ok = ssh_sftp:pwrite(Sftp, Handle, eof, list_to_binary("!")), diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 94a54ec9db..6b03a2b763 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -683,6 +683,8 @@ reply(Cm, Channel, RBuf) -> closed; {ssh_cm, Cm, Msg} -> ct:fail(Msg) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index cc3ebf8151..87eaeec1bc 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -163,7 +163,9 @@ loop_io_server(TestCase, Buff0) -> {'EXIT',_, _} -> erlang:display('ssh_test_lib:loop_io_server/2 EXIT'), ok - end. + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + end. io_request({put_chars, Chars}, TestCase, _, _, Buff) -> reply(TestCase, Chars), @@ -212,6 +214,8 @@ receive_exec_result(Msg) -> Other -> ct:log("Other ~p", [Other]), {unexpected_msg, Other} + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index c0dee6a1d3..026fe545c1 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -653,6 +653,8 @@ receive_hej() -> ct:log("Extra info: ~p~n", [Info]), receive_hej() end + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. receive_logout() -> @@ -662,11 +664,15 @@ receive_logout() -> receive <<"Connection closed">> -> ok + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end; Info -> ct:log("Extra info when logging out: ~p~n", [Info]), receive_logout() - end. + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + end. receive_normal_exit(Shell) -> receive @@ -676,6 +682,8 @@ receive_normal_exit(Shell) -> receive_normal_exit(Shell); Other -> ct:fail({unexpected_msg, Other}) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. extra_logout() -> -- cgit v1.2.3 From d94a8ef6dc136dd2eedf3c3ad4bc053ca8fdd1b0 Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Mon, 12 Oct 2015 07:53:20 +0200 Subject: Fix edge case of Size = 0 in bs_put_integer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit copy_offset_int_big was assuming (Offset + Size - 1) (Tmp9 in the first BB) would not underflow. It was also unconditionally reading and writing the binary even when Size was zero, unlike copy_int_little, which is the only other case of bs_put_integer that does not have a short-circuit on Size = 0. This was causing segfaults when constructing binaries starting with a zero-length integer field, because a logical right shift was used to compute an offset in bytes (which became 0x1fffffffffffffff) to read in the binary. Tests, taken from the emulator bs_construct_SUITE, were also added. The complete credit for the report and the fix goes to Magnus Lång. --- lib/hipe/rtl/hipe_rtl_binary_construct.erl | 9 ++++++--- lib/hipe/test/bs_SUITE_data/bs_construct.erl | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/hipe/rtl/hipe_rtl_binary_construct.erl b/lib/hipe/rtl/hipe_rtl_binary_construct.erl index 40bd22aa8e..692bad7d96 100644 --- a/lib/hipe/rtl/hipe_rtl_binary_construct.erl +++ b/lib/hipe/rtl/hipe_rtl_binary_construct.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1192,7 +1192,10 @@ copy_little_word(Base, Offset, NewOffset, Word) -> hipe_rtl:mk_store(Base, TmpOffset, Word, byte), hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(32))]. -copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -> +copy_offset_int_big(_Base, Offset, NewOffset, 0, _Tmp1) -> + [hipe_rtl:mk_move(NewOffset, Offset)]; +copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) + when is_integer(Size), Size > 0 -> Tmp2 = hipe_rtl:mk_new_reg(), Tmp3 = hipe_rtl:mk_new_reg(), Tmp4 = hipe_rtl:mk_new_reg(), @@ -1203,7 +1206,7 @@ copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) - Tmp9 = hipe_rtl:mk_new_reg(), OldByte = hipe_rtl:mk_new_reg(), TmpOffset = hipe_rtl:mk_new_reg(), - BranchLbl = hipe_rtl:mk_new_label(), + BranchLbl = hipe_rtl:mk_new_label(), BodyLbl = hipe_rtl:mk_new_label(), EndLbl = hipe_rtl:mk_new_label(), NextLbl = hipe_rtl:mk_new_label(), diff --git a/lib/hipe/test/bs_SUITE_data/bs_construct.erl b/lib/hipe/test/bs_SUITE_data/bs_construct.erl index 9cc9ac848c..37a54c1981 100644 --- a/lib/hipe/test/bs_SUITE_data/bs_construct.erl +++ b/lib/hipe/test/bs_SUITE_data/bs_construct.erl @@ -13,6 +13,7 @@ test() -> ok = bs5(), 16#10000008 = bit_size(large_bin(1, 2, 3, 4)), ok = bad_ones(), + ok = zero_width(), ok. %%-------------------------------------------------------------------- @@ -126,3 +127,18 @@ bad_ones() -> Bin123 = <<1,2,3>>, ?FAIL(<>), ok. + +%%-------------------------------------------------------------------- +%% Taken from the emulator bs_construct_SUITE - seg faulted till 18.1 + +zero_width() -> + Z = id(0), + Small = id(42), + Big = id(1 bsl 128), % puts stuff on the heap + <<>> = <>, + <<>> = <>, + <<>> = <>, + <<>> = <>, + ok. + +id(X) -> X. -- cgit v1.2.3 From 93a49adc5a174a034bba0431f1e8119a1f30dec6 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 12 Oct 2015 12:59:04 +0200 Subject: ssh: updatated spec for ssh:daemon --- lib/ssh/src/ssh.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 132de71aed..15591fb4a7 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -117,9 +117,9 @@ channel_info(ConnectionRef, ChannelId, Options) -> ssh_connection_handler:channel_info(ConnectionRef, ChannelId, Options). %%-------------------------------------------------------------------- --spec daemon(integer()) -> {ok, pid()}. --spec daemon(integer(), proplists:proplist()) -> {ok, pid()}. --spec daemon(any | inet:ip_address(), integer(), proplists:proplist()) -> {ok, pid()}. +-spec daemon(integer()) -> {ok, pid()} | {error, term()}. +-spec daemon(integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}. +-spec daemon(any | inet:ip_address(), integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}. %% Description: Starts a server listening for SSH connections %% on the given port. -- cgit v1.2.3 From 929709c2a0aa26b31b59b4c04e2534dd906b4afc Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 12 Oct 2015 14:38:21 +0200 Subject: ssh: add info on GEX algos in ssh_alghoritms:init_suite --- lib/ssh/test/ssh_algorithms_SUITE.erl | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index 1188b324ba..9f388de2a7 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -23,6 +23,7 @@ -module(ssh_algorithms_SUITE). -include_lib("common_test/include/ct.hrl"). +-include_lib("ssh/src/ssh_transport.hrl"). %% Note: This directive should only be used in test suites. -compile(export_all). @@ -72,11 +73,19 @@ init_per_suite(Config) -> "OS ssh:~n=======~n~p~n~n~n" "Erl ssh:~n========~n~p~n~n~n" "Installed ssh client:~n=====================~n~p~n~n~n" - "Installed ssh server:~n=====================~n~p~n~n~n", - [os:cmd("ssh -V"), + "Installed ssh server:~n=====================~n~p~n~n~n" + "Misc values:~n============~n" + " -- Default dh group exchange parameters ({min,def,max}): ~p~n" + " -- dh_default_groups: ~p~n" + " -- Max num algorithms: ~p~n" + ,[os:cmd("ssh -V"), ssh:default_algorithms(), ssh_test_lib:default_algorithms(sshc), - ssh_test_lib:default_algorithms(sshd)]), + ssh_test_lib:default_algorithms(sshd), + {?DEFAULT_DH_GROUP_MIN,?DEFAULT_DH_GROUP_NBITS,?DEFAULT_DH_GROUP_MAX}, + [KeyLen || {KeyLen,_} <- ?dh_default_groups], + ?MAX_NUM_ALGORITHMS + ]), ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]), catch crypto:stop(), case catch crypto:start() of @@ -271,7 +280,8 @@ specific_test_cases(Tag, Alg, SshcAlgos, SshdAlgos) -> [] end ++ case {Tag,Alg} of - {kex,'diffie-hellman-group-exchange-sha1'} -> + {kex,_} when Alg == 'diffie-hellman-group-exchange-sha1' ; + Alg == 'diffie-hellman-group-exchange-sha256' -> [simple_exec_group14, simple_exec_group15, simple_exec_group16, -- cgit v1.2.3 From ba6603d2f3b4853bfbaeecdec6413ecee19f84d4 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 8 Oct 2015 16:45:28 +0200 Subject: ssh: set dh_gex default to group14 --- lib/ssh/src/ssh_transport.hrl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 96ab1bb668..17a0daebe3 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -33,7 +33,7 @@ -define(MAX_NUM_ALGORITHMS, 200). -define(DEFAULT_DH_GROUP_MIN, 1024). --define(DEFAULT_DH_GROUP_NBITS, 6144). +-define(DEFAULT_DH_GROUP_NBITS, 2048). -define(DEFAULT_DH_GROUP_MAX, 8192). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From dae6f3c7bf111db1b1b62b0f0c7af4bbd856d67f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 9 Oct 2015 10:44:21 +0200 Subject: ssh: polished ssh.xml Some changes in the SSH section at top (supported algorithms). Added links to default_algorithms and preferred_algorithms in the SSH section. --- lib/ssh/doc/src/ssh.xml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index c7a09d65a8..b938da091c 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -40,19 +40,24 @@ For application dependencies see ssh(6) Supported SSH version is 2.0. - Supported public key algorithms:ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa and ssh-dss. - Supported MAC algorithms: hmac-sha2-512, hmac-sha2-256 and hmac-sha1. - Supported MAC algorithms: hmac-sha2-256 and hmac-sha1. + Supported public key algorithms: ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa and ssh-dss. + Supported MAC algorithms: hmac-sha2-256, hmac-sha2-512 and hmac-sha1. Supported encryption algorithms: aes256-ctr, aes192-ctr, aes128-ctr, aes128-cb and 3des-cbc. - Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256. - Supported compression algorithms: none, zlib@openssh.com, zlib + Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group-exchange-sha256 and diffie-hellman-group1-sha1 + Supported compression algorithms: none, zlib@openssh.com and zlib Supports unicode filenames if the emulator and the underlaying OS support it. See section DESCRIPTION in the file manual page in kernel for information about this subject. Supports unicode in shell and CLI. - +

The actual set of algorithms can vary depending on which OpenSSL crypto library that is installed on the machine. + For the list on a particular installation, use the command default_algorithms/0. + The user may override the default algorithm configuration both on the server side and the client side. + See the option preferred_algorithms in the daemon and + connect functions. +

+
-- cgit v1.2.3 From f8750f121176c6cedc7b3162b6656ce201c9fe97 Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Mon, 20 Jul 2015 16:38:33 +0300 Subject: inets: fix suppport of HTTP headers with obs-fold httpc should not fail when response contains (now deprecated) multiline HTTP headers constructed with obs-folds. And as RFC7230 specifies user agent should replace obs-folds with spaces. --- lib/inets/src/http_lib/http_response.erl | 30 +++++++++++++++++++++--------- lib/inets/test/httpc_SUITE.erl | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_response.erl b/lib/inets/src/http_lib/http_response.erl index 58b30c4e9e..d13670700c 100644 --- a/lib/inets/src/http_lib/http_response.erl +++ b/lib/inets/src/http_lib/http_response.erl @@ -31,16 +31,11 @@ %% Value - string() %% %% Description: Creates a http_response_h-record used internally to -%% handle http-headers. +%% handle http-headers, assumes reversed list of headers +%% to unfold multiline headers with obs-folds %%------------------------------------------------------------------------- -headers([], Headers) -> - Headers; - -headers([Header | Tail], Headers) -> - {Key, [$: | Value]} = - lists:splitwith(fun($:) -> false; (_) -> true end, Header), - headers(Tail, headers(http_util:to_lower(string:strip(Key)), - string:strip(Value), Headers)). +headers(RevLines, Headers) -> + fill_headers(RevLines, [], Headers). %%------------------------------------------------------------------------- %% headers(#http_response_h{}) -> HeaderList @@ -68,6 +63,23 @@ header_list(Headers) -> %%%======================================================================== %%% Internal functions %%%======================================================================== +fill_headers([], _, Headers) -> + Headers; +fill_headers([[Ch|HeaderFold]|Tail], Folded, Headers) + when Ch == $\t; Ch == $\s -> + fill_headers(Tail, [HeaderFold|Folded], Headers); +fill_headers([Header | Tail], Folded, Headers) -> + Unfolded = unfold([Header|Folded]), + {Key, [$: | Value]} = + lists:splitwith(fun($:) -> false; (_) -> true end, Unfolded), + fill_headers(Tail, [], headers(http_util:to_lower(string:strip(Key)), + string:strip(Value), Headers)). + +unfold([L]) -> + L; +unfold(Folded) -> + string:join(Folded, " "). + headers("cache-control", Value, Headers) -> Headers#http_response_h{'cache-control'= Value}; headers("connection", Value, Headers) -> diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 5b40d08859..2ad00bdf76 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -105,6 +105,7 @@ only_simulated() -> internal_server_error, invalid_http, headers_dummy, + headers_with_obs_fold, empty_response_header, remote_socket_close, remote_socket_close_async, @@ -893,6 +894,13 @@ headers_dummy(Config) when is_list(Config) -> %%------------------------------------------------------------------------- +headers_with_obs_fold(Config) when is_list(Config) -> + Request = {url(group_name(Config), "/obs_folded_headers.html", Config), []}, + {ok, {{_,200,_}, Headers, [_|_]}} = httpc:request(get, Request, [], []), + "a b" = proplists:get_value("folded", Headers). + +%%------------------------------------------------------------------------- + invalid_headers(Config) -> Request = {url(group_name(Config), "/dummy.html", Config), [{"cookie", undefined}]}, {error, _} = httpc:request(get, Request, [], []). @@ -1713,6 +1721,13 @@ handle_uri(_,"/dummy_headers.html",_,_,Socket,_) -> send(Socket, http_chunk:encode("obar")), http_chunk:encode_last(); +handle_uri(_,"/obs_folded_headers.html",_,_,_,_) -> + "HTTP/1.1 200 ok\r\n" + "Content-Length:5\r\n" + "Folded: a\r\n" + " b\r\n\r\n" + "Hello"; + handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) -> Head = "HTTP/1.1 200 ok\r\n" ++ "Transfer-Encoding:Chunked\r\n\r\n", -- cgit v1.2.3 From e4ee8ea94407726d36de6146878ca21cff6e1854 Mon Sep 17 00:00:00 2001 From: Kirill Zaborsky Date: Fri, 28 Aug 2015 15:23:26 +0300 Subject: Small misprint --- lib/os_mon/doc/src/cpu_sup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/os_mon/doc/src/cpu_sup.xml b/lib/os_mon/doc/src/cpu_sup.xml index 524426ce86..51e1a4c9d6 100644 --- a/lib/os_mon/doc/src/cpu_sup.xml +++ b/lib/os_mon/doc/src/cpu_sup.xml @@ -63,7 +63,7 @@ measure.

A server which receives just enough requests to never become idle will score a CPU utilization of 100%. If the server receives - 50% more requests, it will still scores 100%. When the system load + 50% more requests, it will still score 100%. When the system load is calculated with the percentage formula shown previously, the load will increase from 80% to 87%.

The avg1/0, avg5/0, and avg15/0 functions -- cgit v1.2.3 From ad264b2ac5724e3043b7dafa09eb4da0b971bf8e Mon Sep 17 00:00:00 2001 From: Riccardo Date: Sat, 10 Oct 2015 16:00:09 +0200 Subject: Fixed typo in ets documentation --- lib/stdlib/doc/src/ets.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index 03b995e4de..ee2bf96cb7 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -916,7 +916,7 @@ ets:select(Table,MatchSpec),

{keypos,Pos} - Specfies which element in the stored tuples should be + Specifies which element in the stored tuples should be used as key. By default, it is the first element, i.e. Pos=1. However, this is not always appropriate. In particular, we do not want the first element to be the -- cgit v1.2.3 From 3b28f0d9bbc9e5745fb95e48e6daf9179461116b Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Thu, 24 Sep 2015 15:19:52 +0300 Subject: inets: scheme validation fun for http_uri http_uri:parse_scheme function should allow checking scheme of URIs otherwise it could be easily abused to reach limit number of atoms in the VM --- lib/inets/doc/src/http_uri.xml | 13 ++++++++++++- lib/inets/src/http_lib/http_uri.erl | 31 ++++++++++++++++++++++++------- lib/inets/test/uri_SUITE.erl | 23 ++++++++++++++++++++++- 3 files changed, 58 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml index 47c40da96a..64e6c7a6cc 100644 --- a/lib/inets/doc/src/http_uri.xml +++ b/lib/inets/doc/src/http_uri.xml @@ -117,7 +117,8 @@ Options = [Option] Option = {ipv6_host_with_brackets, boolean()} | {scheme_defaults, scheme_defaults()} | - {fragment, boolean()}] + {fragment, boolean()} | + {schema_validation_fun, fun()}] Result = {Scheme, UserInfo, Host, Port, Path, Query} | {Scheme, UserInfo, Host, Port, Path, Query, Fragment} UserInfo = user_info() @@ -141,6 +142,16 @@

If the fragment option is true, the URI fragment is returned as part of the parsing result, otherwise it is ignored.

+

Scheme validation fun is to be defined as follows: + + +fun(SchemeStr :: string()) -> + valid | {error, Reason :: term()}. + + + It is called before scheme string gets converted into scheme atom and + thus possible atom leak could be prevented

+ diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl index 79591eec29..6fe8c1776d 100644 --- a/lib/inets/src/http_lib/http_uri.erl +++ b/lib/inets/src/http_lib/http_uri.erl @@ -138,16 +138,33 @@ parse_scheme(AbsURI, Opts) -> {error, no_scheme} -> {error, no_scheme}; {SchemeStr, Rest} -> - Scheme = list_to_atom(http_util:to_lower(SchemeStr)), - SchemeDefaults = which_scheme_defaults(Opts), - case lists:keysearch(Scheme, 1, SchemeDefaults) of - {value, {Scheme, DefaultPort}} -> - {Scheme, DefaultPort, Rest}; - false -> - {Scheme, no_default_port, Rest} + case extract_scheme(SchemeStr, Opts) of + {error, Error} -> + {error, Error}; + {ok, Scheme} -> + SchemeDefaults = which_scheme_defaults(Opts), + case lists:keysearch(Scheme, 1, SchemeDefaults) of + {value, {Scheme, DefaultPort}} -> + {Scheme, DefaultPort, Rest}; + false -> + {Scheme, no_default_port, Rest} + end end end. +extract_scheme(Str, Opts) -> + case lists:keysearch(scheme_validation_fun, 1, Opts) of + {value, {scheme_validation_fun, Fun}} when is_function(Fun) -> + case Fun(Str) of + valid -> + {ok, list_to_atom(http_util:to_lower(Str))}; + {error, Error} -> + {error, Error} + end; + _ -> + {ok, list_to_atom(http_util:to_lower(Str))} + end. + parse_uri_rest(Scheme, DefaultPort, "//" ++ URIPart, Opts) -> {Authority, PathQueryFragment} = split_uri(URIPart, "[/?#]", {URIPart, ""}, 1, 0), diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl index bfcd7bd339..2642b8fd4e 100644 --- a/lib/inets/test/uri_SUITE.erl +++ b/lib/inets/test/uri_SUITE.erl @@ -49,7 +49,8 @@ all() -> queries, fragments, escaped, - hexed_query + hexed_query, + scheme_validation ]. %%-------------------------------------------------------------------- @@ -175,6 +176,26 @@ hexed_query(Config) when is_list(Config) -> verify_uri(URI2, Verify2), verify_uri(URI3, Verify3). +scheme_validation(Config) when is_list(Config) -> + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment"), + + ValidationFun = + fun("http") -> valid; + (_) -> {error, bad_scheme} + end, + + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + {error, bad_scheme} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + %% non-fun scheme_validation_fun works as no option passed + {ok, {https,[],"localhost",443,"/",""}} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, none}]). + %%-------------------------------------------------------------------- %% Internal Functions ------------------------------------------------ -- cgit v1.2.3 From e3f1601f4cb16ebe68f145e366f78cff9d15beae Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 13 Oct 2015 14:47:34 +0200 Subject: Update release notes --- lib/ssh/doc/src/notes.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'lib') diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 368bb0f552..0c0c947f65 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,23 @@ notes.xml +
Ssh 4.1.1 + +
Improvements and New Features + + +

+ A new option max_channels limits the number of + channels with active server-side subsystems that are + accepted.

+

+ Own Id: OTP-13036

+
+
+
+ +
+
Ssh 4.1
Fixed Bugs and Malfunctions -- cgit v1.2.3 From d8ff1e37c38c37304fb44ba6618da141e4d08c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 12 Oct 2015 12:21:15 +0200 Subject: Remove the deprecated webtool application --- lib/Makefile | 2 +- lib/sasl/test/systools_SUITE.erl | 5 - lib/tools/Makefile | 2 +- lib/tools/doc/src/cover_chapter.xml | 43 - lib/tools/priv/.gitignore | 0 lib/tools/priv/Makefile | 69 -- lib/tools/priv/cover.tool | 2 - lib/tools/priv/index.html | 10 - lib/tools/src/Makefile | 1 - lib/tools/src/cover.erl | 4 +- lib/tools/src/cover_web.erl | 1185 ----------------------- lib/tools/src/tools.app.src | 5 +- lib/webtool/AUTHORS | 4 - lib/webtool/Makefile | 39 - lib/webtool/doc/html/.gitignore | 0 lib/webtool/doc/man1/.gitignore | 0 lib/webtool/doc/man3/.gitignore | 0 lib/webtool/doc/pdf/.gitignore | 0 lib/webtool/doc/src/Makefile | 132 --- lib/webtool/doc/src/book.xml | 48 - lib/webtool/doc/src/fascicules.xml | 18 - lib/webtool/doc/src/notes.xml | 253 ----- lib/webtool/doc/src/notes_history.xml | 74 -- lib/webtool/doc/src/part.xml | 38 - lib/webtool/doc/src/part_notes.xml | 40 - lib/webtool/doc/src/part_notes_history.xml | 40 - lib/webtool/doc/src/ref_man.xml | 39 - lib/webtool/doc/src/start_webtool.xml | 104 -- lib/webtool/doc/src/webtool.xml | 157 --- lib/webtool/doc/src/webtool_chapter.xml | 246 ----- lib/webtool/ebin/.gitignore | 0 lib/webtool/info | 2 - lib/webtool/priv/Makefile | 82 -- lib/webtool/priv/bin/start_webtool | 3 - lib/webtool/priv/bin/start_webtool.bat | 2 - lib/webtool/priv/root/conf/mime.types | 99 -- lib/webtool/priv/root/doc/index.html | 11 - lib/webtool/priv/root/doc/start_info.html | 28 - lib/webtool/priv/root/doc/tool_management.html | 9 - lib/webtool/src/Makefile | 98 -- lib/webtool/src/webtool.app.src | 28 - lib/webtool/src/webtool.appup.src | 22 - lib/webtool/src/webtool.erl | 1208 ------------------------ lib/webtool/src/webtool_sup.erl | 75 -- lib/webtool/test/Makefile | 65 -- lib/webtool/test/webtool.spec | 1 - lib/webtool/test/webtool_SUITE.erl | 51 - lib/webtool/vsn.mk | 1 - 48 files changed, 5 insertions(+), 4340 deletions(-) create mode 100644 lib/tools/priv/.gitignore delete mode 100644 lib/tools/priv/Makefile delete mode 100644 lib/tools/priv/cover.tool delete mode 100644 lib/tools/priv/index.html delete mode 100644 lib/tools/src/cover_web.erl delete mode 100644 lib/webtool/AUTHORS delete mode 100644 lib/webtool/Makefile delete mode 100644 lib/webtool/doc/html/.gitignore delete mode 100644 lib/webtool/doc/man1/.gitignore delete mode 100644 lib/webtool/doc/man3/.gitignore delete mode 100644 lib/webtool/doc/pdf/.gitignore delete mode 100644 lib/webtool/doc/src/Makefile delete mode 100644 lib/webtool/doc/src/book.xml delete mode 100644 lib/webtool/doc/src/fascicules.xml delete mode 100644 lib/webtool/doc/src/notes.xml delete mode 100644 lib/webtool/doc/src/notes_history.xml delete mode 100644 lib/webtool/doc/src/part.xml delete mode 100644 lib/webtool/doc/src/part_notes.xml delete mode 100644 lib/webtool/doc/src/part_notes_history.xml delete mode 100644 lib/webtool/doc/src/ref_man.xml delete mode 100644 lib/webtool/doc/src/start_webtool.xml delete mode 100644 lib/webtool/doc/src/webtool.xml delete mode 100644 lib/webtool/doc/src/webtool_chapter.xml delete mode 100644 lib/webtool/ebin/.gitignore delete mode 100644 lib/webtool/info delete mode 100644 lib/webtool/priv/Makefile delete mode 100755 lib/webtool/priv/bin/start_webtool delete mode 100644 lib/webtool/priv/bin/start_webtool.bat delete mode 100644 lib/webtool/priv/root/conf/mime.types delete mode 100644 lib/webtool/priv/root/doc/index.html delete mode 100644 lib/webtool/priv/root/doc/start_info.html delete mode 100644 lib/webtool/priv/root/doc/tool_management.html delete mode 100644 lib/webtool/src/Makefile delete mode 100644 lib/webtool/src/webtool.app.src delete mode 100644 lib/webtool/src/webtool.appup.src delete mode 100644 lib/webtool/src/webtool.erl delete mode 100644 lib/webtool/src/webtool_sup.erl delete mode 100644 lib/webtool/test/Makefile delete mode 100644 lib/webtool/test/webtool.spec delete mode 100644 lib/webtool/test/webtool_SUITE.erl delete mode 100644 lib/webtool/vsn.mk (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index 64143a39e0..863b9abac6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,7 +35,7 @@ ALL_ERLANG_APPLICATIONS = xmerl edoc erl_docgen snmp otp_mibs erl_interface \ ic mnesia crypto orber os_mon syntax_tools \ public_key ssl observer odbc diameter \ cosTransactions cosEvent cosTime cosNotification \ - cosProperty cosFileTransfer cosEventDomain et megaco webtool \ + cosProperty cosFileTransfer cosEventDomain et megaco \ eunit ssh typer percept eldap dialyzer hipe ifdef BUILD_ALL diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl index cf0ed5fcfc..825a7f6e86 100644 --- a/lib/sasl/test/systools_SUITE.erl +++ b/lib/sasl/test/systools_SUITE.erl @@ -1640,25 +1640,21 @@ app_start_type_relup(Dir2,Name2,Config) -> %% ?t:format("Dn: ~p",[DownInstructions]), [{load_object_code, {mnesia, _, _}}, {load_object_code, {runtime_tools, _, _}}, - {load_object_code, {webtool, _, _}}, {load_object_code, {snmp, _, _}}, {load_object_code, {xmerl, _, _}}, point_of_no_return | UpInstructionsT] = UpInstructions, true = lists:member({apply,{application,start,[mnesia,permanent]}}, UpInstructionsT), true = lists:member({apply,{application,start,[runtime_tools,transient]}}, UpInstructionsT), - true = lists:member({apply,{application,start,[webtool,temporary]}}, UpInstructionsT), true = lists:member({apply,{application,load,[snmp]}}, UpInstructionsT), false = lists:any(fun({apply,{application,_,[xmerl|_]}}) -> true; (_) -> false end, UpInstructionsT), [point_of_no_return | DownInstructionsT] = DownInstructions, true = lists:member({apply,{application,stop,[mnesia]}}, DownInstructionsT), true = lists:member({apply,{application,stop,[runtime_tools]}}, DownInstructionsT), - true = lists:member({apply,{application,stop,[webtool]}}, DownInstructionsT), true = lists:member({apply,{application,stop,[snmp]}}, DownInstructionsT), true = lists:member({apply,{application,stop,[xmerl]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[mnesia]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[runtime_tools]}}, DownInstructionsT), - true = lists:member({apply,{application,unload,[webtool]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[snmp]}}, DownInstructionsT), true = lists:member({apply,{application,unload,[xmerl]}}, DownInstructionsT), ok. @@ -2207,7 +2203,6 @@ create_script(latest_app_start_type1,Config) -> create_script(latest_app_start_type2,Config) -> OtherApps = [{mnesia,current,permanent}, {runtime_tools,current,transient}, - {webtool,current,temporary}, {snmp,current,load}, {xmerl,current,none}], Apps = core_apps(current) ++ OtherApps, diff --git a/lib/tools/Makefile b/lib/tools/Makefile index 2699ffab51..fef33743c0 100644 --- a/lib/tools/Makefile +++ b/lib/tools/Makefile @@ -24,7 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # ---------------------------------------------------- -SUB_DIRECTORIES = c_src src doc/src examples priv emacs +SUB_DIRECTORIES = c_src src doc/src examples emacs include vsn.mk VSN = $(TOOLS_VSN) diff --git a/lib/tools/doc/src/cover_chapter.xml b/lib/tools/doc/src/cover_chapter.xml index 2f7f8d8083..c3f1570477 100644 --- a/lib/tools/doc/src/cover_chapter.xml +++ b/lib/tools/doc/src/cover_chapter.xml @@ -451,48 +451,5 @@ ok

When Cover is stopped, all Cover compiled modules are unloaded.

- -
- Using the Web Based User Interface to Cover - -
- Introduction -

To ease the use of Cover there is a web based user interface - to Cover called WebCover. WebCover is designed to be started - and used via WebTool. It is possible to Cover compile Erlang - modules and to generate printable Cover and Call analyses via - the web based user interface.

-
- -
- Start the Web Based User Interface to Cover -

To start WebCover you can either start WebTool, point a - browser to the start page of WebTool and start WebCover from - there, or you can use the start_webtool script to start - Webtool, WebCover and a browser. See WebTool documentation for - further information.

-

Currently WebCover is only compatible - with Internet Explorer and Netscape Navigator 4.0 and higher.

-
- -
- Navigating WebCover -

From the menu in the lefthand frame you can select the - Nodes, Compile, Import or Result - page.

-

From the Nodes page you can add remote nodes to - participate in the coverage analysis. Coverage data from all - involved nodes will then be merged during analysis.

-

From the Compile page you can Cover compile .erl - or .beam files.

-

From the Import page you can import coverage data from - a previous analysis. Imported data will then be merged with - the current coverage data. Note that it is only possible to - import files with the extension .coverdata.

-

From the Result page you can analyse, reset or export - coverage data.

-

Please follow the instructions on each page.

-
-
diff --git a/lib/tools/priv/.gitignore b/lib/tools/priv/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/tools/priv/Makefile b/lib/tools/priv/Makefile deleted file mode 100644 index aa4aaa2fc8..0000000000 --- a/lib/tools/priv/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# ``Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../vsn.mk -VSN = $(TOOLS_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -HTDOCS_FILES = index.html - -TOOL_FILES = cover.tool - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: - -clean: - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/priv" - $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv" - $(INSTALL_DATA) $(TOOL_FILES) "$(RELSYSDIR)/priv" - -release_docs_spec: - - - diff --git a/lib/tools/priv/cover.tool b/lib/tools/priv/cover.tool deleted file mode 100644 index 9e72f89ff4..0000000000 --- a/lib/tools/priv/cover.tool +++ /dev/null @@ -1,2 +0,0 @@ -{version,"1.2"}. -[{config_func,{cover_web,configData,[]}}]. diff --git a/lib/tools/priv/index.html b/lib/tools/priv/index.html deleted file mode 100644 index 6b60ef5d0a..0000000000 --- a/lib/tools/priv/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - -Erlang webb tools - - - - - - - diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile index 9fcfb79628..7301ff856a 100644 --- a/lib/tools/src/Makefile +++ b/lib/tools/src/Makefile @@ -37,7 +37,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN) MODULES= \ cover \ - cover_web \ eprof \ fprof \ cprof \ diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 366d6bcbd9..1d7d112c06 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -20,9 +20,7 @@ -module(cover). %% -%% This module implements the Erlang coverage tool. The module named -%% cover_web implements a user interface for the coverage tool to run -%% under webtool. +%% This module implements the Erlang coverage tool. %% %% ARCHITECTURE %% The coverage tool consists of one process on each node involved in diff --git a/lib/tools/src/cover_web.erl b/lib/tools/src/cover_web.erl deleted file mode 100644 index ae8b3f25cf..0000000000 --- a/lib/tools/src/cover_web.erl +++ /dev/null @@ -1,1185 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(cover_web). --author('marting@erix.ericsson.se'). --behaviour(gen_server). - -%%Export of configuration function --export([configData/0]). -%% External exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). - --export([start_link/0,start/0,stop/0]). --export([menu_frame/2,nodes_frame/2,import_frame/2, - compile_frame/2,result_frame/2]). --export([list_dir/2,compile/2,add_node/2,remove_node/2,result/2, - calls/2,coverage/2,import/2]). - --record(state,{dir}). - --include_lib("kernel/include/file.hrl"). - -%% Timeouts --define(DEFAULT_TIME,10000). --define(MAX_COMPILE_TIME,60000). --define(MAX_ANALYSE_TIME,30000). - -%% Colors --define(INFO_BG_COLOR,"#C0C0EA"). - -%%%---------------------------------------------------------------------- -%%% API - called from erlang shell -%%%---------------------------------------------------------------------- -%% Start webtool and webcover from erlang shell -start() -> - webtool:start(), - webtool:start_tools([],"app=webcover"), - ok. - -%% Stop webtool and webcover from erlang shell -stop() -> - webtool:stop_tools([],"app=webcover"), - webtool:stop(). - - - -%%%---------------------------------------------------------------------- -%%% API - called from webtool -%%%---------------------------------------------------------------------- -start_link() -> - gen_server:start_link({local, webcover_server},cover_web, [], []). - - -nodes_frame(Env,Input)-> - call({nodes_frame,Env,Input}). - -add_node(Env,Input)-> - call({add_node,Env,Input}). - -remove_node(Env,Input)-> - call({remove_node,Env,Input}). - -compile_frame(Env,Input)-> - call({compile_frame,Env,Input}). - -list_dir(Env,Input) -> - call({list_dir,Env,Input}). - -compile(Env,Input)-> - call({compile,Env,Input},?MAX_COMPILE_TIME). - -result_frame(Env,Input)-> - call({result_frame,Env,Input}). - -result(Env,Input) -> - call({result,Env,Input},?MAX_ANALYSE_TIME). - -calls(Env,Input) -> - call({calls,Env,Input}). - -coverage(Env,Input) -> - call({coverage,Env,Input}). - -import_frame(Env,Input)-> - call({import_frame,Env,Input}). - -import(Env,Input)-> - call({import,Env,Input}). - -menu_frame(Env,Input)-> - call({menu_frame,Env,Input}). - -call(Msg) -> - call(Msg,?DEFAULT_TIME). -call(Msg,Time) -> - gen_server:call(webcover_server,Msg,Time). - - - -configData()-> - {webcover,[{web_data,{"WebCover","/webcover"}}, - {alias,{"/webcover",code:priv_dir(tools)}}, - {alias,{erl_alias,"/webcover/erl",[cover_web]}}, - {start,{child,{{local,webcover_server}, - {cover_web,start_link,[]}, - permanent,100,worker,[cover_web]}}} - ]}. - - -%%%---------------------------------------------------------------------- -%%% Callback functions from gen_server -%%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%%---------------------------------------------------------------------- -init([]) -> - cover:start(), - CS = whereis(cover_server), - link(CS), - GL = spawn_link(fun group_leader_proc/0), - group_leader(GL,CS), - - %% Must trap exists in order to have terminate/2 executed when - %% crashing because of a linked process crash. - process_flag(trap_exit,true), - {ok,Cwd} = file:get_cwd(), - {ok, #state{dir=Cwd}}. - -group_leader_proc() -> - register(cover_group_leader_proc,self()), - group_leader_loop([]). -group_leader_loop(Warnings) -> - receive - {io_request,From,ReplyAs,{put_chars,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> group_leader_loop(Warnings); - false -> group_leader_loop([Msg|Warnings]) - end; - {io_request,From,ReplyAs,{put_chars,_Encoding,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> group_leader_loop(Warnings); - false -> group_leader_loop([Msg|Warnings]) - end; - IoReq when element(1,IoReq)=:= io_request -> - group_leader() ! IoReq, - group_leader_loop(Warnings); - {From,get_warnings} -> - Warnings1 = - receive - {io_request,From,ReplyAs, - {put_chars,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> Warnings; - false -> [Msg|Warnings] - end - after 0 -> - Warnings - end, - From ! {warnings,Warnings1}, - group_leader_loop([]) - end. - -%%---------------------------------------------------------------------- -%% Func: handle_call/3 -%% Returns: {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | (terminate/2 is called) -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_call({nodes_frame,_Env,_Input},_From,State)-> - {reply,nodes_frame1(),State}; - -handle_call({add_node,_Env,Input},_From,State)-> - {reply,do_add_node(Input),State}; - -handle_call({remove_node,_Env,Input},_From,State)-> - {reply,do_remove_node(Input),State}; - -handle_call({compile_frame,_Env,_Input},_From,State)-> - {reply,compile_frame1(State#state.dir),State}; - -handle_call({list_dir,_Env,Input},_From,State)-> - Dir = get_input_data(Input,"path"), - case filelib:is_dir(Dir) of - true -> - {reply,compile_frame1(Dir),State#state{dir=Dir}}; - false -> - Err = Dir ++ " is not a directory", - {reply,compile_frame1(State#state.dir,Err),State} - end; -handle_call({compile,_Env,Input},_From,State)-> - {reply,do_compile(Input,State#state.dir),State}; - -handle_call({result_frame,_Env,_Input},_From,State)-> - {reply,result_frame1(),State}; - -handle_call({result,_Env,Input},_From,State)-> - {reply,handle_result(Input),State}; - -handle_call({calls,_Env,Input},_From,State)-> - {reply,call_page(Input),State}; - -handle_call({coverage,_Env,Input},_From,State)-> - {reply,coverage_page(Input),State}; - -handle_call({import_frame,_Env,_Input},_From,State)-> - {ok,Cwd} = file:get_cwd(), - {reply,import_frame1(Cwd),State}; - -handle_call({import,_Env,Input},_From,State)-> - {reply,do_import(Input),State}; - -handle_call({menu_frame,_Env,_Input},_From,State)-> - {reply,menu_frame1(),State}; - -handle_call(_Request, _From, State) -> - Reply = bad_request, - {reply, Reply, State}. - - -%%---------------------------------------------------------------------- -%% Func: handle_cast/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_cast(_Msg, State) -> - {noreply, State}. - -%%---------------------------------------------------------------------- -%% Func: handle_info/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_info({'EXIT',_Pid,Reason}, State) -> - {stop, Reason, State}. - -%%---------------------------------------------------------------------- -%% Func: terminate/2 -%% Purpose: Shutdown the server -%% Returns: any (ignored by gen_server) -%%---------------------------------------------------------------------- -terminate(_Reason, _State) -> - cover:stop(), - ok. - -%%-------------------------------------------------------------------- -%% Func: code_change/3 -%% Purpose: Convert process state when code is changed -%% Returns: {ok, NewState} -%%-------------------------------------------------------------------- -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%%---------------------------------------------------------------------- -%%% Internal functions -%%%---------------------------------------------------------------------- - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that creates the whole pages by collecting all the %% -%% neccessary data for each page. These functions are the public %% -%% interface. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%---------------------------------------------------------------------- -%% Returns the page to the left frame -%%---------------------------------------------------------------------- -menu_frame1()-> - [header(),html_header(""),menu_body(),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can add and remove nodes -%%---------------------------------------------------------------------- - -nodes_frame1()-> - nodes_frame1([]). -nodes_frame1(Err)-> - [header(),html_header("Add/remove nodes"),nodes_body(Err),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can cover compile modules -%%---------------------------------------------------------------------- - -compile_frame1(Dir)-> - compile_frame1(Dir,[]). -compile_frame1(Dir,Err) -> - [header(),html_header("Cover compile"),compile_body(Dir,Err),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can handle results -%%---------------------------------------------------------------------- - -result_frame1()-> - result_frame1([]). -result_frame1(Err) -> - [header(),html_header("Show cover results"),result_body(Err),html_end()]. - -%%---------------------------------------------------------------------- -%%The beginning of the page that clear the cover information on a cover -%%compiled module -%%---------------------------------------------------------------------- -call_page(Input)-> - [header(),html_header("Code coverage"),call_result(Input),html_end()]. - -coverage_page(Input)-> - [header(),html_header("Code coverage"),coverage_result(Input),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user an import files -%%---------------------------------------------------------------------- -import_frame1(Dir) -> - import_frame1(Dir,""). -import_frame1(Dir,Err) -> - [header(),html_header("Import coverdata"),import_body(Dir,Err),html_end()]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that build the body of the menu frame %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -menu_body() -> - Nodes = cover:which_nodes(), - Modules = cover:modules(), - Imported = cover:imported(), - ["Nodes
\n", - "Compile
\n", - "Import
\n", - "Result\n", - "

Nodes:\n", - "

    \n", - lists:map(fun(N) -> "
  • "++atom_to_list(N)++"
  • \n" end,[node()|Nodes]), - "
\n", - "

Compiled modules:\n", - "

    \n", - lists:map(fun(M) -> "
  • "++atom_to_list(M)++"
  • \n" end,Modules), - "
\n", - "

Imported files:\n", - "

    \n", - "\n", - lists:map(fun(F) -> - Short = filename:basename(F), - "
  • "++Short++"
  • \n" end,Imported), - "
    \n", - "
\n"]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that build the body of the nodes frame %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nodes_body(Err) -> - CN = cover:which_nodes(), - Fun = fun(N) -> - NStr = atom_to_list(N), - ["\n"] - end, - AllNodes = lists:append(lists:map(Fun,nodes()--CN)), - CoverNodes = lists:append(lists:map(Fun,CN)), - - [reload_menu_script(Err), - "

Nodes

\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - "\n", - "\n", - "\n", - "\n", - "\n", - "", - "
\n", - "

You can run cover over several nodes simultaneously. Coverage data\n", - "from all involved nodes will be merged during analysis.\n", - "

Select or enter node names to add or remove here.\n", - "



Add node:", - "" - "
\n", - "


Remove node:\n", - "" - "
"]. - - -do_add_node(Input) -> - NodeStr = get_input_data(Input, "node"), - Node = list_to_atom(NodeStr), - case net_adm:ping(Node) of - pong -> - cover:start(Node), - nodes_frame1(); - pang -> - nodes_frame1("Node \\\'" ++ NodeStr ++ "\\\' is not alive") - end. - -do_remove_node(Input) -> - Node = list_to_atom(get_input_data(Input, "node")), - cover:stop(Node), - nodes_frame1(). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that is used when the user wants to compile something % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -compile_body(Dir,Err) -> - Erls = filelib:wildcard(filename:join(Dir,"*.erl")), - Beams = filelib:wildcard(filename:join(Dir,"*.beam")), - - [reload_menu_script(Err), - "

Compile

\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
\n", - "Each module which shall be part of the cover analysis must be prepared\n", - "or 'cover compiled'. On this page you can select .erl files and/or\n", - ".beam files to include in the analysis. If you select a .erl file it\n", - "will first be compiled with the Erlang compiler and then prepared for\n", - "coverage analysis. If you select a .beam file it will be prepared for\n", - "coverage analysis directly.\n", - "
\n", - "To list a different directory, enter the directory name here.\n", - "
List directory:
\n", - "", - "", - "

\n", - "

Select one or more .erl or .beam files to prepare for coverage\n" - "analysis, and click the \"Compile\" button.\n", - "

To reload the original file after coverage analysis is complete,\n" - "select one or more files and click the \"Uncompile\" button, or\n", - "simply click the \"Uncompile all\" button to reload all originals.\n" - "

.erl files.beam files
\n", - "\n", - "
\n", - "Compile options are only needed for .erl files. The options must be\n" - "given e.g. like this: \n" - "[{i,\"/my/path/include\"},{i,\"/other/path/\"}]\n" - "
Compile options:
\n", - "\n", - "
\n", - "", - "", - "", - "
\n"]. - -list_modules([File|Files]) -> - Mod = filename:basename(File), - ["\n" | list_modules(Files)]; -list_modules([]) -> - []. - -do_compile(Input,Dir) -> - {Erls,Beams,Opts,Action} = get_compile_input(parse(Input),[],[]), - Errs = - case Action of - "compile" -> - do_compile(Erls,Beams,Opts,[]); - "uncompile" -> - do_uncompile(Erls++Beams); - "uncompile_all" -> - do_uncompile(cover:modules()) - end, - compile_frame1(Dir,Errs). - -get_compile_input([{"erl",File}|Input],Erl,Beam) -> - get_compile_input(Input,[File|Erl],Beam); -get_compile_input([{"beam",File}|Input],Erl,Beam) -> - get_compile_input(Input,Erl,[File|Beam]); -get_compile_input([{"options",Opts0},{"action",Action}],Erl,Beam) -> - Opts = parse_options(Opts0), - {Erl,Beam,Opts,Action}. - -do_compile([Erl|Erls],Beams,Opts,Errs) -> - case cover:compile_module(Erl,Opts) of - {ok,_} -> - do_compile(Erls,Beams,Opts,Errs); - {error,File} -> - do_compile(Erls,Beams,Opts,["\\n"++File|Errs]) - end; -do_compile([],[Beam|Beams],Opts,Errs) -> - case cover:compile_beam(Beam) of - {ok,_} -> - do_compile([],Beams,Opts,Errs); - {error,{no_abstract_code,File}} -> - do_compile([],Beams,Opts,["\\n"++File++" (no_abstract_code)"|Errs]) - end; -do_compile([],[],_,[]) -> - []; -do_compile([],[],_,Errs) -> - "Compilation failed for the following files:" ++ Errs. - -parse_options(Options)-> - case erl_scan:string(Options ++".") of - {ok,Tokens,_Line} -> - case erl_parse:parse_exprs(Tokens) of - {ok,X}-> - case lists:map(fun erl_parse:normalise/1, X) of - [List] when is_list(List) -> List; - List -> List - end; - _ -> - [] - end; - _ -> - [] - end. - - -do_uncompile(Files) -> - lists:foreach( - fun(File) -> - Module = - if is_atom(File) -> - File; - true -> - ModStr = filename:basename(filename:rootname(File)), - list_to_atom(ModStr) - end, - case code:which(Module) of - cover_compiled -> - code:purge(Module), - case code:load_file(Module) of - {module, Module} -> - ok; - {error, _Reason2} -> - code:delete(Module) - end; - _ -> - ok - end - end, - Files), - []. - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page for coverage analysis% -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -result_body(Err) -> - [reload_menu_script(Err), - "

Result

\n", - "\n", - "\n", - "
\n", - "

After executing all your tests you can view the result of the\n", - "coverage analysis here. For each module you can\n", - "

\n", - "
Analyse to file
\n", - "
The source code of the module is shown with the number of calls\n", - "to each line stated in the left margin. Lines which are never called\n", - "are colored red.
\n", - "
Analyse coverage
\n", - "
Show the number of covered and uncovered lines in the module.
\n", - "
Analyse calls
\n", - "
Show the number of calls in the module.
\n", - "
Reset module
\n", - "
Delete all coverage data for the module.
\n", - "
Export module
\n", - "
Write all coverage data for the module to a file. The data can\n", - "later be imported from the \"Import\" page.
\n", - "
\n", - "

You can also reset or export data for all modules with the\n", - "Reset all and Export all actions respectively. For these\n", - "two actions there is no need to select a module.\n", - "

Select module and action from the drop down menus below, and click\n", - "the \"Execute\" button.\n", - "



\n", - result_selections(), - "
"]. - -result_selections() -> - ModList = filter_modlist(cover:modules()++cover:imported_modules(),[]), - - ["
\n", - "\n", - "\n", - "\n", - "\n" - "
\n", - "Module:\n", - "
\n", - "
\n", - "Action:\n", - "
\n", - "
\n" - "
\n", - "
\n"]. - -filter_modlist([M|Ms],Already) -> - case lists:member(M,Already) of - true -> - filter_modlist(Ms,Already); - false -> - MStr = atom_to_list(M), - ["\n" | - filter_modlist(Ms,[M|Already])] - end; -filter_modlist([],_Already) -> - []. - - - -handle_result(Input) -> - case parse(Input) of - [{"module",M},{"action",A}] -> - case A of - "analyse_to_file" -> - case cover:analyse_to_file(list_to_atom(M),[html]) of - {ok,File} -> - case file:read_file(File) of - {ok,HTML}-> - file:delete(File), - [header(), - reload_menu_script(""), - binary_to_list(HTML)]; - _ -> - result_frame1("Can not read file" ++ File) - end; - {error,no_source_code_found} -> - result_frame1("No source code found for \\\'" ++ - M ++ "\\\'") - end; - "calls" -> - call_page(Input); - "coverage" -> - coverage_page(Input); - "reset" -> - cover:reset(list_to_atom(M)), - result_frame1("Coverage data for \\\'" ++ M ++ - "\\\' is now reset"); - "reset_all" -> - cover:reset(), - result_frame1("All coverage data is now reset"); - "export" -> - ExportFile = generate_filename(M), - cover:export(ExportFile,list_to_atom(M)), - result_frame1("Coverage data for \\\'" ++ M ++ - "\\\' is now exported to file \\\"" ++ - ExportFile ++ "\\\""); - "export_all" -> - ExportFile = generate_filename("COVER"), - cover:export(ExportFile), - result_frame1( - "All coverage data is now exported to file \\\"" ++ - ExportFile ++ "\\\"") - end; - [{"action",_A}] -> - result_frame1("No module is selected") - end. - -generate_filename(Prefix) -> - {ok,Cwd} = file:get_cwd(), - filename:join(Cwd,Prefix ++ "_" ++ ts() ++ ".coverdata"). - -ts() -> - {{Y,M,D},{H,Min,S}} = calendar:now_to_local_time(erlang:timestamp()), - io_lib:format("~4.4.0w~2.2.0w~2.2.0w-~2.2.0w~2.2.0w~2.2.0w", - [Y,M,D,H,Min,S]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page that shows the calls % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -call_result(Input)-> - Mod = list_to_atom(get_input_data(Input, "module")), - case cover:analyse(Mod,calls) of - {error,_}-> - error_body(); - {ok,_} -> - call_result2(Mod,Input) - end. - -call_result2(Mod,Input)-> - Result = - case get_input_data(Input,"what") of - "mod" -> - call_result(mod,Mod); - "func" -> - call_result(func,Mod); - "clause" -> - call_result(clause,Mod); - _-> - call_result(all,Mod) - end, - result_choice("calls",Mod) ++ Result. - -result_choice(Level,Mod)-> - ModStr=atom_to_list(Mod), - [reload_menu_script(""), - "\n", - "\n", - "\n", - "\n", - "\n", - "
All DataModuleFunctionClause

\n"]. - -call_result(Mode,Module)-> - Content = - case Mode of - mod-> - format_cover_call(cover:analyse(Module,calls,module),mod); - func-> - format_cover_call(cover:analyse(Module,calls,function),func); - clause-> - format_cover_call(cover:analyse(Module,calls,clause),clause); - _-> - format_cover_call(cover:analyse(Module,calls,module),mod) ++ - format_cover_call(cover:analyse(Module,calls,function),func)++ - format_cover_call(cover:analyse(Module,calls,clause),clause) - end, - getModDate(Module,date())++"
"++ - "" - ++ Content ++"
". - - -format_cover_call({error,_},_)-> - ["\n", - "



\n", - "The selected module is not Cover Compiled\n", - "
\n", - "\n"]; - -format_cover_call({ok,{Mod,Calls}},mod)-> - ["Module calls\n", - "Module", - "Number of calls\n", - "" ++ atom_to_list(Mod) ++"" - "" ++ integer_to_list(Calls)++"\n"]; - -format_cover_call({ok,Calls},func)-> - ["Function calls\n", - "ModuleFunction", - "Arity", - "Number of calls \n", - lists:append( - lists:map( - fun({{Mod,Func,Arity},Nr_of_calls})-> - [""++ atom_to_list(Mod)++"\n", - "" ++ atom_to_list(Func) ++" \n", - "", - integer_to_list(Arity), - "\n", - "", - integer_to_list(Nr_of_calls), - "\n"] - end, - Calls))]; - -format_cover_call({ok,Calls},clause)-> - ["Clause calls\n", - "ModuleFunction", - "Arity", - "Ordinal", - "Number of calls\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity,Ord},Nr_of_calls})-> - ["", atom_to_list(Mod), "\n", - "", atom_to_list(Func), "\n", - "", - integer_to_list(Arity), - "\n", - "", - integer_to_list(Ord), - "\n", - "", - integer_to_list(Nr_of_calls), - "\n"] - end, - Calls))]. - - -error_body()-> - ["\n", - "\n", - "\n", - "\n", - "
\n", - "





\n", - "The selected module is not Cover Compiled\n", - "
\n", - "
\n"]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page that shows coverage % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -coverage_result(Input)-> - Mod = list_to_atom(get_input_data(Input, "module")), - case cover:analyse(Mod,coverage) of - {error,_}-> - error_body(); - {ok,_} -> - coverage_result2(Mod,Input) - end. - -coverage_result2(Mod,Input)-> - Result = - case get_input_data(Input,"what") of - "mod" -> - coverage_result(mod,Mod); - "func" -> - coverage_result(func,Mod); - "clause" -> - coverage_result(clause,Mod); - _-> - coverage_result(all,Mod) - end, - result_choice("coverage",Mod) ++ Result. - -coverage_result(Mode,Module)-> - Content = - case Mode of - mod-> - format_cover_coverage(cover:analyse(Module,coverage,module), - mod); - func-> - format_cover_coverage(cover:analyse(Module,coverage,function), - func); - clause-> - format_cover_coverage(cover:analyse(Module,coverage,clause), - clause); - _-> - format_cover_coverage(cover:analyse(Module,coverage,module), - mod) ++ - format_cover_coverage(cover:analyse(Module,coverage,function), - func)++ - format_cover_coverage(cover:analyse(Module,coverage,clause), - clause) - end, - getModDate(Module,date())++"
"++ - "" - ++ Content ++"
". - -getModDate(Module,{Year,Mon,Day})-> - " - - - - - - - - -
Module:" ++ atom_to_list(Module) ++ "
Date:" ++ integer_to_list(Day) ++ "/" ++ - integer_to_list(Mon) ++" - "++ - integer_to_list(Year) ++ - "
". - - -format_cover_coverage({error,_},_)-> - " -



- The selected module is not Cover Compiled -
- "; - - -format_cover_coverage({ok,{Mod,{Cov,Not_cov}}},mod)-> - ["Module coverage\n", - "Module\n", - "Covered\n" - "Not Covered\n", - "\n", - "", atom_to_list(Mod), "\n" - "", integer_to_list(Cov), "\n" - "", integer_to_list(Not_cov), "\n"]; - -format_cover_coverage({ok,Cov_res},func)-> - ["Function coverage\n", - "\n", - "ModuleFunction", - "Arity", - "Covered", - "Not Covered", - "\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity},{Cov,Not_cov}})-> - [""++ atom_to_list(Mod) ++" \n", - "" ++ atom_to_list(Func) ++"\n", - "", - integer_to_list(Arity), - "\n", - "", - integer_to_list(Cov), - "\n" - "", - integer_to_list(Not_cov), - "\n"] - end, - Cov_res))]; - -format_cover_coverage({ok,Cov_res},clause)-> - ["Clause coverage\n", - "ModuleFunction\n", - "Arity\n", - "Ordinal\n", - "Covered\n", - "Not Covered\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity,Ord},{Cov,Not_cov}})-> - [""++ atom_to_list(Mod) ++"\n", - "" ++ atom_to_list(Func) ++" \n", - "", - integer_to_list(Arity), - "\n" - "", - integer_to_list(Ord), - "\n" - "", - integer_to_list(Cov), - "\n" - "", - integer_to_list(Not_cov), - "\n"] - end, - Cov_res))]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the import page % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -import_body(Dir,Err) -> - [reload_menu_script(Err), - "

Import

\n", - "\n", - "\n", - "
\n", - "

You can import coverage data from a previous analysis. If you do so\n", - "the imported data will be merged with the current coverage data.\n", - "

You can export data from the current analysis from the \"Result\"\n", - "page.\n", - "

Select the file to import here.\n", - "



\n", - "
\n", - "Change directory:
\n", - "", - "\n", - "
\n", - "
\n", - browse_import(Dir), - "
"]. - -browse_import(Dir) -> - {ok,List} = file:list_dir(Dir), - Sorted = lists:reverse(lists:sort(List)), - {Dirs,Files} = filter_files(Dir,Sorted,[],[]), - ["
\n" - "\n", - "\n", - "
\n" - "
\n"]. - -filter_files(Dir,[File|Files],Ds,Fs) -> - case filename:extension(File) of - ".coverdata" -> - Fs1 = ["\n" | Fs], - filter_files(Dir,Files,Ds,Fs1); - _ -> - FullName = filename:join(Dir,File), - case filelib:is_dir(FullName) of - true -> - Ds1 = ["\n" | Ds], - filter_files(Dir,Files,Ds1,Fs); - false -> - filter_files(Dir,Files,Ds,Fs) - end - end; -filter_files(_Dir,[],Ds,Fs) -> - {Ds,Fs}. - - - - -do_import(Input) -> - case parse(Input) of - [{"file",File0},{"dir",Dir}] -> - File = filename:join(Dir,File0), - case filelib:is_dir(File) of - true -> - import_frame1(File); - false -> - case filelib:is_file(File) of - true -> - case cover:import(File) of - ok -> - import_frame1(Dir); - {error,{cant_open_file,ExportFile,_Reason}} -> - import_frame1(Dir, - "Error importing file\\n\\\"" - ++ ExportFile ++ "\\\"") - end; - false -> - import_frame1(Dir, - "Error importing file\\n\\\"" ++ - File ++ "\\\"") - end - end; - [{"dir",Dir}] -> - import_frame1(Dir,"No file is selected") - end. - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% Different private helper functions % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%Create the Header for the page If we now the mimetype use that type %% -%%otherwise use text %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -header() -> - header("text/html"). -header(MimeType) -> - "Pragma:no-cache\r\n" ++ - "Content-type: " ++ MimeType ++ "\r\n\r\n". - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%Create the Htmlheader set the title of the page %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -html_header(Title) -> - "\n" ++ - "\n" ++ - "" ++ Title ++ "\n" ++ - "\n" - "\n". - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Close the body- and Html tags %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -html_end()-> - "". - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% A script which reloads the menu frame and possibly pops up an alert%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -reload_menu_script(Err) -> - ["\n", - ""]. - -fix_newline([$\n|Rest]) -> - [$\\,$n|fix_newline(Rest)]; -fix_newline([$"|Rest]) -> - [$\\,$"|fix_newline(Rest)]; -fix_newline([Char|Rest]) -> - [Char|fix_newline(Rest)]; -fix_newline([]) -> - []. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Control the input data and return the intresting values or error % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_input_data(Input,Key)-> - case lists:keysearch(Key,1,parse(Input)) of - {value,{Key,Value}} -> - Value; - false -> - undefined - end. - -parse(Input) -> - httpd:parse_query(Input). - - -get_warnings() -> - cover_group_leader_proc ! {self(), get_warnings}, - receive {warnings,Warnings} -> - Warnings - end. diff --git a/lib/tools/src/tools.app.src b/lib/tools/src/tools.app.src index 978b54719c..a00969eabe 100644 --- a/lib/tools/src/tools.app.src +++ b/lib/tools/src/tools.app.src @@ -21,7 +21,6 @@ [{description, "DEVTOOLS CXC 138 16"}, {vsn, "%VSN%"}, {modules, [cover, - cover_web, eprof, fprof, instrument, @@ -36,12 +35,12 @@ xref_utils ] }, - {registered,[webcover_server]}, + {registered, []}, {applications, [kernel, stdlib]}, {env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]} ] }, - {runtime_dependencies, ["webtool-0.8.10","stdlib-2.5","runtime_tools-1.8.14", + {runtime_dependencies, ["stdlib-2.5","runtime_tools-1.8.14", "kernel-3.0","inets-5.10","erts-7.0", "compiler-5.0"]} ] diff --git a/lib/webtool/AUTHORS b/lib/webtool/AUTHORS deleted file mode 100644 index 5f173dd264..0000000000 --- a/lib/webtool/AUTHORS +++ /dev/null @@ -1,4 +0,0 @@ -Original Authors and Contributors: - -Siri Hansen -Martin Gustafsson diff --git a/lib/webtool/Makefile b/lib/webtool/Makefile deleted file mode 100644 index 9afcb87af2..0000000000 --- a/lib/webtool/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2001-2009. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Common Macros -# ---------------------------------------------------- - -SUB_DIRECTORIES = src priv doc/src - -include vsn.mk -VSN = $(WEBTOOL_VSN) - -SPECIAL_TARGETS = - -# ---------------------------------------------------- -# Default Subdir Targets -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_subdir.mk - - diff --git a/lib/webtool/doc/html/.gitignore b/lib/webtool/doc/html/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/webtool/doc/man1/.gitignore b/lib/webtool/doc/man1/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/webtool/doc/man3/.gitignore b/lib/webtool/doc/man3/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/webtool/doc/pdf/.gitignore b/lib/webtool/doc/pdf/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/webtool/doc/src/Makefile b/lib/webtool/doc/src/Makefile deleted file mode 100644 index 57de52a616..0000000000 --- a/lib/webtool/doc/src/Makefile +++ /dev/null @@ -1,132 +0,0 @@ -# ``Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../../vsn.mk -VSN=$(WEBTOOL_VSN) -APPLICATION=webtool - -DOC_EXTRA_FRONT_PAGE_INFO=Important note: \ -The Webtool application is obsolete and will be removed \ -in the next major OTP release - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- -XML_APPLICATION_FILES = ref_man.xml - -XML_REF1_FILES = start_webtool.xml - -XML_REF3_FILES = webtool.xml - -XML_PART_FILES = \ - part.xml \ - part_notes.xml \ - part_notes_history.xml - -XML_CHAPTER_FILES = \ - webtool_chapter.xml \ - notes.xml \ - notes_history.xml - -BOOK_FILES = book.xml - -XML_FILES = \ - $(BOOK_FILES) $(XML_CHAPTER_FILES) \ - $(XML_PART_FILES) $(XML_REF3_FILES) \ - $(XML_REF1_FILES) $(XML_APPLICATION_FILES) - -GIF_FILES = - -# ---------------------------------------------------- - -HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) - -INFO_FILE = ../../info - -MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1) -MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) - -HTML_REF_MAN_FILE = $(HTMLDIR)/index.html - -TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -XML_FLAGS += -DVIPS_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- -$(HTMLDIR)/%.gif: %.gif - $(INSTALL_DATA) $< $@ - -docs: pdf html man - -$(TOP_PDF_FILE): $(XML_FILES) - -pdf: $(TOP_PDF_FILE) - -html: gifs $(HTML_REF_MAN_FILE) - - -clean clean_docs: - rm -rf $(HTMLDIR)/* - rm -f $(MAN1DIR)/* - rm -f $(MAN3DIR)/* - rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) - rm -f errs core *~ - -man: $(MAN1_FILES) $(MAN3_FILES) - -gifs: $(GIF_FILES:%=$(HTMLDIR)/%) - -debug opt: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_docs_spec: docs - $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(HTMLDIR)/* \ - "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1" - $(INSTALL_DATA) $(MAN1_FILES) "$(RELEASE_PATH)/man/man1" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" - $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3" - -release_spec: - diff --git a/lib/webtool/doc/src/book.xml b/lib/webtool/doc/src/book.xml deleted file mode 100644 index feccee7c62..0000000000 --- a/lib/webtool/doc/src/book.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - -
- - 20012013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - WebTool - - - - 1.0 -
- - - WebTool - - - - - - - - - - - - - -
- diff --git a/lib/webtool/doc/src/fascicules.xml b/lib/webtool/doc/src/fascicules.xml deleted file mode 100644 index 37feca543f..0000000000 --- a/lib/webtool/doc/src/fascicules.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - User's Guide - - - Reference Manual - - - Release Notes - - - Off-Print - - - diff --git a/lib/webtool/doc/src/notes.xml b/lib/webtool/doc/src/notes.xml deleted file mode 100644 index 21309261a8..0000000000 --- a/lib/webtool/doc/src/notes.xml +++ /dev/null @@ -1,253 +0,0 @@ - - - - -
- - 20042013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Webtool Release Notes - otp_appnotes - nil - nil - nil - notes.xml -
-

This document describes the changes made to the Webtool - application.

- -
WebTool 0.9 - -
Improvements and New Features - - -

- The Webtool application has been marked as obsolete and - will be removed from OTP in the next major release (OTP - 19.0).

-

- Own Id: OTP-10922 Aux Id: OTP-12705

-
-
-
- -
- -
WebTool 0.8.10 - -
Fixed Bugs and Malfunctions - - -

- Application upgrade (appup) files are corrected for the - following applications:

-

- asn1, common_test, compiler, crypto, debugger, - dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, - inets, observer, odbc, os_mon, otp_mibs, parsetools, - percept, public_key, reltool, runtime_tools, ssh, - syntax_tools, test_server, tools, typer, webtool, wx, - xmerl

-

- A new test utility for testing appup files is added to - test_server. This is now used by most applications in - OTP.

-

- (Thanks to Tobias Schlager)

-

- Own Id: OTP-11744

-
-
-
- -
- -
WebTool 0.8.9.2 - -
Improvements and New Features - - -

- Misc build updates

-

- Own Id: OTP-10784

-
-
-
- -
- -
WebTool 0.8.9.1 - -
Improvements and New Features - - -

- Miscellaneous documentation build updates

-

- Own Id: OTP-9813

-
-
-
- -
- -
WebTool 0.8.9 - -
Fixed Bugs and Malfunctions - - -

- Do not install *.bat files on non-win32 machines (Thanks - to Hans Ulrich Niedermann)

-

- Own Id: OTP-9515

-
-
-
- -
- -
WebTool 0.8.8 - -
Fixed Bugs and Malfunctions - - -

- Various small documentation fixes (Thanks to Bernard - Duggan)

-

- Own Id: OTP-9172

-
-
-
- -
- -
WebTool 0.8.7 - -
Improvements and New Features - - -

- Up until now Netscape has been the default web browser on - Unix/Linux. Webtool has now been updated to start Firefox - as default browser instead.

-

- Own Id: OTP-8651 Aux Id: OTP-8650

-
-
-
- -
- -
WebTool 0.8.6 - -
Improvements and New Features - - -

- Misc updates

-

- Own Id: OTP-8456

-
-
-
- -
- -
WebTool 0.8.5 - -
Improvements and New Features - - -

- The documentation is now built with open source tools - (xsltproc and fop) that exists on most platforms. One - visible change is that the frames are removed.

-

- Own Id: OTP-8201

-
-
-
- -
- -
WebTool 0.8.4 - -
Improvements and New Features - - -

The copyright notices have been updated.

-

- Own Id: OTP-7851

-
-
-
- -
-
WebTool 0.8.3.2 - -
Improvements and New Features - - -

- Minor updates.

-

- Own Id: OTP-6998

-
-
-
- -
- -
- WebTool 0.8.3.1 - -
- Improvements and New Features - - -

Minor Makefile changes.

-

Own Id: OTP-6689

-
- -

Obsolete guard tests (such as list()) have been replaced - with the modern guard tests (such as is_list()).

-

Own Id: OTP-6725

-
-
-
-
- -
- WebTool 0.8.3 - -
- Improvements and New Features - - -

Removed some dead code discovered by Dialyzer.

-

Own Id: OTP-6041

-
-
-
-
-
- diff --git a/lib/webtool/doc/src/notes_history.xml b/lib/webtool/doc/src/notes_history.xml deleted file mode 100644 index 792475d948..0000000000 --- a/lib/webtool/doc/src/notes_history.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - -
- - 2006 - 2013 - Ericsson AB, All Rights Reserved - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - - - Webtool Release Notes History - otp_appnotes - nil - nil - nil -
- -
- Webtool 0.8.2 - -
- Fixed Bugs and Malfunctions - - -

Bugfix: webtool crashed when trying to find a free - port number if connection failed with other reason than - econnrefused.

-

Own Id: OTP-5166

-
-
-
- -
- Improvements and New Features - - -

Misc improvements:

- - The function debug_app/1 and some error - printouts are added to simplify debugging of own - application. - Multiple webtool instances can now be started on - the same host. If the default port (8888) is in use, port - 8889 is tried. If 8889 is also used, 8890 is tried and so - on. Max number of ports tried is 256. - Incompatible: If Data is set to - PortNumber in start(Path,Data), the default - data will be used for ip-number (127.0.0.1) and - server name (localhost). - -

*** POTENTIAL INCOMPATIBILITY ***

-

Own Id: OTP-4724

-
-
-
-
-
- diff --git a/lib/webtool/doc/src/part.xml b/lib/webtool/doc/src/part.xml deleted file mode 100644 index b0c4ee310d..0000000000 --- a/lib/webtool/doc/src/part.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - -
- - 20012013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - WebTool User's Guide - - - - -
- -

WebTool provides a easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.

-
- -
- diff --git a/lib/webtool/doc/src/part_notes.xml b/lib/webtool/doc/src/part_notes.xml deleted file mode 100644 index db2b790f3f..0000000000 --- a/lib/webtool/doc/src/part_notes.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - -
- - 20042013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - WebTool Release Notes - - - - -
- -

WebTool provides an easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.

-

For information about older versions, see - Release Notes History.

-
- -
- diff --git a/lib/webtool/doc/src/part_notes_history.xml b/lib/webtool/doc/src/part_notes_history.xml deleted file mode 100644 index 50ce62e58d..0000000000 --- a/lib/webtool/doc/src/part_notes_history.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - -
- - 2006 - 2013 - Ericsson AB, All Rights Reserved - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - - - WebTool Release Notes History - - - - -
- -

WebTool provides a easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.

-
- -
- diff --git a/lib/webtool/doc/src/ref_man.xml b/lib/webtool/doc/src/ref_man.xml deleted file mode 100644 index aa81392b11..0000000000 --- a/lib/webtool/doc/src/ref_man.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - -
- - 20012013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - WebTool Reference Manual - - - - -
- -

WebTool provides an easy way to use web based tools with - Erlang/OTP. It configures and starts a webserver as well as all - available tools.

-
- - -
- diff --git a/lib/webtool/doc/src/start_webtool.xml b/lib/webtool/doc/src/start_webtool.xml deleted file mode 100644 index e9c94c4271..0000000000 --- a/lib/webtool/doc/src/start_webtool.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - -
- - 20032013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - start_webtool - - - 1 - - - 2003-06-18 - - start_webtool.sgml -
- start_webtool - WebTool Start Script - -

The start_webtool script starts WebTool, a WebTool - application and a web browser pointing to this application.

-
- - - start_webtool application [ browser ] - Start a WebTool Application - -

Starts WebTool, the given WebTool Application and a web - browser pointing to this application. -

-

If no argument is given, a list of available applications - is displayed, e.g.

-
->start_webtool
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or  http://127.0.0.1:8888/
-
-Usage: start_webtool application [ browser ]
-
-Available applications are: [orber,appmon,crashdump_viewer,webcover]
-Default browser is 'iexplore' (Internet Explorer) on Windows or else 'firefox'        
-

To start any of the listed applications, give the - application name as the first argument, e.g.

-
->start_webtool webcover
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or  http://127.0.0.1:8888/
-Starting webcover...
-Sending URL to netscape...done        
-

The WebTool application WebCover is then started and the - default browser is used. The default browser is Internet - Explorer on Windows or else Firefox. -

-

To use another browser, give the browser's start command - as the second argument, e.g.

-
->start_webtool webcover mozilla
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or  http://127.0.0.1:8888/
-Starting webcover...
-Sending URL to mozilla...done        
-

If the given browser name is not known to WebTool, WebTool - will run it as a command with the start URL as the only - argument, e.g.

-
->start_webtool webcover mybrowser
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or  http://127.0.0.1:8888/
-Starting webcover...
-Starting mybrowser...        
-

Here the command "mybrowser http://localhost:8888/webcover" is executed. -

-
-
-
- -
- See Also -

webtool(3)

-
-
- diff --git a/lib/webtool/doc/src/webtool.xml b/lib/webtool/doc/src/webtool.xml deleted file mode 100644 index 2647518dae..0000000000 --- a/lib/webtool/doc/src/webtool.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - - -
- - 2001 - 2013 - Ericsson AB, All Rights Reserved - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - The Initial Developer of the Original Code is Ericsson AB. - - - webtool - - - - -
- webtool - WebTool is a tool used to simplify the implementation of web based tools with Erlang/OTP. - -

WebTool makes it easy to use web based tools with Erlang/OTP. WebTool - configures and starts the webserver httpd.

-
- - - start()-> {ok,Pid}| {stop,Reason} - Start WebTool. - -

Start WebTool with default data, i.e. port 8888, ip-number - 127.0.0.1, and server-name localhost. If port 8888 is - in use, port 8889 is tried instead. If 8889 is also in use, - 8890 is tried and so on. Max number of ports tried is 256. -

-

The mime.types file and WebTool's own HTML files - are assumed to be in the directory - /priv/root/conf]]>.

-
-
- - start(Path,Data)->{ok,Pid}|{stop,Reason} - Start WebTool with default configuration. - - Path = string() | standard_path - Data = [Port,Address,Name] | PortNumber | standard_data - Port = {port,PortNumber} - Address = {bind_address,IpNumber} - Name = {server_name,ServerName} - PortNumber = integer() - IpNumber = tuple(), e.g. {127,0,0,1} - ServerName = string() - Pid = pid() - - -

Use this function to start WebTool if the default port, - ip-number,servername or path can not be used.

-

Path is the directory where the mime.types - file and WebTool's own HTML files are located. By default - this is /priv]]>, and in most cases there - is no need to change this. If Path is set to - standard_path the default will be used.

-

If Data is set to PortNumber, the default data - will be used for ip-number (127.0.0.1) and server - name (localhost).

-
-
- - stop()->void - Stop WebTool. - -

Stop WebTool and the tools started by WebTool.

-
-
- - debug_app(Module)->void - Debug a WebTool application. - - Module = atom() - - -

Debug a WebTool application by tracing all functions in the - given module which are called from WebTool.

-
-
- - stop_debug()->void - Stop debugging an application and format the trace log. - -

Stop the tracing started by debug_app/1, and format - the trace log.

-
-
-
- -
- CALLBACK FUNCTIONS -

The following callback function must be implemented by each web - based tool that will be used via WebTool. When started, WebTool - searches the Erlang code path for *.tool files to locate all web - based tools and their callback functions. See the WebTool User's Guide for more - information about the *.tool files.

-
- - - Module:Func(Data)-> {Name,WebData}|error - Returns configuration data needed by WebTool to configure and start a tool. - - Data = term() - Name = atom() - WebData = [WebOptions] - WebOptions = LinkData | Alias | Start - LinkData = {web_data,{ToolName,Url}} - Alias = {alias,{VirtualPath,RealPath}} | {alias,{erl_alias,Path,[Modules]} - Start = {start,StartData} - ToolName = Url = VirtualPath = RealPath = Path = string() - Modules = atom() - StartData = AppData | ChildSpec | Func - AppData = {app,AppName} - ChildSpec = {child,child_spec()} - See the Reference Manual for the module supervisor in the STDLIB application for details about child_spec(). - Func = {func,{StartMod,StartFunc,StartArg}, {StopMod,StopFunc,StopArg}} - AppName = StartMod = StartFunc = StopMod = StopFunc =atom() - StartArg = StopArg = [term()] - - -

This is the configuration function (config_func) - which must be stated in the *.tool file.

-

The function is called by WebTool at startup to retrieve the - data needed to start and configure the tool. LinkData is - used by WebTool to create the link to the tool. Alias is - used to create the aliases needed by the webserver. Start - is used to start and stop the tool.

-
-
-
- -
- See Also -

start_webtool(1), - WebTool User's Guide

-
-
- diff --git a/lib/webtool/doc/src/webtool_chapter.xml b/lib/webtool/doc/src/webtool_chapter.xml deleted file mode 100644 index 160a42f855..0000000000 --- a/lib/webtool/doc/src/webtool_chapter.xml +++ /dev/null @@ -1,246 +0,0 @@ - - - - -
- - 20012013 - Ericsson AB. All Rights Reserved. - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - WebTool User Guide - - - - - webtool_chapter.xml -
- -
- Introduction -

WebTool provides an easy and efficient way to implement web - based tools with Erlang/OTP. WebTool configures and starts the - webserver and the various web based tools.

-

All tools that shall run under WebTool must have a *.tool - file in the code path or in its priv directory. When WebTool - starts it searches the code path for such files. For each - ebin directory in the path, the priv directory is - also searched. The *.tool files contain the configuration data - for each web based tool.

-
- -
- Starting WebTool -

Start WebTool by calling the function webtool:start/0 or - webtool:start/2. If webtool:start/0 is used the - start page of WebTool is available at - http://localhost:8888/ or - http://127.0.0.1:8888/, and the directory containing - the root directory for the webserver, is assumed to be - /priv]]>.

-

Use webtool:start/2 if the default path for the root - directory, port, ip-number or server name can not be used. See - the Reference Manual for webtool for more information.

-

WebTool, with the default configuration as in start/0, - can also be started with the start_webtool script which - is available in the priv directory of the WebTool - application. See the Reference Manual for start_webtool for further - information about this script. For Windows users, the batch file - start_webtool.bat can be used for the same purpose.

-
- -
- Using WebTool -

Start WebTool and point the browser to the corresponding URL. - At the top of the page there is a frame with a link named - WebTool. Click that link and a page where it is - possible to start the available tools will appear in the main - frame.

-
- -
- Start a web based tool -

Click on the link labeled WebTool in the topmost frame, - select the checkbox for each tool to start and - click on the button labeled Start. A link to each tool - that WebTool succeeded to start will appear in the topmost frame.

-
- -
- Stop a web based tool -

Click on the link labeled WebTool in the topmost - frame. Select Stop Tools in the left frame. Select the - checkbox for each tool to stop and click on the button labeled - Stop.

-
- -
- Develop new web based tools -

WebTool can be used as a framework when developing new web based - tools.

-

A web based tool running under WebTool will typically consist of - three parts.

- - A *.tool file which defines how WebTool can find the tool's - configuration data - The Erlang code generating the web interface to the tool (HTML - code) - The tool itself. - -

In most cases it is a good idea to separate the code for - creation of the html-pages and the code for the logic. This - increases the readability of the code and the logic might be - possible to reuse.

- -
- The *.tool file -

When WebTool starts it searches the current path for - *.tool files to find all available tools. The *.tool - file contains a version identifier and a list of tuples which - is the configuration data. The version identifier specifies - the *.tool file version, i.e. not the version of - webtool. Currently the only valid version is "1.2" and the - only valid configuration tag is - config_func. config_func specifies which - function WebTool must call to get further configuration data - for the tool. This means that a *.tool file generally must - look like this:

- - {version,"1.2"}. - [{config_func,{Module,Function,Arguments}}]. -

Module is the name of the module where the callback - function is defined. Function is the name of the - callback function, and Arguments is the list of - arguments to the callback function.

-
- -
- The configuration function -

The *.tool file points out a configuration function. This - function must return a list of configuration parameters (see - the Reference Manual for webtool).

-

The web_data parameter is mandatory and it specifies - the name of the tool and the link to the tool's start - page. All other parameters are optional.

-

If the tool requires any processes to run, the start - parameter specifies the function that WebTool must call in - order to start the process(es).

-

The alias parameters are passed directly on to the - webserver (INETS). The webserver has three ways to create - dynamic web pages CGI, Eval Scheme and Erl Scheme. All tools - running under WebTool must use Erl Scheme.

-

Erl Scheme tries to resemble plain CGI. The big difference is - that Erl Scheme can only execute Erlang code. The code will - furthermore be executed on the same instance as the webserver.

-

An URL which calls an Erlang function with Erl Scheme can have - the following syntax:

- ]]> -

An alias parameter in the configuration function can be - an ErlScriptAlias as used in the above URL. The definition of - an ErlScriptAlias shall be like this:

-

{alias,{erl_alias,Path,[Modules]}}, e.g.

-

{alias,{erl_alias,"/testtool",[helloworld]}}

-

The following URL will then cause a call to the function - helloworld:helloworld/2 (if WebTool is started with default - settings i.e. servername "localhost" and port 8888):

-

http://localhost:8888/testtool/helloworld/helloworld

-

Note that the module helloworld must be in the code - path of the node running WebTool.

-

Functions that are called via the Erl Scheme must take two - arguments, Environment and Input. -

- - Environment is a list of key/value tuples. - Input is the part of the URL after the "?", i.e. the - part of the URL containing name-value pairs. If the page was - called with the URL: -

-

-Input will be the string - . In the module - httpd in the INETS application there is a function - parse_query which will parse such a string and return - a list of key-value tuples.
-
-

An alias parameter in the configuration function can - also be a normal path alias. This can e.g. be used to point - out a directory where HTML files are stored. The following - definition states that the URL - http://localhost:8888/mytool_home/ really points to the - directory /usr/local/otp/lib/myapp-1.0/priv:

-

{alias,{"/mytool_home","/usr/local/otp/lib/myapp-1.0/priv"}}

-

See the INETS documentation, especially the module - mod_esi, for a more in depth coverage of the Erl Scheme.

-
- -
- A small example -

A Hello World example that uses Erl Scheme would look like - this. Note that this example does not have a process running - and thus does not need a start parameter in the - configuration function. -

-

helloworld.erl:

-
-        -module(helloworld).
-        -export([config_data/0]).
-        -export([helloworld/2]).
-        
-        config_data()->
-            {testtool,
-             [{web_data,{"TestTool","/testtool/helloworld/helloworld"}},
-              {alias,{erl_alias,"/testtool",[helloworld]}}]}.
-        
-        helloworld(_Env,_Input)->
-            [header(),html_header(),helloworld_body(),html_end()].
-
-        header() ->
-            header("text/html").
-
-        header(MimeType) ->
-            "Content-type: " ++ MimeType ++ "\r\n\r\n".
-
-        html_header() ->    
-            "<HTML>
-               <HEAD>
-                  <TITLE>Hello world Example </TITLE>
-               </HEAD>\n".
-
-        helloworld_body()->
-            "<BODY>Hello World</BODY>".
-
-        html_end()->
-            "</HTML>".
-      
-

To use this example with WebTool a *.tool file must be created - and added to a directory in the current path, e.g. the same - directory as the compiled helloworld.beam.

-

testtool.tool:

- - {version,"1.2"}. - [{config_func, {helloworld,config_data,[]}}]. - -

When helloworld.erl is compiled, start WebTool by - calling the function webtool:start() and point your - browser to http://localhost:8888/. Select WebTool in - the topmost frame and start TestTool from the web page. Click - on the link labeled TestTool in the topmost frame.

-
-
-
- diff --git a/lib/webtool/ebin/.gitignore b/lib/webtool/ebin/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/webtool/info b/lib/webtool/info deleted file mode 100644 index 4d8dc6f2cb..0000000000 --- a/lib/webtool/info +++ /dev/null @@ -1,2 +0,0 @@ -group: tools -short: A tool that simplifying the use of web based Erlang tools diff --git a/lib/webtool/priv/Makefile b/lib/webtool/priv/Makefile deleted file mode 100644 index 4963767a4d..0000000000 --- a/lib/webtool/priv/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -# ``Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../vsn.mk -VSN=$(WEBTOOL_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/webtool-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -WEBSERVER_CONFIG_FILES = root/conf/mime.types - -HTDOCS_FILES = root/doc/index.html \ - root/doc/tool_management.html \ - root/doc/start_info.html - -ifeq ($(findstring win32,$(TARGET)),win32) -WIN32_SCRIPTS= bin/start_webtool.bat -else -WIN32_SCRIPTS= -endif -SCRIPTS = bin/start_webtool $(WIN32_SCRIPTS) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: - -clean: - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/priv" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/root" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/conf" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/doc" - $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv/root/doc" - $(INSTALL_DATA) $(WEBSERVER_CONFIG_FILES) "$(RELSYSDIR)/priv/root/conf" - $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin" - $(INSTALL_SCRIPT) $(SCRIPTS) "$(RELSYSDIR)/priv/bin" - -release_docs_spec: - - diff --git a/lib/webtool/priv/bin/start_webtool b/lib/webtool/priv/bin/start_webtool deleted file mode 100755 index e552fb5af0..0000000000 --- a/lib/webtool/priv/bin/start_webtool +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -erl -sname webtool -s webtool script_start $@ diff --git a/lib/webtool/priv/bin/start_webtool.bat b/lib/webtool/priv/bin/start_webtool.bat deleted file mode 100644 index cd16aa6200..0000000000 --- a/lib/webtool/priv/bin/start_webtool.bat +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -CALL erl -sname webtool -s webtool script_start %* -s erlang halt \ No newline at end of file diff --git a/lib/webtool/priv/root/conf/mime.types b/lib/webtool/priv/root/conf/mime.types deleted file mode 100644 index 32f7cd853c..0000000000 --- a/lib/webtool/priv/root/conf/mime.types +++ /dev/null @@ -1,99 +0,0 @@ -# This is a comment. I love comments. - -application/activemessage -application/andrew-inset -application/applefile -application/atomicmail -application/dca-rft -application/dec-dx -application/mac-binhex40 hqx -application/mac-compactpro cpt -application/macwriteii -application/msword doc -application/news-message-id -application/news-transmission -application/octet-stream bin dms lha lzh exe class -application/oda oda -application/pdf pdf -application/postscript ai eps ps -application/powerpoint ppt -application/remote-printing -application/rtf rtf -application/slate -application/wita -application/wordperfect5.1 -application/x-bcpio bcpio -application/x-cdlink vcd -application/x-compress Z -application/x-cpio cpio -application/x-csh csh -application/x-director dcr dir dxr -application/x-dvi dvi -application/x-gtar gtar -application/x-gzip gz -application/x-hdf hdf -application/x-httpd-cgi cgi -application/x-koan skp skd skt skm -application/x-latex latex -application/x-mif mif -application/x-netcdf nc cdf -application/x-sh sh -application/x-shar shar -application/x-stuffit sit -application/x-sv4cpio sv4cpio -application/x-sv4crc sv4crc -application/x-tar tar -application/x-tcl tcl -application/x-tex tex -application/x-texinfo texinfo texi -application/x-troff t tr roff -application/x-troff-man man -application/x-troff-me me -application/x-troff-ms ms -application/x-ustar ustar -application/x-wais-source src -application/zip zip -audio/basic au snd -audio/mpeg mpga mp2 -audio/x-aiff aif aiff aifc -audio/x-pn-realaudio ram -audio/x-pn-realaudio-plugin rpm -audio/x-realaudio ra -audio/x-wav wav -chemical/x-pdb pdb xyz -image/gif gif -image/ief ief -image/jpeg jpeg jpg jpe -image/png png -image/tiff tiff tif -image/x-cmu-raster ras -image/x-portable-anymap pnm -image/x-portable-bitmap pbm -image/x-portable-graymap pgm -image/x-portable-pixmap ppm -image/x-rgb rgb -image/x-xbitmap xbm -image/x-xpixmap xpm -image/x-xwindowdump xwd -message/external-body -message/news -message/partial -message/rfc822 -multipart/alternative -multipart/appledouble -multipart/digest -multipart/mixed -multipart/parallel -text/html html htm -text/x-server-parsed-html shtml -text/plain txt -text/richtext rtx -text/tab-separated-values tsv -text/x-setext etx -text/x-sgml sgml sgm -video/mpeg mpeg mpg mpe -video/quicktime qt mov -video/x-msvideo avi -video/x-sgi-movie movie -x-conference/x-cooltalk ice -x-world/x-vrml wrl vrml diff --git a/lib/webtool/priv/root/doc/index.html b/lib/webtool/priv/root/doc/index.html deleted file mode 100644 index 9fbb143cc7..0000000000 --- a/lib/webtool/priv/root/doc/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - -Erlang WebTool - - - - - - - - diff --git a/lib/webtool/priv/root/doc/start_info.html b/lib/webtool/priv/root/doc/start_info.html deleted file mode 100644 index fcf44433f1..0000000000 --- a/lib/webtool/priv/root/doc/start_info.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - -
- - - - - - - - - - - - - -
Welcome
to
WebTool




-
Click on the link WebTool on the top of the page, or here to start the Web based tools.
- -
- - \ No newline at end of file diff --git a/lib/webtool/priv/root/doc/tool_management.html b/lib/webtool/priv/root/doc/tool_management.html deleted file mode 100644 index 19d9dbcb9e..0000000000 --- a/lib/webtool/priv/root/doc/tool_management.html +++ /dev/null @@ -1,9 +0,0 @@ - - -Erlang WebTool - - - - - - diff --git a/lib/webtool/src/Makefile b/lib/webtool/src/Makefile deleted file mode 100644 index a5a8eaf5dc..0000000000 --- a/lib/webtool/src/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2001-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../vsn.mk -VSN=$(WEBTOOL_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/webtool-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= webtool \ - webtool_sup - - - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) - -APP_FILE= webtool.app -APPUP_FILE= webtool.appup - -APP_SRC= $(APP_FILE).src -APPUP_SRC= $(APPUP_FILE).src - - -APP_TARGET= $(EBIN)/$(APP_FILE) -APPUP_TARGET= $(EBIN)/$(APPUP_FILE) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += +warn_obsolete_guard - - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) - -clean: - rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) - rm -f core - -docs: - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(APP_TARGET): $(APP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/src" - $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src" - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \ - "$(RELSYSDIR)/ebin" - -release_docs_spec: - diff --git a/lib/webtool/src/webtool.app.src b/lib/webtool/src/webtool.app.src deleted file mode 100644 index 6b9750c2b4..0000000000 --- a/lib/webtool/src/webtool.app.src +++ /dev/null @@ -1,28 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -{application,webtool, - [{description,"Toolbar lookalike for the web"}, - {vsn,"%VSN%"}, - {modules,[webtool,webtool_sup]}, - {registered,[web_tool,websup]}, - {applications,[kernel,stdlib]}, - {runtime_dependencies, ["stdlib-2.0","observer-2.0","kernel-3.0", - "inets-5.10","erts-6.0"]}]}. - diff --git a/lib/webtool/src/webtool.appup.src b/lib/webtool/src/webtool.appup.src deleted file mode 100644 index 1394d0d6d5..0000000000 --- a/lib/webtool/src/webtool.appup.src +++ /dev/null @@ -1,22 +0,0 @@ -%% -*- erlang -*- -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2014. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -{"%VSN%", - [{<<".*">>,[{restart_application, webtool}]}], - [{<<".*">>,[{restart_application, webtool}]}] -}. diff --git a/lib/webtool/src/webtool.erl b/lib/webtool/src/webtool.erl deleted file mode 100644 index 80dad53f8f..0000000000 --- a/lib/webtool/src/webtool.erl +++ /dev/null @@ -1,1208 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(webtool). --behaviour(gen_server). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The general idea is: %% -%% %% -%% %% -%% 1. Scan through the path for *.tool files and find all the web %% -%% based tools. Query each tool for configuration data. %% -%% 2. Add Alias for Erlscript and html for each tool to %% -%% the webserver configuration data. %% -%% 3. Start the webserver. %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% API functions --export([start/0, start/2, stop/0]). - -%% Starting Webtool from a shell script --export([script_start/0, script_start/1]). - -%% Web api --export([started_tools/2, toolbar/2, start_tools/2, stop_tools/2]). - -%% API against other tools --export([is_localhost/0]). - -%% Debug export s --export([get_tools1/1]). --export([debug/1, stop_debug/0, debug_app/1]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). - --include_lib("kernel/include/file.hrl"). --include_lib("stdlib/include/ms_transform.hrl"). - --record(state,{priv_dir,app_data,supvis,web_data,started=[]}). - --define(MAX_NUMBER_OF_WEBTOOLS,256). --define(DEFAULT_PORT,8888).% must be >1024 or the user must be root on unix --define(DEFAULT_ADDR,{127,0,0,1}). - --define(WEBTOOL_ALIAS,{webtool,[{alias,{erl_alias,"/webtool",[webtool]}}]}). --define(HEADER,"Pragma:no-cache\r\n Content-type: text/html\r\n\r\n"). --define(HTML_HEADER,"\r\n\r\nWebTool\r\n\r\n\r\n"). --define(HTML_HEADER_RELOAD,"\r\n\r\nWebTool - \r\n\r\n - \r\n"). - --define(HTML_END,""). - --define(SEND_URL_TIMEOUT,5000). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% For debugging only. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Start tracing with -%% debug(Functions). -%% Functions = local | global | FunctionList -%% FunctionList = [Function] -%% Function = {FunctionName,Arity} | FunctionName | -%% {Module, FunctionName, Arity} | {Module,FunctionName} -debug(F) -> - ttb:tracer(all,[{file,"webtool.trc"}]), % tracing all nodes - ttb:p(all,[call,timestamp]), - MS = [{'_',[],[{return_trace},{message,{caller}}]}], - tp(F,MS), - ttb:ctp(?MODULE,stop_debug), % don't want tracing of the stop_debug func - ok. -tp(local,MS) -> % all functions - ttb:tpl(?MODULE,MS); -tp(global,MS) -> % all exported functions - ttb:tp(?MODULE,MS); -tp([{M,F,A}|T],MS) -> % Other module - ttb:tpl(M,F,A,MS), - tp(T,MS); -tp([{M,F}|T],MS) when is_atom(F) -> % Other module - ttb:tpl(M,F,MS), - tp(T,MS); -tp([{F,A}|T],MS) -> % function/arity - ttb:tpl(?MODULE,F,A,MS), - tp(T,MS); -tp([F|T],MS) -> % function - ttb:tpl(?MODULE,F,MS), - tp(T,MS); -tp([],_MS) -> - ok. -stop_debug() -> - ttb:stop([format]). - -debug_app(Mod) -> - ttb:tracer(all,[{file,"webtool_app.trc"},{handler,{fun out/4,true}}]), - ttb:p(all,[call,timestamp]), - MS = [{'_',[],[{return_trace},{message,{caller}}]}], - ttb:tp(Mod,MS), - ok. - -out(_,{trace_ts,Pid,call,MFA={M,F,A},{W,_,_},TS},_,S) - when W==webtool;W==mod_esi-> - io:format("~w: (~p)~ncall ~s~n", [TS,Pid,ffunc(MFA)]), - [{M,F,length(A)}|S]; -out(_,{trace_ts,Pid,return_from,MFA,R,TS},_,[MFA|S]) -> - io:format("~w: (~p)~nreturned from ~s -> ~p~n", [TS,Pid,ffunc(MFA),R]), - S; -out(_,_,_,_) -> - ok. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Functions called via script. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -script_start() -> - usage(), - halt(). -script_start([App]) -> - DefaultBrowser = - case os:type() of - {win32,_} -> iexplore; - _ -> firefox - end, - script_start([App,DefaultBrowser]); -script_start([App,Browser]) -> - io:format("Starting webtool...\n"), - start(), - AvailableApps = get_applications(), - {OSType,_} = os:type(), - case lists:keysearch(App,1,AvailableApps) of - {value,{App,StartPage}} -> - io:format("Starting ~w...\n",[App]), - start_tools([],"app=" ++ atom_to_list(App)), - PortStr = integer_to_list(get_port()), - Url = case StartPage of - "/" ++ Page -> - "http://localhost:" ++ PortStr ++ "/" ++ Page; - _ -> - "http://localhost:" ++ PortStr ++ "/" ++ StartPage - end, - case Browser of - none -> - ok; - iexplore when OSType == win32-> - io:format("Starting internet explorer...\n"), - {ok,R} = win32reg:open(""), - Key="\\local_machine\\SOFTWARE\\Microsoft\\IE Setup\\Setup", - win32reg:change_key(R,Key), - {ok,Val} = win32reg:value(R,"Path"), - IExplore=filename:join(win32reg:expand(Val),"iexplore.exe"), - os:cmd("\"" ++ IExplore ++ "\" " ++ Url); - _ when OSType == win32 -> - io:format("Starting ~w...\n",[Browser]), - os:cmd("\"" ++ atom_to_list(Browser) ++ "\" " ++ Url); - B when B==firefox; B==mozilla -> - io:format("Sending URL to ~w...",[Browser]), - BStr = atom_to_list(Browser), - SendCmd = BStr ++ " -raise -remote \'openUrl(" ++ - Url ++ ")\'", - Port = open_port({spawn,SendCmd},[exit_status]), - receive - {Port,{exit_status,0}} -> - io:format("done\n"), - ok; - {Port,{exit_status,_Error}} -> - io:format(" not running, starting ~w...\n", - [Browser]), - os:cmd(BStr ++ " " ++ Url), - ok - after ?SEND_URL_TIMEOUT -> - io:format(" failed, starting ~w...\n",[Browser]), - erlang:port_close(Port), - os:cmd(BStr ++ " " ++ Url) - end; - _ -> - io:format("Starting ~w...\n",[Browser]), - os:cmd(atom_to_list(Browser) ++ " " ++ Url) - end, - ok; - false -> - stop(), - io:format("\n{error,{unknown_app,~p}}\n",[App]), - halt() - end. - -usage() -> - io:format("Starting webtool...\n"), - start(), - Apps = lists:map(fun({A,_}) -> A end,get_applications()), - io:format( - "\nUsage: start_webtool application [ browser ]\n" - "\nAvailable applications are: ~p\n" - "Default browser is \'iexplore\' (Internet Explorer) on Windows " - "or else \'firefox\'\n", - [Apps]), - stop(). - - -get_applications() -> - gen_server:call(web_tool,get_applications). - -get_port() -> - gen_server:call(web_tool,get_port). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Api functions to the genserver. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------------------------------------- -% -%---------------------------------------------------------------------- - -start()-> - start(standard_path,standard_data). - -start(Path,standard_data)-> - case get_standard_data() of - {error,Reason} -> - {error,Reason}; - Data -> - start(Path,Data) - end; - -start(standard_path,Data)-> - Path=get_path(), - start(Path,Data); - -start(Path,Port) when is_integer(Port)-> - Data = get_standard_data(Port), - start(Path,Data); - -start(Path,Data0)-> - Data = Data0 ++ rest_of_standard_data(), - gen_server:start({local,web_tool},webtool,{Path,Data},[]). - -stop()-> - gen_server:call(web_tool,stoppit). - -%---------------------------------------------------------------------- -%Web Api functions called by the web -%---------------------------------------------------------------------- -started_tools(Env,Input)-> - gen_server:call(web_tool,{started_tools,Env,Input}). - -toolbar(Env,Input)-> - gen_server:call(web_tool,{toolbar,Env,Input}). - -start_tools(Env,Input)-> - gen_server:call(web_tool,{start_tools,Env,Input}). - -stop_tools(Env,Input)-> - gen_server:call(web_tool,{stop_tools,Env,Input}). -%---------------------------------------------------------------------- -%Support API for other tools -%---------------------------------------------------------------------- - -is_localhost()-> - gen_server:call(web_tool,is_localhost). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%%The gen_server callback functions that builds the webbpages %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -handle_call(get_applications,_,State)-> - MS = ets:fun2ms(fun({Tool,{web_data,{_,Start}}}) -> {Tool,Start} end), - Tools = ets:select(State#state.app_data,MS), - {reply,Tools,State}; - -handle_call(get_port,_,State)-> - {value,{port,Port}}=lists:keysearch(port,1,State#state.web_data), - {reply,Port,State}; - -handle_call({started_tools,_Env,_Input},_,State)-> - {reply,started_tools_page(State),State}; - -handle_call({toolbar,_Env,_Input},_,State)-> - {reply,toolbar(),State}; - -handle_call({start_tools,Env,Input},_,State)-> - {NewState,Page}=start_tools_page(Env,Input,State), - {reply,Page,NewState}; - -handle_call({stop_tools,Env,Input},_,State)-> - {NewState,Page}=stop_tools_page(Env,Input,State), - {reply,Page,NewState}; - -handle_call(stoppit,_From,Data)-> - {stop,normal,ok,Data}; - -handle_call(is_localhost,_From,Data)-> - Result=case proplists:get_value(bind_address, Data#state.web_data) of - ?DEFAULT_ADDR -> - true; - _IpNumber -> - false - end, - {reply,Result,Data}. - - -handle_info(_Message,State)-> - {noreply,State}. - -handle_cast(_Request,State)-> - {noreply,State}. - -code_change(_,State,_)-> - {ok,State}. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% The other functions needed by the gen_server behaviour -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------------------------------------- -% Start the gen_server -%---------------------------------------------------------------------- -init({Path,Config})-> - case filelib:is_dir(Path) of - true -> - {ok, Table} = get_tool_files_data(), - insert_app(?WEBTOOL_ALIAS, Table), - case webtool_sup:start_link() of - {ok, Pid} -> - case start_webserver(Table, Path, Config) of - {ok, _} -> - print_url(Config), - {ok,#state{priv_dir=Path, - app_data=Table, - supvis=Pid, - web_data=Config}}; - {error, Error} -> - {stop, {error, Error}} - end; - Error -> - {stop,Error} - end; - false -> - {stop, {error, error_dir}} - end. - -terminate(_Reason,Data)-> - %%shut down the webbserver - shutdown_server(Data), - %%Shutdown the different tools that are started with application:start - shutdown_apps(Data), - %%Shutdown the supervisor and its children will die - shutdown_supervisor(Data), - ok. - -print_url(ConfigData)-> - Server=proplists:get_value(server_name,ConfigData,"undefined"), - Port=proplists:get_value(port,ConfigData,"undefined"), - {A,B,C,D}=proplists:get_value(bind_address,ConfigData,"undefined"), - io:format("WebTool is available at http://~s:~w/~n",[Server,Port]), - io:format("Or http://~w.~w.~w.~w:~w/~n",[A,B,C,D,Port]). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% begin build the pages -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -%The page that shows the started tools -%---------------------------------------------------------------------- -started_tools_page(State)-> - [?HEADER,?HTML_HEADER,started_tools(State),?HTML_END]. - -toolbar()-> - [?HEADER,?HTML_HEADER,toolbar_page(),?HTML_END]. - - -start_tools_page(_Env,Input,State)-> - %%io:format("~n======= ~n ~p ~n============~n",[Input]), - case get_tools(Input) of - {tools,Tools}-> - %%io:format("~n======= ~n ~p ~n============~n",[Tools]), - {ok,NewState}=handle_apps(Tools,State,start), - {NewState,[?HEADER,?HTML_HEADER_RELOAD,reload_started_apps(), - show_unstarted_apps(NewState),?HTML_END]}; - _ -> - {State,[?HEADER,?HTML_HEADER,show_unstarted_apps(State),?HTML_END]} - end. - -stop_tools_page(_Env,Input,State)-> - case get_tools(Input) of - {tools,Tools}-> - {ok,NewState}=handle_apps(Tools,State,stop), - {NewState,[?HEADER,?HTML_HEADER_RELOAD,reload_started_apps(), - show_started_apps(NewState),?HTML_END]}; - _ -> - {State,[?HEADER,?HTML_HEADER,show_started_apps(State),?HTML_END]} - end. - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% Functions that start and config the webserver -%% 1. Collect the config data -%% 2. Start webserver -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -% Start the webserver -%---------------------------------------------------------------------- -start_webserver(Data,Path,Config)-> - case get_conf_data(Data,Path,Config) of - {ok,Conf_data}-> - %%io:format("Conf_data: ~p~n",[Conf_data]), - start_server(Conf_data); - {error,Error} -> - {error,{error_server_conf_file,Error}} - end. - -start_server(Conf_data)-> - case inets:start(httpd, Conf_data, stand_alone) of - {ok,Pid}-> - {ok,Pid}; - Error-> - {error,{server_error,Error}} - end. - -%---------------------------------------------------------------------- -% Create config data for the webserver -%---------------------------------------------------------------------- -get_conf_data(Data,Path,Config)-> - Aliases=get_aliases(Data), - ServerRoot = filename:join([Path,"root"]), - MimeTypesFile = filename:join([ServerRoot,"conf","mime.types"]), - case httpd_conf:load_mime_types(MimeTypesFile) of - {ok,MimeTypes} -> - Config1 = Config ++ Aliases, - Config2 = [{server_root,ServerRoot}, - {document_root,filename:join([Path,"root/doc"])}, - {mime_types,MimeTypes} | - Config1], - {ok,Config2}; - Error -> - Error - end. - -%---------------------------------------------------------------------- -% Control the path for *.tools files -%---------------------------------------------------------------------- -get_tool_files_data()-> - Tools=get_tools1(code:get_path()), - %%io:format("Data : ~p ~n",[Tools]), - get_file_content(Tools). - -%---------------------------------------------------------------------- -%Control that the data in the file really is erlang terms -%---------------------------------------------------------------------- -get_file_content(Tools)-> - Get_data=fun({tool,ToolData}) -> - %%io:format("Data : ~p ~n",[ToolData]), - case proplists:get_value(config_func,ToolData) of - {M,F,A}-> - case catch apply(M,F,A) of - {'EXIT',_} -> - bad_data; - Data when is_tuple(Data) -> - Data; - _-> - bad_data - end; - _ -> - bad_data - end - end, - insert_file_content([X ||X<-lists:map(Get_data,Tools),X/=bad_data]). - -%---------------------------------------------------------------------- -%Insert the data from the file in to the ets:table -%---------------------------------------------------------------------- -insert_file_content(Content)-> - Table=ets:new(app_data,[bag]), - lists:foreach(fun(X)-> - insert_app(X,Table) - end,Content), - {ok,Table}. - -%---------------------------------------------------------------------- -%Control that we got a a tuple of a atom and a list if so add the -%elements in the list to the ets:table -%---------------------------------------------------------------------- -insert_app({Name,Key_val_list},Table) when is_list(Key_val_list),is_atom(Name)-> - %%io:format("ToolData: ~p: ~p~n",[Name,Key_val_list]), - lists:foreach( - fun({alias,{erl_alias,Alias,Mods}}) -> - Key_val = {erl_script_alias,{Alias,Mods}}, - %%io:format("Insert: ~p~n",[Key_val]), - ets:insert(Table,{Name,Key_val}); - (Key_val_pair)-> - %%io:format("Insert: ~p~n",[Key_val_pair]), - ets:insert(Table,{Name,Key_val_pair}) - end, - Key_val_list); - -insert_app(_,_)-> - ok. - -%---------------------------------------------------------------------- -% Select all the alias in the database -%---------------------------------------------------------------------- -get_aliases(Data)-> - MS = ets:fun2ms(fun({_,{erl_script_alias,Alias}}) -> - {erl_script_alias,Alias}; - ({_,{alias,Alias}}) -> - {alias,Alias} - end), - ets:select(Data,MS). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Helper functions %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_standard_data(Port)-> - [ - {port,Port}, - {bind_address,?DEFAULT_ADDR}, - {server_name,"localhost"} - ]. - -get_standard_data()-> - case get_free_port(?DEFAULT_PORT,?MAX_NUMBER_OF_WEBTOOLS) of - {error,Reason} -> {error,Reason}; - Port -> - [ - {port,Port}, - {bind_address,?DEFAULT_ADDR}, - {server_name,"localhost"} - ] - end. - -get_free_port(_Port,0) -> - {error,no_free_port_found}; -get_free_port(Port,N) -> - case gen_tcp:connect("localhost",Port,[]) of - {error, _Reason} -> - Port; - {ok,Sock} -> - gen_tcp:close(Sock), - get_free_port(Port+1,N-1) - end. - -rest_of_standard_data() -> - [ - %% Do not allow the server to be crashed by malformed http-request - {max_header_siz,1024}, - {max_header_action,reply414}, - %% Go on a straight ip-socket - {com_type,ip_comm}, - %% Do not change the order of these module names!! - {modules,[mod_alias, - mod_auth, - mod_esi, - mod_actions, - mod_cgi, - mod_include, - mod_dir, - mod_get, - mod_head, - mod_log, - mod_disk_log]}, - {directory_index,["index.html"]}, - {default_type,"text/plain"} - ]. - - -get_path()-> - code:priv_dir(webtool). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% These functions is used to shutdown the webserver -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -% Shut down the webbserver -%---------------------------------------------------------------------- -shutdown_server(State)-> - {Addr,Port} = get_addr_and_port(State#state.web_data), - inets:stop(httpd,{Addr,Port}). - -get_addr_and_port(Config) -> - Addr = proplists:get_value(bind_address,Config,?DEFAULT_ADDR), - Port = proplists:get_value(port,Config,?DEFAULT_PORT), - {Addr,Port}. - -%---------------------------------------------------------------------- -% Select all apps in the table and close them -%---------------------------------------------------------------------- -shutdown_apps(State)-> - Data=State#state.app_data, - MS = ets:fun2ms(fun({_,{start,HowToStart}}) -> HowToStart end), - lists:foreach(fun(Start_app)-> - stop_app(Start_app) - end, - ets:select(Data,MS)). - -%---------------------------------------------------------------------- -%Shuts down the supervisor that supervises tools that is not -%Designed as applications -%---------------------------------------------------------------------- -shutdown_supervisor(State)-> - %io:format("~n==================~n"), - webtool_sup:stop(State#state.supvis). - %io:format("~n==================~n"). - -%---------------------------------------------------------------------- -%close the individual apps. -%---------------------------------------------------------------------- -stop_app({child,_Real_name})-> - ok; - -stop_app({app,Real_name})-> - application:stop(Real_name); - -stop_app({func,_Start,Stop})-> - case Stop of - {M,F,A} -> - catch apply(M,F,A); - _NoStop -> - ok - end. - - - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% These functions creates the webpage where the user can select if -%% to start apps or to stop apps -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -toolbar_page()-> - " - - - - - - - - - -
- Select Action -
- Start Tools -
- Stop Tools -
". -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% These functions creates the webbpage that shows the started apps -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%---------------------------------------------------------------------- -% started_tools(State)->String (html table) -% State is a record of type state -%---------------------------------------------------------------------- -started_tools(State)-> - Names=get_started_apps(State#state.app_data,State#state.started), - " - "++ make_rows(Names,[],0) ++" -
". -%---------------------------------------------------------------------- -%get_started_apps(Data,Started)-> [{web_name,link}] -%selects the started apps from the ets table of apps. -%---------------------------------------------------------------------- - -get_started_apps(Data,Started)-> - SelectData=fun({Name,Link}) -> - {Name,Link} - end, - MS = lists:map(fun(A) -> {{A,{web_data,'$1'}},[],['$1']} end,Started), - - [{"WebTool","/tool_management.html"} | - [SelectData(X) || X <- ets:select(Data,MS)]]. - -%---------------------------------------------------------------------- -% make_rows(List,Result,Fields)-> String (The rows of a htmltable -% List a list of tupler discibed above -% Result an accumulator for the result -% Field, counter that counts the number of cols in each row. -%---------------------------------------------------------------------- -make_rows([],Result,Fields)-> - Result ++ fill_out(Fields); -make_rows([Data|Paths],Result,Field)when Field==0-> - make_rows(Paths,Result ++ "" ++ make_field(Data),Field+1); - -make_rows([Path|Paths],Result,Field)when Field==4-> - make_rows(Paths,Result ++ make_field(Path) ++ "",0); - -make_rows([Path|Paths],Result,Field)-> - make_rows(Paths,Result ++ make_field(Path),Field+1). - -%---------------------------------------------------------------------- -% make_fields(Path)-> String that is a field i a html table -% Path is a name url tuple {Name,url} -%---------------------------------------------------------------------- -make_field(Path)-> - "" ++ get_name(Path) ++ "". - - -%---------------------------------------------------------------------- -%get_name({Nae,Url})->String that represents a tag in html. -%---------------------------------------------------------------------- -get_name({Name,Url})-> - "" ++ Name ++ "". - - -%---------------------------------------------------------------------- -% fill_out(Nr)-> String, that represent Nr fields in a html-table. -%---------------------------------------------------------------------- -fill_out(Nr)when Nr==0-> - []; -fill_out(Nr)when Nr==4-> - " "; - -fill_out(Nr)-> - " " ++ fill_out(Nr+1). - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%%These functions starts applicatons and builds the page showing tools -%%to start -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------------------------------------- -%Controls whether the user selected a tool to start -%---------------------------------------------------------------------- -get_tools(Input)-> - case httpd:parse_query(Input) of - []-> - no_tools; - Tools-> - FormatData=fun({_Name,Data}) -> list_to_atom(Data) end, - SelectData= - fun({Name,_Data}) -> string:equal(Name,"app") end, - {tools,[FormatData(X)||X<-Tools,SelectData(X)]} - end. - -%---------------------------------------------------------------------- -% Selects the data to start the applications the user has ordered -% starting of -%---------------------------------------------------------------------- -handle_apps([],State,_Cmd)-> - {ok,State}; - -handle_apps([Tool|Tools],State,Cmd)-> - case ets:match_object(State#state.app_data,{Tool,{start,'_'}}) of - []-> - Started = case Cmd of - start -> - [Tool|State#state.started]; - stop -> - lists:delete(Tool,State#state.started) - end, - {ok,#state{priv_dir=State#state.priv_dir, - app_data=State#state.app_data, - supvis=State#state.supvis, - web_data=State#state.web_data, - started=Started}}; - ToStart -> - case handle_apps2(ToStart,State,Cmd) of - {ok,NewState}-> - handle_apps(Tools,NewState,Cmd); - _-> - handle_apps(Tools,State,Cmd) - end - end. - -%---------------------------------------------------------------------- -%execute every start or stop data about a tool. -%---------------------------------------------------------------------- -handle_apps2([{Name,Start_data}],State,Cmd)-> - case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd) of - ok-> - Started = case Cmd of - start -> - [Name|State#state.started]; - stop -> - - lists:delete(Name,State#state.started) - end, - {ok,#state{priv_dir=State#state.priv_dir, - app_data=State#state.app_data, - supvis=State#state.supvis, - web_data=State#state.web_data, - started=Started}}; - _-> - error - end; - -handle_apps2([{Name,Start_data}|Rest],State,Cmd)-> - case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd)of - ok-> - handle_apps2(Rest,State,Cmd); - _-> - error - end. - - -%---------------------------------------------------------------------- -% Handle start and stop of applications -%---------------------------------------------------------------------- - -handle_app({Name,{start,{func,Start,Stop}}},Data,_Pid,Cmd)-> - Action = case Cmd of - start -> - Start; - _ -> - Stop - end, - case Action of - {M,F,A} -> - case catch apply(M,F,A) of - {'EXIT',_} = Exit-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "~w:~w(~s) ->\n" - "~p\n\n", - [?LINE,Name,M,F,format_args(A),Exit]), - ets:delete(Data,Name); - _OK-> - ok - end; - _NoStart -> - ok - end; - - -handle_app({Name,{start,{child,ChildSpec}}},Data,Pid,Cmd)-> - case Cmd of - start -> - case catch supervisor:start_child(Pid,ChildSpec) of - {ok,_}-> - ok; - {ok,_,_}-> - ok; - {error,Reason}-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "supervisor:start_child(~p,~p) ->\n" - "~p\n\n", - [?LINE,Name,Pid,ChildSpec,{error,Reason}]), - ets:delete(Data,Name); - Error -> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "supervisor:start_child(~p,~p) ->\n" - "~p\n\n", - [?LINE,Name,Pid,ChildSpec,Error]), - ets:delete(Data,Name) - end; - stop -> - case catch supervisor:terminate_child(websup,element(1,ChildSpec)) of - ok -> - supervisor:delete_child(websup,element(1,ChildSpec)); - _ -> - error - end - end; - - - -handle_app({Name,{start,{app,Real_name}}},Data,_Pid,Cmd)-> - case Cmd of - start -> - case application:start(Real_name,temporary) of - ok-> - io:write(Name), - ok; - {error,{already_started,_}}-> - %% Remove it from the database so we dont start - %% anything already started - ets:match_delete(Data,{Name,{start,{app,Real_name}}}), - ok; - {error,_Reason}=Error-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not start application \'~p\'\n\n" - "application:start(~p,~p) ->\n" - "~p\n\n", - [?LINE,Name,Real_name,temporary,Error]), - ets:delete(Data,Name) - end; - - stop -> - application:stop(Real_name) - end; - -%---------------------------------------------------------------------- -% If the data is incorrect delete the app -%---------------------------------------------------------------------- -handle_app({Name,Incorrect},Data,_Pid,Cmd)-> - %%! Here the tool disappears from the webtool interface!! - io:format("\n=======ERROR (webtool, line ~w) =======\n" - "Could not ~w application \'~p\'\n\n" - "Incorrect data: ~p\n\n", - [?LINE,Cmd,Name,Incorrect]), - ets:delete(Data,Name). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% this functions creates the page that shows the unstarted tools %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -reload_started_apps()-> - "". - -show_unstarted_apps(State)-> - " - - -
-
- - - - - - - - -
Available Tools
- - "++ list_available_apps(State)++" - - - - -
 
- -
-
- To Start a Tool: -
    -
  • Select the - checkbox for each tool to - start.
  • -
  • Click on the - button marked Start.
-
-
-
 
". - - - -list_available_apps(State)-> - MS = ets:fun2ms(fun({Tool,{web_data,{Name,_}}}) -> {Tool,Name} end), - Unstarted_apps= - lists:filter( - fun({Tool,_})-> - false==lists:member(Tool,State#state.started) - end, - ets:select(State#state.app_data,MS)), - case Unstarted_apps of - []-> - "All tools are started"; - _-> - list_apps(Unstarted_apps) - end. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% these functions creates the page that shows the started apps %% -%% the user can select to shutdown %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -show_started_apps(State)-> - " - - -
-
- - - - - - - - -
Started Tools
- - "++ list_started_apps(State)++" - - - - -
 
- -
-
- Stop a Tool: -
    -
  • Select the - checkbox for each tool to - stop.
  • -
  • Click on the - button marked Stop.
-
-
-
 
". - -list_started_apps(State)-> - MS = lists:map(fun(A) -> {{A,{web_data,{'$1','_'}}},[],[{{A,'$1'}}]} end, - State#state.started), - Started_apps= ets:select(State#state.app_data,MS), - case Started_apps of - []-> - "No tool is started yet."; - _-> - list_apps(Started_apps) - end. - - -list_apps(Apps) -> - lists:map(fun({Tool,Name})-> - " - - " ++ Name ++ " - " - end, - Apps). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Collecting the data from the *.tool files %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%---------------------------------------- -% get_tools(Dirs) => [{M,F,A},{M,F,A}...{M,F,A}] -% Dirs - [string()] Directory names -% Calls get_tools2/2 recursively for a number of directories -% to retireve the configuration data for the web based tools. -%---------------------------------------- -get_tools1(Dirs)-> - get_tools1(Dirs,[]). - -get_tools1([Dir|Rest],Data) when is_list(Dir) -> - Tools=case filename:basename(Dir) of - %% Dir is an 'ebin' directory, check in '../priv' as well - "ebin" -> - [get_tools2(filename:join(filename:dirname(Dir),"priv")) | - get_tools2(Dir)]; - _ -> - get_tools2(Dir) - end, - get_tools1(Rest,[Tools|Data]); - -get_tools1([],Data) -> - lists:flatten(Data). - -%---------------------------------------- -% get_tools2(Directory) => DataList -% DataList : [WebTuple]|[] -% WebTuple: {tool,[{web,M,F,A}]} -% -%---------------------------------------- -get_tools2(Dir)-> - get_tools2(tool_files(Dir),[]). - -get_tools2([ToolFile|Rest],Data) -> - case get_tools3(ToolFile) of - {tool,WebData} -> - get_tools2(Rest,[{tool,WebData}|Data]); - {error,_Reason} -> - get_tools2(Rest,Data); - nodata -> - get_tools2(Rest,Data) - end; - -get_tools2([],Data) -> - Data. - -%---------------------------------------- -% get_tools3(ToolFile) => {ok,Tool}|{error,Reason}|nodata -% Tool: {tool,[KeyValTuple]} -% ToolFile - string() A .tool file -% Now we have the file get the data and sort it out -%---------------------------------------- -get_tools3(ToolFile) -> - case file:consult(ToolFile) of - {error,open} -> - {error,nofile}; - {error,read} -> - {error,format}; - {ok,[{version,"1.2"},ToolInfo]} when is_list(ToolInfo)-> - webdata(ToolInfo); - {ok,[{version,_Vsn},_Info]} -> - {error,old_version}; - {ok,_Other} -> - {error,format} - end. - - -%---------------------------------------------------------------------- -% webdata(TupleList)-> ToolTuple| nodata -% ToolTuple: {tool,[{config_func,{M,F,A}}]} -% -% There are a little unneccesary work in this format but it is extendable -%---------------------------------------------------------------------- -webdata(TupleList)-> - case proplists:get_value(config_func,TupleList,nodata) of - {M,F,A} -> - {tool,[{config_func,{M,F,A}}]}; - _ -> - nodata - end. - - -%============================================================================= -% Functions for getting *.tool configuration files -%============================================================================= - -%---------------------------------------- -% tool_files(Dir) => ToolFiles -% Dir - string() Directory name -% ToolFiles - [string()] -% Return the list of all files in Dir ending with .tool (appended to Dir) -%---------------------------------------- -tool_files(Dir) -> - case file:list_dir(Dir) of - {ok,Files} -> - filter_tool_files(Dir,Files); - {error,_Reason} -> - [] - end. - -%---------------------------------------- -% filter_tool_files(Dir,Files) => ToolFiles -% Dir - string() Directory name -% Files, ToolFiles - [string()] File names -% Filters out the files in Files ending with .tool and append them to Dir -%---------------------------------------- -filter_tool_files(_Dir,[]) -> - []; -filter_tool_files(Dir,[File|Rest]) -> - case filename:extension(File) of - ".tool" -> - [filename:join(Dir,File)|filter_tool_files(Dir,Rest)]; - _ -> - filter_tool_files(Dir,Rest) - end. - - -%%%----------------------------------------------------------------- -%%% format functions -ffunc({M,F,A}) when is_list(A) -> - io_lib:format("~w:~w(~s)\n",[M,F,format_args(A)]); -ffunc({M,F,A}) when is_integer(A) -> - io_lib:format("~w:~w/~w\n",[M,F,A]). - -format_args([]) -> - ""; -format_args(Args) -> - Str = lists:append(["~p"|lists:duplicate(length(Args)-1,",~p")]), - io_lib:format(Str,Args). diff --git a/lib/webtool/src/webtool_sup.erl b/lib/webtool/src/webtool_sup.erl deleted file mode 100644 index e4a05c53ae..0000000000 --- a/lib/webtool/src/webtool_sup.erl +++ /dev/null @@ -1,75 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(webtool_sup). - --behaviour(supervisor). - -%% External exports --export([start_link/0,stop/1]). - -%% supervisor callbacks --export([init/1]). - -%%%---------------------------------------------------------------------- -%%% API -%%%---------------------------------------------------------------------- -start_link() -> - supervisor:start_link({local,websup},webtool_sup, []). - -stop(Pid)-> - exit(Pid,normal). -%%%---------------------------------------------------------------------- -%%% Callback functions from supervisor -%%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, {SupFlags, [ChildSpec]}} | -%% ignore | -%% {error, Reason} -%%---------------------------------------------------------------------- -init(_StartArgs) -> - %%Child1 = - %%Child2 ={webcover_backend,{webcover_backend,start_link,[]},permanent,2000,worker,[webcover_backend]}, - %%{ok,{{simple_one_for_one,5,10},[Child1]}}. - {ok,{{one_for_one,100,10},[]}}. - -%%%---------------------------------------------------------------------- -%%% Internal functions -%%%---------------------------------------------------------------------- - - - - - - - - - - - - - - - - - - - diff --git a/lib/webtool/test/Makefile b/lib/webtool/test/Makefile deleted file mode 100644 index 93aa1c09eb..0000000000 --- a/lib/webtool/test/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - webtool_SUITE - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) -INSTALL_PROGS= $(TARGET_FILES) - -EMAKEFILE=Emakefile - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/webtool_test - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- - -ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include - -EBIN = . - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -make_emakefile: - $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ - > $(EMAKEFILE) - $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \ - >> $(EMAKEFILE) - -tests debug opt: make_emakefile - erl $(ERL_MAKE_FLAGS) -make - -clean: - rm -f $(EMAKEFILE) - rm -f $(TARGET_FILES) $(GEN_FILES) - rm -f core - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - -release_tests_spec: make_emakefile - $(INSTALL_DIR) "$(RELSYSDIR)" - $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)" - $(INSTALL_DATA) webtool.spec "$(RELSYSDIR)" - chmod -R u+w "$(RELSYSDIR)" - -release_docs_spec: diff --git a/lib/webtool/test/webtool.spec b/lib/webtool/test/webtool.spec deleted file mode 100644 index 134e6ed40c..0000000000 --- a/lib/webtool/test/webtool.spec +++ /dev/null @@ -1 +0,0 @@ -{suites,"../webtool_test",all}. diff --git a/lib/webtool/test/webtool_SUITE.erl b/lib/webtool/test/webtool_SUITE.erl deleted file mode 100644 index 9e2d9a2e0f..0000000000 --- a/lib/webtool/test/webtool_SUITE.erl +++ /dev/null @@ -1,51 +0,0 @@ -%% ``Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. -%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -%% AB. All Rights Reserved.'' -%% --module(webtool_SUITE). - --compile([export_all]). --include_lib("common_test/include/ct.hrl"). - -suite() -> - [{ct_hooks, [ts_install_cth]}]. - -all() -> - [app, appup]. - -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -app() -> - [{doc, "Test that the webtool app file is ok"}]. -app(Config) when is_list(Config) -> - ok = ?t:app_test(webtool). - -appup() -> - [{doc, "Test that the webtool appup file is ok"}]. -appup(Config) when is_list(Config) -> - ok = ?t:appup_test(webtool). diff --git a/lib/webtool/vsn.mk b/lib/webtool/vsn.mk deleted file mode 100644 index 4a701ae6e0..0000000000 --- a/lib/webtool/vsn.mk +++ /dev/null @@ -1 +0,0 @@ -WEBTOOL_VSN=0.9 -- cgit v1.2.3 From 28609dd161b7975f86c179a9ab54506c1d04a1fe Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 15 Oct 2015 15:58:25 +0200 Subject: ssh: Add a 1024 group to the list of key gex groups --- lib/ssh/src/ssh_transport.hrl | 3 ++- lib/ssh/vsn.mk | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 96ab1bb668..04e587ff34 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -258,7 +258,8 @@ {8192, {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF}}). --define(dh_default_groups, [?dh_group14, +-define(dh_default_groups, [?dh_group1, + ?dh_group14, ?dh_group15, ?dh_group16, ?dh_group17, diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 997c544c45..5bb18a656a 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.1.1 +SSH_VSN = 4.1.2 APP_VSN = "ssh-$(SSH_VSN)" -- cgit v1.2.3 From 1609b74689178627d1345f64e87d58b8249b6fde Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 8 Oct 2015 16:45:28 +0200 Subject: ssh: set dh_gex default to group14 --- lib/ssh/src/ssh_transport.hrl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 04e587ff34..337f455279 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -33,7 +33,7 @@ -define(MAX_NUM_ALGORITHMS, 200). -define(DEFAULT_DH_GROUP_MIN, 1024). --define(DEFAULT_DH_GROUP_NBITS, 6144). +-define(DEFAULT_DH_GROUP_NBITS, 2048). -define(DEFAULT_DH_GROUP_MAX, 8192). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From a2235c63238e1bfa9aefa4778260c671cdd4b61b Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Thu, 15 Oct 2015 16:31:18 +0200 Subject: Update release notes --- lib/ssh/doc/src/notes.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'lib') diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 0c0c947f65..bb111c8e0e 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,21 @@ notes.xml +
Ssh 4.1.2 + +
Fixed Bugs and Malfunctions + + +

+ Add a 1024 group to the list of key group-exchange groups

+

+ Own Id: OTP-13046

+
+
+
+ +
+
Ssh 4.1.1
Improvements and New Features -- cgit v1.2.3 From 01d1e4dc9a6e7ea958683ab419dea38bf576a39f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 13 Oct 2015 09:21:02 +0200 Subject: ssh, public_key: Change EC Public Key representation to what was intended --- lib/public_key/src/pubkey_ssh.erl | 76 ++++++++-------- lib/public_key/src/public_key.erl | 16 ++++ lib/ssh/src/ssh.hrl | 13 ++- lib/ssh/src/ssh_auth.erl | 17 ++-- lib/ssh/src/ssh_connection_handler.erl | 1 + lib/ssh/src/ssh_file.erl | 13 +-- lib/ssh/src/ssh_message.erl | 162 ++++++++++++++------------------- lib/ssh/src/ssh_transport.erl | 100 +++++++++++--------- lib/ssh/test/ssh_test_lib.erl | 11 +-- lib/ssh/test/ssh_trpt_test_lib.erl | 2 +- 10 files changed, 204 insertions(+), 207 deletions(-) (limited to 'lib') diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl index 26fbeb68ce..3addbfe3c6 100644 --- a/lib/public_key/src/pubkey_ssh.erl +++ b/lib/public_key/src/pubkey_ssh.erl @@ -21,7 +21,8 @@ -include("public_key.hrl"). --export([decode/2, encode/2]). +-export([decode/2, encode/2 + ]). -define(UINT32(X), X:32/unsigned-big-integer). -define(STRING(X), ?UINT32((size(X))), (X)/binary). @@ -33,6 +34,7 @@ %% are still compliant.)" So we choose to use 68 also. -define(ENCODED_LINE_LENGTH, 68). + %%==================================================================== %% Internal application API %%==================================================================== @@ -133,12 +135,11 @@ rfc4716_pubkey_decode(<>) when Type == <<"ecdsa-sha2-nistp256">>; - Type == <<"ecdsa-sha2-nistp384">>; - Type == <<"ecdsa-sha2-nistp521">> -> - {#'ECPoint'{point = Q}, Id}. + ?UINT32(SizeQ), Q:SizeQ/binary>>) -> + <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc, + {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. openssh_decode(Bin, FileType) -> Lines = binary:split(Bin, <<"\n">>, [global]), @@ -192,26 +193,28 @@ do_openssh_decode(known_hosts = FileType, [Line | Lines], Acc) -> end; do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) -> - case split_n(2, Line, []) of - [KeyType, Base64Enc] when KeyType == <<"ssh-rsa">>; - KeyType == <<"ssh-dss">>; - KeyType == <<"ecdsa-sha2-nistp256">>; - KeyType == <<"ecdsa-sha2-nistp384">>; - KeyType == <<"ecdsa-sha2-nistp521">> -> + [KeyType, Base64Enc | Comment0] = split_n(2, Line, []), + KnownKeyType = + case KeyType of + <<"ssh-rsa">> -> true; + <<"ssh-dss">> -> true; + <<"ecdsa-sha2-",Curve/binary>> -> is_ssh_curvename(Curve); + _ -> false + end, + + case Comment0 of + [] when KnownKeyType==true -> do_openssh_decode(FileType, Lines, [{openssh_pubkey_decode(KeyType, Base64Enc), []} | Acc]); - [KeyType, Base64Enc | Comment0] when KeyType == <<"ssh-rsa">>; - KeyType == <<"ssh-dss">>; - KeyType == <<"ecdsa-sha2-nistp256">>; - KeyType == <<"ecdsa-sha2-nistp384">>; - KeyType == <<"ecdsa-sha2-nistp521">> -> + _ when KnownKeyType==true -> Comment = string:strip(string_decode(iolist_to_binary(Comment0)), right, $\n), do_openssh_decode(FileType, Lines, [{openssh_pubkey_decode(KeyType, Base64Enc), [{comment, Comment}]} | Acc]) end. + decode_comment([]) -> []; decode_comment(Comment) -> @@ -244,7 +247,7 @@ openssh_pubkey_decode(<<"ecdsa-sha2-", Id/binary>>, Base64Enc) -> ?UINT32(SizeId), Id:SizeId/binary, ?UINT32(SizeQ), Q:SizeQ/binary>> = base64:mime_decode(Base64Enc), - {#'ECPoint'{point = Q}, Id}; + {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}; openssh_pubkey_decode(KeyType, Base64Enc) -> {KeyType, base64:mime_decode(Base64Enc)}. @@ -372,12 +375,9 @@ line_end("") -> line_end(Comment) -> [" ", Comment, "\n"]. -key_type(#'RSAPublicKey'{}) -> - <<"ssh-rsa">>; -key_type({_, #'Dss-Parms'{}}) -> - <<"ssh-dss">>; -key_type({#'ECPoint'{}, Id}) -> - <<"ecdsa-sha2-",Id/binary>>. +key_type(#'RSAPublicKey'{}) -> <<"ssh-rsa">>; +key_type({_, #'Dss-Parms'{}}) -> <<"ssh-dss">>; +key_type({#'ECPoint'{}, {namedCurve,Curve}}) -> <<"ecdsa-sha2-", (public_key:oid2ssh_curvename(Curve))/binary>>. comma_list_encode([Option], []) -> Option; @@ -408,25 +408,18 @@ ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> QBin/binary, GBin/binary, YBin/binary>>; -ssh2_pubkey_encode({#'ECPoint'{point = Q}, Id}) -> - TypeStr = <<"ecdsa-sha2-", Id/binary>>, +ssh2_pubkey_encode(Key={#'ECPoint'{point = Q}, {namedCurve,OID}}) -> + TypeStr = key_type(Key), StrLen = size(TypeStr), + IdB = public_key:oid2ssh_curvename(OID), <>. -is_key_field(<<"ssh-dss">>) -> - true; -is_key_field(<<"ssh-rsa">>) -> - true; -is_key_field(<<"ecdsa-sha2-nistp256">>) -> - true; -is_key_field(<<"ecdsa-sha2-nistp384">>) -> - true; -is_key_field(<<"ecdsa-sha2-nistp521">>) -> - true; -is_key_field(_) -> - false. +is_key_field(<<"ssh-dss">>) -> true; +is_key_field(<<"ssh-rsa">>) -> true; +is_key_field(<<"ecdsa-sha2-",Id/binary>>) -> is_ssh_curvename(Id); +is_key_field(_) -> false. is_bits_field(Part) -> try list_to_integer(binary_to_list(Part)) of @@ -546,3 +539,8 @@ string(X) when is_binary(X) -> << ?STRING(X) >>; string(X) -> << ?STRING(list_to_binary(X)) >>. + +is_ssh_curvename(Id) -> try public_key:ssh_curvename2oid(Id) of _ -> true + catch _:_ -> false + end. + diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 2f4cc64c2a..2b04b3f79b 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -47,6 +47,7 @@ pkix_normalize_name/1, pkix_path_validation/3, ssh_decode/2, ssh_encode/2, + ssh_curvename2oid/1, oid2ssh_curvename/1, pkix_crls_validate/3, pkix_dist_point/1, pkix_dist_points/1, @@ -741,6 +742,21 @@ ssh_encode(Entries, Type) when is_list(Entries), Type == known_hosts -> pubkey_ssh:encode(Entries, Type). +%%-------------------------------------------------------------------- +%% Description: Converts from the ssh name of elliptic curves to +%% the OIDs. +%%-------------------------------------------------------------------- +ssh_curvename2oid(<<"nistp256">>) -> ?'secp256r1'; +ssh_curvename2oid(<<"nistp384">>) -> ?'secp384r1'; +ssh_curvename2oid(<<"nistp521">>) -> ?'secp521r1'. + +%%-------------------------------------------------------------------- +%% Description: Converts from elliptic curve OIDs to the ssh name. +%%-------------------------------------------------------------------- +oid2ssh_curvename(?'secp256r1') -> <<"nistp256">>; +oid2ssh_curvename(?'secp384r1') -> <<"nistp384">>; +oid2ssh_curvename(?'secp521r1') -> <<"nistp521">>. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index da64e4abf9..fc9d60c500 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -37,13 +37,16 @@ -define(FALSE, 0). -define(TRUE, 1). %% basic binary constructors --define(BOOLEAN(X), X:8/unsigned-big-integer). --define(BYTE(X), X:8/unsigned-big-integer). --define(UINT16(X), X:16/unsigned-big-integer). --define(UINT32(X), X:32/unsigned-big-integer). --define(UINT64(X), X:64/unsigned-big-integer). +-define(BOOLEAN(X), (X):8/unsigned-big-integer). +-define(BYTE(X), (X):8/unsigned-big-integer). +-define(UINT16(X), (X):16/unsigned-big-integer). +-define(UINT32(X), (X):32/unsigned-big-integer). +-define(UINT64(X), (X):64/unsigned-big-integer). -define(STRING(X), ?UINT32((size(X))), (X)/binary). +-define(DEC_BIN(X,Len), ?UINT32(Len), X:Len/binary ). +-define(DEC_MPINT(I,Len), ?UINT32(Len), I:Len/big-signed-integer-unit:8 ). + %% building macros -define(boolean(X), case X of diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 0c16e19701..8c6ffceb4b 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -500,16 +500,15 @@ decode_public_key_v2(< {ok, {Y, #'Dss-Parms'{p = P, q = Q, g = G}}}; decode_public_key_v2(<> for example + ?UINT32(Len1), IdB:Len1/binary, %% Id = <<"nistp256">> for example ?UINT32(Len2), Blob:Len2/binary>>, - Curve) -> - Id = - case Curve of - "ecdsa-sha2-nistp256" -> <<"nistp256">>; - "ecdsa-sha2-nistp384" -> <<"nistp384">>; - "ecdsa-sha2-nistp521" -> <<"nistp521">> - end, - {ok, {#'ECPoint'{point=Blob}, Id}}; + "ecdsa-sha2-" ++ IdS) -> + case binary_to_list(IdB) of + IdS -> + {ok, {#'ECPoint'{point=Blob}, {namedCurve,public_key:ssh_curvename2oid(IdB)}} }; + _ -> + {error, bad_format} + end; decode_public_key_v2(_, _) -> {error, bad_format}. diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 7fb86c1108..09ef03f3f8 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1348,6 +1348,7 @@ event(Event, StateName, State) -> throw:{ErrorToDisplay, #ssh_msg_disconnect{} = DisconnectMsg} -> handle_disconnect(DisconnectMsg, State, ErrorToDisplay); _C:_Error -> +ct:pal("*** FAIL ~p:~p(~p,...~n -> ~p:~p ",[?MODULE,StateName,Event,_C,_Error]), handle_disconnect(#ssh_msg_disconnect{code = error_code(StateName), description = "Invalid state", language = "en"}, State) diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index 4e6d58cbff..c087ce14d7 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -276,12 +276,13 @@ key_match(#'RSAPublicKey'{}, 'ssh-rsa') -> true; key_match({_, #'Dss-Parms'{}}, 'ssh-dss') -> true; -key_match({#'ECPoint'{},<<"nistp256">>}, 'ecdsa-sha2-nistp256') -> - true; -key_match({#'ECPoint'{},<<"nistp384">>}, 'ecdsa-sha2-nistp384') -> - true; -key_match({#'ECPoint'{},<<"nistp521">>}, 'ecdsa-sha2-nistp521') -> - true; +key_match({#'ECPoint'{},{namedCurve,Curve}}, Alg) -> + case atom_to_list(Alg) of + "ecdsa-sha2-"++IdS -> + Curve == public_key:ssh_curvename2oid(list_to_binary(IdS)); + _ -> + false + end; key_match(_, _) -> false. diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index cfa11903fb..42e9b27b93 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -228,7 +228,7 @@ encode(#ssh_msg_kexdh_reply{ h_sig = Signature }) -> EncKey = encode_host_key(Key), - EncSign = encode_sign(Key, Signature), + EncSign = encode_signature(Key, Signature), ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); encode(#ssh_msg_kex_dh_gex_request{ @@ -256,7 +256,7 @@ encode(#ssh_msg_kex_dh_gex_reply{ h_sig = Signature }) -> EncKey = encode_host_key(Key), - EncSign = encode_sign(Key, Signature), + EncSign = encode_signature(Key, Signature), ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) -> @@ -264,7 +264,7 @@ encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) -> encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) -> EncKey = encode_host_key(Key), - EncSign = encode_sign(Key, Sign), + EncSign = encode_signature(Key, Sign), ssh_bits:encode([?SSH_MSG_KEX_ECDH_REPLY, EncKey, Q_s, EncSign], [byte, binary, mpint, binary]); encode(#ssh_msg_ignore{data = Data}) -> @@ -280,8 +280,7 @@ encode(#ssh_msg_debug{always_display = Bool, %% Connection Messages -decode(<>) -> +decode(<>) -> #ssh_msg_global_request{ name = Name, want_reply = erl_boolean(Bool), @@ -292,8 +291,7 @@ decode(<>) -> decode(<>) -> #ssh_msg_request_failure{}; decode(<>) -> #ssh_msg_channel_open{ channel_type = binary_to_list(Type), @@ -313,7 +311,7 @@ decode(<>) -> + ?DEC_BIN(Desc,__0), ?DEC_BIN(Lang,__1) >> ) -> #ssh_msg_channel_open_failure{ recipient_channel = Recipient, reason = Reason, @@ -326,13 +324,13 @@ decode(<>) -> +decode(<>) -> #ssh_msg_channel_data{ recipient_channel = Recipient, data = Data }; decode(<>) -> + ?UINT32(DataType), ?DEC_BIN(Data,__0)>>) -> #ssh_msg_channel_extended_data{ recipient_channel = Recipient, data_type_code = DataType, @@ -347,8 +345,7 @@ decode(<>) -> recipient_channel = Recipient }; decode(<>) -> + ?DEC_BIN(RequestType,__0), ?BYTE(Bool), Data/binary>>) -> #ssh_msg_channel_request{ recipient_channel = Recipient, request_type = unicode:characters_to_list(RequestType), @@ -366,9 +363,7 @@ decode(<>) -> %%% Auth Messages decode(<>) -> #ssh_msg_userauth_request{ user = unicode:characters_to_list(User), @@ -378,7 +373,7 @@ decode(<>) -> #ssh_msg_userauth_failure { authentications = unicode:characters_to_list(Auths), @@ -388,16 +383,14 @@ decode(<>) -> #ssh_msg_userauth_success{}; -decode(<>) -> +decode(<>) -> #ssh_msg_userauth_banner{ message = Banner, language = Lang }; -decode(<>) -> #ssh_msg_userauth_info_request{ name = Name, @@ -407,15 +400,14 @@ decode(<>) -> +decode(<>) -> #ssh_msg_userauth_passwd_changereq{ prompt = Prompt, languge = Lang }; %%% Unhandled message, also masked by same 1:st byte value as ?SSH_MSG_USERAUTH_INFO_REQUEST: -decode(<>) -> +decode(<>) -> #ssh_msg_userauth_pk_ok{ algorithm_name = Alg, key_blob = KeyBlob @@ -430,18 +422,15 @@ decode(<>) -> decode(<>) -> decode_kex_init(Data, [Cookie, ssh_msg_kexinit], 10); -decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?UINT32(Len), E:Len/big-signed-integer-unit:8>>) -> +decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?DEC_MPINT(E,__0)>>) -> #ssh_msg_kexdh_init{e = E }; -decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY), - ?UINT32(Len0), Key:Len0/binary, - ?UINT32(Len1), F:Len1/big-signed-integer-unit:8, - ?UINT32(Len2), Hashsign:Len2/binary>>) -> +decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1), ?DEC_BIN(Hashsign,__2)>>) -> #ssh_msg_kexdh_reply{ public_host_key = decode_host_key(Key), f = F, - h_sig = decode_sign(Hashsign) + h_sig = decode_signature(Hashsign) }; decode(<>) -> @@ -456,57 +445,48 @@ decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_REQUEST_OLD), ?UINT32(N)>>) -> n = N }; -decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP), - ?UINT32(Len0), Prime:Len0/big-signed-integer-unit:8, - ?UINT32(Len1), Generator:Len1/big-signed-integer-unit:8>>) -> +decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP), ?DEC_MPINT(Prime,__0), ?DEC_MPINT(Generator,__1) >>) -> #ssh_msg_kex_dh_gex_group{ p = Prime, g = Generator }; -decode(<>) -> +decode(<>) -> #ssh_msg_kex_dh_gex_init{ e = E }; -decode(<>) -> +decode(<>) -> #ssh_msg_kex_dh_gex_reply{ public_host_key = decode_host_key(Key), f = F, - h_sig = decode_sign(Hashsign) + h_sig = decode_signature(Hashsign) }; -decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), - ?UINT32(Len0), Q_c:Len0/big-signed-integer-unit:8>>) -> +decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_MPINT(Q_c,__0)>>) -> #ssh_msg_kex_ecdh_init{ q_c = Q_c }; decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY), - ?UINT32(Len1), Key:Len1/binary, - ?UINT32(Len2), Q_s:Len2/big-signed-integer-unit:8, - ?UINT32(Len3), Sig:Len3/binary>>) -> + ?DEC_BIN(Key,__1), ?DEC_MPINT(Q_s,__2), ?DEC_BIN(Sig,__3)>>) -> #ssh_msg_kex_ecdh_reply{ public_host_key = decode_host_key(Key), q_s = Q_s, - h_sig = decode_sign(Sig) + h_sig = decode_signature(Sig) }; -decode(<>) -> +decode(<>) -> #ssh_msg_service_request{ name = unicode:characters_to_list(Service) }; -decode(<>) -> +decode(<>) -> #ssh_msg_service_accept{ name = unicode:characters_to_list(Service) }; -decode(<>) -> +decode(<>) -> #ssh_msg_disconnect{ code = Code, description = unicode:characters_to_list(Desc), @@ -514,8 +494,7 @@ decode(<>) -> +decode(<>) -> #ssh_msg_disconnect{ code = Code, description = unicode:characters_to_list(Desc), @@ -525,21 +504,25 @@ decode(<>) -> #ssh_msg_newkeys{}; -decode(<>) -> +decode(<>) -> #ssh_msg_ignore{data = Data}; decode(<>) -> #ssh_msg_unimplemented{sequence = Seq}; -decode(<>) -> +decode(<>) -> #ssh_msg_debug{always_display = erl_boolean(Bool), message = Msg, language = Lang}. +%%%================================================================ +%%% +%%% Helper functions +%%% + decode_keyboard_interactive_prompts(<<>>, Acc) -> lists:reverse(Acc); -decode_keyboard_interactive_prompts(<>, +decode_keyboard_interactive_prompts(<>, Acc) -> decode_keyboard_interactive_prompts(Bin, [{Prompt, erl_boolean(Bool)} | Acc]). @@ -555,38 +538,34 @@ decode_kex_init(<>, Acc, 0) -> %% See rfc 4253 7.1 X = 0, list_to_tuple(lists:reverse([X, erl_boolean(Bool) | Acc])); -decode_kex_init(<>, Acc, N) -> +decode_kex_init(<>, Acc, N) -> Names = string:tokens(unicode:characters_to_list(Data), ","), decode_kex_init(Rest, [Names | Acc], N -1). +%%%================================================================ +%%% +%%% Host key decode/encode +%%% -decode_sign(<>) -> - Signature. - - -decode_host_key(<>) -> - decode_host_key(Alg, Rest). +decode_host_key(<>) -> decode_host_key(Alg, Rest). -decode_host_key(<<"ssh-rsa">>, <>) -> +decode_host_key(<<"ssh-rsa">>, <>) -> #'RSAPublicKey'{publicExponent = E, modulus = N}; - decode_host_key(<<"ssh-dss">>, - <>) -> + <>) -> {Y, #'Dss-Parms'{p = P, q = Q, g = G}}; - decode_host_key(<<"ecdsa-sha2-",Id/binary>>, - <> for example - ?UINT32(Len1), Blob:Len1/binary>>) -> - {#'ECPoint'{point=Blob}, Id}. + <> for example + ?DEC_BIN(Blob,__1)>>) -> + {#'ECPoint'{point=Blob}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. encode_host_key(#'RSAPublicKey'{modulus = N, publicExponent = E}) -> @@ -594,30 +573,25 @@ encode_host_key(#'RSAPublicKey'{modulus = N, publicExponent = E}) -> encode_host_key({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> ssh_bits:encode(["ssh-dss", P, Q, G, Y], [string, mpint, mpint, mpint, mpint]); -encode_host_key({#'ECPoint'{point = Q}, Id}) -> - ssh_bits:encode([<<"ecdsa-sha2-",Id/binary>>,Id,Q], [binary,binary,binary]); +encode_host_key({#'ECPoint'{point = Q}, {namedCurve,OID}}) -> + CurveName = public_key:oid2ssh_curvename(OID), + ssh_bits:encode([<<"ecdsa-sha2-",CurveName/binary>>,CurveName,Q], [binary,binary,binary]). -encode_host_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) -> - ssh_bits:encode(["ssh-rsa", E, N], [string, mpint, mpint]); -encode_host_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) -> - ssh_bits:encode(["ssh-dss", P, Q, G, Y], - [string, mpint, mpint, mpint, mpint]); -encode_host_key(#'ECPrivateKey'{parameters = Params, %{namedCurve,{1,2,840,10045,3,1,7}}, - publicKey = Pub}) -> - Id = ecdsa_id(Params), - ssh_bits:encode(["ecdsa-sha2-"++Id, Id, Pub], - [string, string, binary]). + +%%%================================================================ +%%% +%%% Signature decode/encode +%%% + +decode_signature(<>) -> + Signature. -encode_sign(#'RSAPrivateKey'{}, Signature) -> +encode_signature(#'RSAPublicKey'{}, Signature) -> ssh_bits:encode(["ssh-rsa", Signature],[string, binary]); -encode_sign(#'DSAPrivateKey'{}, Signature) -> +encode_signature({_, #'Dss-Parms'{}}, Signature) -> ssh_bits:encode(["ssh-dss", Signature],[string, binary]); -encode_sign(#'ECPrivateKey'{parameters = Params}, Signature) -> - Id = "ecdsa-sha2-" ++ ecdsa_id(Params), - ssh_bits:encode([Id, Signature],[string, binary]). - +encode_signature({#'ECPoint'{}, {namedCurve,OID}}, Signature) -> + CurveName = public_key:oid2ssh_curvename(OID), + ssh_bits:encode([<<"ecdsa-sha2-",CurveName/binary>>, Signature], [binary,binary]). -ecdsa_id({namedCurve,?'secp256r1'}) -> "nistp256"; -ecdsa_id({namedCurve,?'secp384r1'}) -> "nistp384"; -ecdsa_id({namedCurve,?'secp521r1'}) -> "nistp521". diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index a6438e69d4..080d6f74f7 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -380,13 +380,15 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, 1= {Public, Private} = generate_key(dh, [P,G]), K = compute_key(dh, E, Private, [P,G]), - Key = get_host_key(Ssh0), - H = kex_h(Ssh0, Key, E, Public, K), - H_SIG = sign_host_key(Ssh0, Key, H), - {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_reply{public_host_key = Key, - f = Public, - h_sig = H_SIG - }, Ssh0), + MyPrivHostKey = get_host_key(Ssh0), + MyPubHostKey = extract_public_key(MyPrivHostKey), + H = kex_h(Ssh0, MyPubHostKey, E, Public, K), + H_SIG = sign_host_key(Ssh0, MyPrivHostKey, H), + {SshPacket, Ssh1} = + ssh_packet(#ssh_msg_kexdh_reply{public_host_key = MyPubHostKey, + f = Public, + h_sig = H_SIG + }, Ssh0), {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}, shared_secret = K, exchanged_hash = H, @@ -401,7 +403,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, }) end. -handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, +handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = PeerPubHostKey, f = F, h_sig = H_SIG}, #ssh{keyex_key = {{Private, Public}, {G, P}}} = Ssh0) -> @@ -409,9 +411,9 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, if 1= K = compute_key(dh, F, Private, [P,G]), - H = kex_h(Ssh0, HostKey, Public, F, K), + H = kex_h(Ssh0, PeerPubHostKey, Public, F, K), - case verify_host_key(Ssh0, HostKey, H, H_SIG) of + case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -480,11 +482,12 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, K = compute_key(dh, E, Private, [P,G]), if 1 - HostKey = get_host_key(Ssh0), - H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, E, Public, K), - H_SIG = sign_host_key(Ssh0, HostKey, H), + MyPrivHostKey = get_host_key(Ssh0), + MyPubHostKey = extract_public_key(MyPrivHostKey), + H = kex_h(Ssh0, MyPubHostKey, Min, NBits, Max, P, G, E, Public, K), + H_SIG = sign_host_key(Ssh0, MyPrivHostKey, H), {SshPacket, Ssh} = - ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, + ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = MyPubHostKey, f = Public, h_sig = H_SIG}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -508,7 +511,7 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, }) end. -handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, +handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = PeerPubHostKey, f = F, h_sig = H_SIG}, #ssh{keyex_key = {{Private, Public}, {G, P}}, @@ -520,9 +523,9 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey, K = compute_key(dh, F, Private, [P,G]), if 1 - H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K), + H = kex_h(Ssh0, PeerPubHostKey, Min, NBits, Max, P, G, Public, F, K), - case verify_host_key(Ssh0, HostKey, H, H_SIG) of + case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -565,11 +568,12 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, true -> {MyPublic, MyPrivate} = generate_key(ecdh, Curve), K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), - HostKey = get_host_key(Ssh0), - H = kex_h(Ssh0, Curve, HostKey, PeerPublic, MyPublic, K), - H_SIG = sign_host_key(Ssh0, HostKey, H), + MyPrivHostKey = get_host_key(Ssh0), + MyPubHostKey = extract_public_key(MyPrivHostKey), + H = kex_h(Ssh0, Curve, MyPubHostKey, PeerPublic, MyPublic, K), + H_SIG = sign_host_key(Ssh0, MyPrivHostKey, H), {SshPacket, Ssh1} = - ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, + ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = MyPubHostKey, q_s = MyPublic, h_sig = H_SIG}, Ssh0), @@ -587,7 +591,7 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, }) end. -handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, +handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, q_s = PeerPublic, h_sig = H_SIG}, #ssh{keyex_key = {{MyPublic,MyPrivate}, Curve}} = Ssh0 @@ -596,8 +600,8 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = HostKey, case ecdh_validate_public_key(PeerPublic, Curve) of true -> K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), - H = kex_h(Ssh0, Curve, HostKey, MyPublic, PeerPublic, K), - case verify_host_key(Ssh0, HostKey, H, H_SIG) of + H = kex_h(Ssh0, Curve, PeerPubHostKey, MyPublic, PeerPublic, K), + case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0), {ok, SshPacket, Ssh#ssh{shared_secret = K, @@ -659,13 +663,20 @@ get_host_key(SSH) -> sign_host_key(_Ssh, PrivateKey, H) -> sign(H, sign_host_key_sha(PrivateKey), PrivateKey). -sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve, ?'secp256r1'}}) -> sha256; -sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve, ?'secp384r1'}}) -> sha384; -sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve, ?'secp521r1'}}) -> sha512; +sign_host_key_sha(#'ECPrivateKey'{parameters = {namedCurve,OID}}) -> sha(OID); sign_host_key_sha(#'RSAPrivateKey'{}) -> sha; sign_host_key_sha(#'DSAPrivateKey'{}) -> sha. +extract_public_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) -> + #'RSAPublicKey'{modulus = N, publicExponent = E}; +extract_public_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) -> + {Y, #'Dss-Parms'{p=P, q=Q, g=G}}; +extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID}, + publicKey = Q}) -> + {#'ECPoint'{point=Q}, {namedCurve,OID}}. + + verify_host_key(SSH, PublicKey, Digest, Signature) -> case verify(Digest, host_key_sha(PublicKey), Signature, PublicKey) of false -> @@ -674,14 +685,16 @@ verify_host_key(SSH, PublicKey, Digest, Signature) -> known_host_key(SSH, PublicKey, public_algo(PublicKey)) end. -host_key_sha(#'RSAPublicKey'{}) -> sha; -host_key_sha({_, #'Dss-Parms'{}}) -> sha; -host_key_sha({#'ECPoint'{},Id}) -> sha(list_to_atom(binary_to_list(Id))). +host_key_sha(#'RSAPublicKey'{}) -> sha; +host_key_sha({_, #'Dss-Parms'{}}) -> sha; +host_key_sha({#'ECPoint'{},{namedCurve,OID}}) -> sha(OID). public_algo(#'RSAPublicKey'{}) -> 'ssh-rsa'; public_algo({_, #'Dss-Parms'{}}) -> 'ssh-dss'; -public_algo({#'ECPoint'{},Id}) -> list_to_atom("ecdsa-sha2-" ++ binary_to_list(Id)). +public_algo({#'ECPoint'{},{namedCurve,OID}}) -> + Curve = public_key:oid2ssh_curvename(OID), + list_to_atom("ecdsa-sha2-" ++ binary_to_list(Curve)). accepted_host(Ssh, PeerName, Opts) -> @@ -933,17 +946,12 @@ verify(PlainText, Hash, Sig, {_, #'Dss-Parms'{}} = Key) -> <> = Sig, Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}), public_key:verify(PlainText, Hash, Signature, Key); -verify(PlainText, Hash, Sig, {ECPoint=#'ECPoint'{}, Param}) -> - C = case Param of - <<"nistp256">> -> {namedCurve, ?'secp256r1'}; - <<"nistp384">> -> {namedCurve, ?'secp384r1'}; - <<"nistp521">> -> {namedCurve, ?'secp521r1'} - end, +verify(PlainText, Hash, Sig, {#'ECPoint'{},_} = Key) -> <> = Sig, Sval = #'ECDSA-Sig-Value'{r=R, s=S}, DerEncodedSig = public_key:der_encode('ECDSA-Sig-Value',Sval), - public_key:verify(PlainText, Hash, DerEncodedSig, {ECPoint,C}); + public_key:verify(PlainText, Hash, DerEncodedSig, Key); verify(PlainText, Hash, Sig, Key) -> public_key:verify(PlainText, Hash, Sig, Key). @@ -1372,16 +1380,18 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> end, crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). -sha('nistp256') -> sha256; -sha('secp256r1')-> sha256; -sha('nistp384') -> sha384; -sha('secp384r1')-> sha384; -sha('nistp521') -> sha512; -sha('secp521r1')-> sha512; + +sha(secp256r1) -> sha256; +sha(secp384r1) -> sha384; +sha(secp521r1) -> sha512; sha('diffie-hellman-group1-sha1') -> sha; sha('diffie-hellman-group14-sha1') -> sha; sha('diffie-hellman-group-exchange-sha1') -> sha; -sha('diffie-hellman-group-exchange-sha256') -> sha256. +sha('diffie-hellman-group-exchange-sha256') -> sha256; +sha(?'secp256r1') -> sha(secp256r1); +sha(?'secp384r1') -> sha(secp384r1); +sha(?'secp521r1') -> sha(secp521r1). + mac_key_size('hmac-sha1') -> 20*8; mac_key_size('hmac-sha1-96') -> 20*8; diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 87eaeec1bc..a269192785 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -403,18 +403,13 @@ setup_rsa_auth_keys(Dir, UserDir) -> PKey = #'RSAPublicKey'{publicExponent = E, modulus = N}, setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir). -setup_ecdsa_auth_keys(Size, Dir, UserDir) -> +setup_ecdsa_auth_keys(_Size, Dir, UserDir) -> {ok, Pem} = file:read_file(filename:join(Dir, "id_ecdsa")), ECDSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))), #'ECPrivateKey'{publicKey = Q, - parameters = {namedCurve,Id0}} = ECDSA, + parameters = Param = {namedCurve,_Id0}} = ECDSA, PKey = #'ECPoint'{point = Q}, - Id = case pubkey_cert_records:namedCurves(Id0) of - secp256r1 when Size=="256" -> <<"nistp256">>; - secp384r1 when Size=="384" -> <<"nistp384">>; - secp521r1 when Size=="521" -> <<"nistp521">> - end, - setup_auth_keys([{ {PKey,Id}, [{comment, "Test"}]}], UserDir). + setup_auth_keys([{ {PKey,Param}, [{comment, "Test"}]}], UserDir). setup_auth_keys(Keys, Dir) -> AuthKeys = public_key:ssh_encode(Keys, auth_keys), diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index caf9bac3b6..772e50df87 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -743,7 +743,7 @@ print_traces(S) -> [case Len-length(Acc)-1 of 0 -> io_lib:format(Fmt,Args); - N -> + _N -> io_lib:format(lists:concat(['~p --------~n',Fmt]), [Len-length(Acc)-1|Args]) end | Acc] -- cgit v1.2.3 From 19eec0552c6b4e5024e307d2376c061665007e4f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 14 Oct 2015 17:47:13 +0200 Subject: ssh, public_key: use pubkey encode/decode in app public_key --- lib/public_key/src/pubkey_ssh.erl | 71 ++++++++++++++++++++-------------- lib/public_key/src/public_key.erl | 6 ++- lib/ssh/src/ssh_auth.erl | 68 ++++++++------------------------ lib/ssh/src/ssh_connection_handler.erl | 1 - lib/ssh/src/ssh_message.erl | 49 ++++------------------- lib/ssh/src/ssh_transport.erl | 13 +++++-- 6 files changed, 78 insertions(+), 130 deletions(-) (limited to 'lib') diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl index 3addbfe3c6..ba67abb4eb 100644 --- a/lib/public_key/src/pubkey_ssh.erl +++ b/lib/public_key/src/pubkey_ssh.erl @@ -54,6 +54,8 @@ decode(Bin, public_key)-> end; decode(Bin, rfc4716_public_key) -> rfc4716_decode(Bin); +decode(Bin, ssh2_pubkey) -> + ssh2_pubkey_decode(Bin); decode(Bin, Type) -> openssh_decode(Bin, Type). @@ -63,6 +65,8 @@ decode(Bin, Type) -> %% %% Description: Encodes a list of ssh file entries. %%-------------------------------------------------------------------- +encode(Bin, ssh2_pubkey) -> + ssh2_pubkey_encode(Bin); encode(Entries, Type) -> iolist_to_binary(lists:map(fun({Key, Attributes}) -> do_encode(Type, Key, Attributes) @@ -221,36 +225,13 @@ decode_comment(Comment) -> [{comment, string_decode(iolist_to_binary(Comment))}]. -openssh_pubkey_decode(<<"ssh-rsa">>, Base64Enc) -> - <> - = base64:mime_decode(Base64Enc), - #'RSAPublicKey'{modulus = erlint(SizeN, N), - publicExponent = erlint(SizeE, E)}; - -openssh_pubkey_decode(<<"ssh-dss">>, Base64Enc) -> - <> - = base64:mime_decode(Base64Enc), - {erlint(SizeY, Y), - #'Dss-Parms'{p = erlint(SizeP, P), - q = erlint(SizeQ, Q), - g = erlint(SizeG, G)}}; - -openssh_pubkey_decode(<<"ecdsa-sha2-", Id/binary>>, Base64Enc) -> - %% rfc5656#section-3.1 - <> - = base64:mime_decode(Base64Enc), - {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}; - -openssh_pubkey_decode(KeyType, Base64Enc) -> - {KeyType, base64:mime_decode(Base64Enc)}. +openssh_pubkey_decode(Type, Base64Enc) -> + try + ssh2_pubkey_decode(Type, base64:mime_decode(Base64Enc)) + catch + _:_ -> + {Type, base64:mime_decode(Base64Enc)} + end. erlint(MPIntSize, MPIntValue) -> @@ -416,6 +397,36 @@ ssh2_pubkey_encode(Key={#'ECPoint'{point = Q}, {namedCurve,OID}}) -> (string(IdB))/binary, (string(Q))/binary>>. + +ssh2_pubkey_decode(Bin = <>) -> + ssh2_pubkey_decode(Type, Bin). + +ssh2_pubkey_decode(<<"ssh-rsa">>, + <>) -> + #'RSAPublicKey'{modulus = erlint(SizeN, N), + publicExponent = erlint(SizeE, E)}; + +ssh2_pubkey_decode(<<"ssh-dss">>, + <>) -> + {erlint(SizeY, Y), + #'Dss-Parms'{p = erlint(SizeP, P), + q = erlint(SizeQ, Q), + g = erlint(SizeG, G)}}; +ssh2_pubkey_decode(<<"ecdsa-sha2-",Id/binary>>, + <>) -> + <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc, + {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. + + + is_key_field(<<"ssh-dss">>) -> true; is_key_field(<<"ssh-rsa">>) -> true; is_key_field(<<"ecdsa-sha2-",Id/binary>>) -> is_ssh_curvename(Id); diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 2b04b3f79b..941ade3dd7 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -725,7 +725,8 @@ ssh_decode(SshBin, Type) when is_binary(SshBin), Type == rfc4716_public_key; Type == openssh_public_key; Type == auth_keys; - Type == known_hosts -> + Type == known_hosts; + Type == ssh2_pubkey -> pubkey_ssh:decode(SshBin, Type). %%-------------------------------------------------------------------- @@ -739,7 +740,8 @@ ssh_encode(Entries, Type) when is_list(Entries), Type == rfc4716_public_key; Type == openssh_public_key; Type == auth_keys; - Type == known_hosts -> + Type == known_hosts; + Type == ssh2_pubkey -> pubkey_ssh:encode(Entries, Type). %%-------------------------------------------------------------------- diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 8c6ffceb4b..04749fcf8e 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -44,15 +44,15 @@ publickey_msg([Alg, #ssh{user = User, Hash = sha, %% Maybe option?! KeyCb = proplists:get_value(key_cb, Opts, ssh_file), case KeyCb:user_key(Alg, Opts) of - {ok, Key} -> - StrAlgo = algorithm_string(Alg), - case encode_public_key(StrAlgo, Key) of + {ok, PrivKey} -> + StrAlgo = atom_to_list(Alg), + case encode_public_key(StrAlgo, ssh_transport:extract_public_key(PrivKey)) of not_ok -> not_ok; PubKeyBlob -> SigData = build_sig_data(SessionId, User, Service, PubKeyBlob, StrAlgo), - Sig = ssh_transport:sign(SigData, Hash, Key), + Sig = ssh_transport:sign(SigData, Hash, PrivKey), SigBlob = list_to_binary([?string(StrAlgo), ?binary(Sig)]), ssh_transport:ssh_packet( #ssh_msg_userauth_request{user = User, @@ -430,12 +430,6 @@ build_sig_data(SessionId, User, Service, KeyBlob, Alg) -> ?binary(KeyBlob)], list_to_binary(Sig). -algorithm_string('ssh-rsa') -> "ssh-rsa"; -algorithm_string('ssh-dss') -> "ssh-dss"; -algorithm_string('ecdsa-sha2-nistp256') -> "ecdsa-sha2-nistp256"; -algorithm_string('ecdsa-sha2-nistp384') -> "ecdsa-sha2-nistp384"; -algorithm_string('ecdsa-sha2-nistp521') -> "ecdsa-sha2-nistp521". - decode_keyboard_interactive_prompts(_NumPrompts, Data) -> @@ -487,46 +481,18 @@ keyboard_interact_fun(KbdInteractFun, Name, Instr, PromptInfos, NumPrompts) -> language = "en"}}) end. -decode_public_key_v2(<> - ,"ssh-rsa") -> - {ok, #'RSAPublicKey'{publicExponent = E, modulus = N}}; -decode_public_key_v2(<> - , "ssh-dss") -> - {ok, {Y, #'Dss-Parms'{p = P, q = Q, g = G}}}; -decode_public_key_v2(<> for example - ?UINT32(Len2), Blob:Len2/binary>>, - "ecdsa-sha2-" ++ IdS) -> - case binary_to_list(IdB) of - IdS -> - {ok, {#'ECPoint'{point=Blob}, {namedCurve,public_key:ssh_curvename2oid(IdB)}} }; - _ -> - {error, bad_format} - end; -decode_public_key_v2(_, _) -> - {error, bad_format}. - -encode_public_key("ssh-rsa", #'RSAPrivateKey'{publicExponent = E, modulus = N}) -> - ssh_bits:encode(["ssh-rsa",E,N], [string,mpint,mpint]); -encode_public_key("ssh-dss", #'DSAPrivateKey'{p = P, q = Q, g = G, y = Y}) -> - ssh_bits:encode(["ssh-dss",P,Q,G,Y], [string,mpint,mpint,mpint,mpint]); -encode_public_key("ecdsa-sha2-"++Curve, #'ECPrivateKey'{parameters = Params, - publicKey = Pub}) -> - Id = ecdsa_id(Params), - if - Id =/= Curve -> - not_ok; - true -> - ssh_bits:encode(["ecdsa-sha2-"++Id, Id, Pub], - [string, string, binary]) +decode_public_key_v2(Bin, _Type) -> + try + public_key:ssh_decode(Bin, ssh2_pubkey) + of + Key -> {ok, Key} + catch + _:_ -> {error, bad_format} end. -ecdsa_id({namedCurve,?'secp256r1'}) -> "nistp256"; -ecdsa_id({namedCurve,?'secp384r1'}) -> "nistp384"; -ecdsa_id({namedCurve,?'secp521r1'}) -> "nistp521". +encode_public_key(_Alg, Key) -> + try + public_key:ssh_encode(Key, ssh2_pubkey) + catch + _:_ -> not_ok + end. diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 09ef03f3f8..7fb86c1108 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1348,7 +1348,6 @@ event(Event, StateName, State) -> throw:{ErrorToDisplay, #ssh_msg_disconnect{} = DisconnectMsg} -> handle_disconnect(DisconnectMsg, State, ErrorToDisplay); _C:_Error -> -ct:pal("*** FAIL ~p:~p(~p,...~n -> ~p:~p ",[?MODULE,StateName,Event,_C,_Error]), handle_disconnect(#ssh_msg_disconnect{code = error_code(StateName), description = "Invalid state", language = "en"}, State) diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index 42e9b27b93..b6c4496be2 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -30,7 +30,7 @@ -include("ssh_auth.hrl"). -include("ssh_transport.hrl"). --export([encode/1, decode/1, encode_host_key/1, decode_keyboard_interactive_prompts/2]). +-export([encode/1, decode/1, decode_keyboard_interactive_prompts/2]). encode(#ssh_msg_global_request{ name = Name, @@ -227,7 +227,7 @@ encode(#ssh_msg_kexdh_reply{ f = F, h_sig = Signature }) -> - EncKey = encode_host_key(Key), + EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Signature), ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); @@ -255,7 +255,7 @@ encode(#ssh_msg_kex_dh_gex_reply{ f = F, h_sig = Signature }) -> - EncKey = encode_host_key(Key), + EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Signature), ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); @@ -263,7 +263,7 @@ encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) -> ssh_bits:encode([?SSH_MSG_KEX_ECDH_INIT, Q_c], [byte, mpint]); encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) -> - EncKey = encode_host_key(Key), + EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Sign), ssh_bits:encode([?SSH_MSG_KEX_ECDH_REPLY, EncKey, Q_s, EncSign], [byte, binary, mpint, binary]); @@ -428,7 +428,7 @@ decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?DEC_MPINT(E,__0)>>) -> decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1), ?DEC_BIN(Hashsign,__2)>>) -> #ssh_msg_kexdh_reply{ - public_host_key = decode_host_key(Key), + public_host_key = public_key:ssh_decode(Key, ssh2_pubkey), f = F, h_sig = decode_signature(Hashsign) }; @@ -458,7 +458,7 @@ decode(<>) -> decode(<>) -> #ssh_msg_kex_dh_gex_reply{ - public_host_key = decode_host_key(Key), + public_host_key = public_key:ssh_decode(Key, ssh2_pubkey), f = F, h_sig = decode_signature(Hashsign) }; @@ -471,7 +471,7 @@ decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_MPINT(Q_c,__0)>>) -> decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY), ?DEC_BIN(Key,__1), ?DEC_MPINT(Q_s,__2), ?DEC_BIN(Sig,__3)>>) -> #ssh_msg_kex_ecdh_reply{ - public_host_key = decode_host_key(Key), + public_host_key = public_key:ssh_decode(Key, ssh2_pubkey), q_s = Q_s, h_sig = decode_signature(Sig) }; @@ -543,41 +543,6 @@ decode_kex_init(<>, Acc, N) -> decode_kex_init(Rest, [Names | Acc], N -1). -%%%================================================================ -%%% -%%% Host key decode/encode -%%% - -decode_host_key(<>) -> decode_host_key(Alg, Rest). - - -decode_host_key(<<"ssh-rsa">>, <>) -> - #'RSAPublicKey'{publicExponent = E, - modulus = N}; -decode_host_key(<<"ssh-dss">>, - <>) -> - {Y, #'Dss-Parms'{p = P, - q = Q, - g = G}}; -decode_host_key(<<"ecdsa-sha2-",Id/binary>>, - <> for example - ?DEC_BIN(Blob,__1)>>) -> - {#'ECPoint'{point=Blob}, {namedCurve,public_key:ssh_curvename2oid(Id)}}. - - -encode_host_key(#'RSAPublicKey'{modulus = N, publicExponent = E}) -> - ssh_bits:encode(["ssh-rsa", E, N], [string, mpint, mpint]); -encode_host_key({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) -> - ssh_bits:encode(["ssh-dss", P, Q, G, Y], - [string, mpint, mpint, mpint, mpint]); -encode_host_key({#'ECPoint'{point = Q}, {namedCurve,OID}}) -> - CurveName = public_key:oid2ssh_curvename(OID), - ssh_bits:encode([<<"ecdsa-sha2-",CurveName/binary>>,CurveName,Q], [binary,binary,binary]). - - %%%================================================================ %%% %%% Signature decode/encode diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 080d6f74f7..500db91df5 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -44,6 +44,7 @@ handle_kexdh_reply/2, handle_kex_ecdh_init/2, handle_kex_ecdh_reply/2, + extract_public_key/1, unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1, sign/3, verify/4]). @@ -1344,38 +1345,42 @@ hash(K, H, Ki, N, HASH) -> hash(K, H, <>, N-128, HASH). kex_h(SSH, Key, E, F, K) -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version, SSH#ssh.c_keyinit, SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), E,F,K], + KeyBin, E,F,K], [string,string,binary,binary,binary, mpint,mpint,mpint]), crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). %% crypto:hash(sha,L). kex_h(SSH, Curve, Key, Q_c, Q_s, K) -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version, SSH#ssh.c_keyinit, SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), Q_c, Q_s, K], + KeyBin, Q_c, Q_s, K], [string,string,binary,binary,binary, mpint,mpint,mpint]), crypto:hash(sha(Curve), L). kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> L = if Min==-1; Max==-1 -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), Ts = [string,string,binary,binary,binary, uint32, mpint,mpint,mpint,mpint,mpint], ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version, SSH#ssh.c_keyinit,SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), NBits, Prime, Gen, E,F,K], + KeyBin, NBits, Prime, Gen, E,F,K], Ts); true -> + KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), Ts = [string,string,binary,binary,binary, uint32,uint32,uint32, mpint,mpint,mpint,mpint,mpint], ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version, SSH#ssh.c_keyinit,SSH#ssh.s_keyinit, - ssh_message:encode_host_key(Key), Min, NBits, Max, + KeyBin, Min, NBits, Max, Prime, Gen, E,F,K], Ts) end, crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). -- cgit v1.2.3 From 255f36937752404038f32ca67f438f13ef8ce4fb Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 15 Oct 2015 10:25:19 +0200 Subject: public_key: add/update -spec for ssh functions --- lib/public_key/src/pubkey_ssh.erl | 8 ++++++-- lib/public_key/src/public_key.erl | 14 +++++++++++--- lib/ssh/src/ssh_transport.erl | 18 ++++++++---------- 3 files changed, 25 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl index ba67abb4eb..82042550a0 100644 --- a/lib/public_key/src/pubkey_ssh.erl +++ b/lib/public_key/src/pubkey_ssh.erl @@ -41,7 +41,9 @@ %%-------------------------------------------------------------------- -spec decode(binary(), public_key | public_key:ssh_file()) -> - [{public_key:public_key(), Attributes::list()}]. + [{public_key:public_key(), Attributes::list()}] + ; (binary(), ssh2_pubkey) -> public_key:public_key() + . %% %% Description: Decodes a ssh file-binary. %%-------------------------------------------------------------------- @@ -61,7 +63,9 @@ decode(Bin, Type) -> %%-------------------------------------------------------------------- -spec encode([{public_key:public_key(), Attributes::list()}], public_key:ssh_file()) -> - binary(). + binary() + ; (public_key:public_key(), ssh2_pubkey) -> binary() + . %% %% Description: Encodes a list of ssh file entries. %%-------------------------------------------------------------------- diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 941ade3dd7..8288f68f7f 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -712,7 +712,9 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) -> %%-------------------------------------------------------------------- --spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}]. +-spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}] + ; (binary(), ssh2_pubkey) -> public_key() + . %% %% Description: Decodes a ssh file-binary. In the case of know_hosts %% or auth_keys the binary may include one or more lines of the @@ -730,8 +732,10 @@ ssh_decode(SshBin, Type) when is_binary(SshBin), pubkey_ssh:decode(SshBin, Type). %%-------------------------------------------------------------------- --spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> - binary(). +-spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> binary() + ; (public_key(), ssh2_pubkey) -> binary() + . +%% %% Description: Encodes a list of ssh file entries (public keys and %% attributes) to a binary. Possible attributes depends on the file %% type. @@ -745,6 +749,8 @@ ssh_encode(Entries, Type) when is_list(Entries), pubkey_ssh:encode(Entries, Type). %%-------------------------------------------------------------------- +-spec ssh_curvename2oid(binary()) -> oid(). + %% Description: Converts from the ssh name of elliptic curves to %% the OIDs. %%-------------------------------------------------------------------- @@ -753,6 +759,8 @@ ssh_curvename2oid(<<"nistp384">>) -> ?'secp384r1'; ssh_curvename2oid(<<"nistp521">>) -> ?'secp521r1'. %%-------------------------------------------------------------------- +-spec oid2ssh_curvename(oid()) -> binary(). + %% Description: Converts from elliptic curve OIDs to the ssh name. %%-------------------------------------------------------------------- oid2ssh_curvename(?'secp256r1') -> <<"nistp256">>; diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 500db91df5..d8574877f2 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -66,8 +66,8 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()]. algo_classes() -> [kex, public_key, cipher, mac, compression]. -default_algorithms(kex) -> - supported_algorithms(kex, []); %% Just to have a call to supported_algorithms/2 +%% default_algorithms(kex) -> % Example of how to disable an algorithm +%% supported_algorithms(kex, ['ecdh-sha2-nistp521']); default_algorithms(Alg) -> supported_algorithms(Alg). @@ -118,11 +118,11 @@ supported_algorithms(compression) -> 'zlib' ]). -supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> - [{client2server,As1},{server2client,As2}] = supported_algorithms(Key), - [{client2server,As1--BL1},{server2client,As2--BL2}]; -supported_algorithms(Key, BlackList) -> - supported_algorithms(Key) -- BlackList. +%% Dialyzer complains when not called...supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> +%% Dialyzer complains when not called... [{client2server,As1},{server2client,As2}] = supported_algorithms(Key), +%% Dialyzer complains when not called... [{client2server,As1--BL1},{server2client,As2--BL2}]; +%% Dialyzer complains when not called...supported_algorithms(Key, BlackList) -> +%% Dialyzer complains when not called... supported_algorithms(Key) -- BlackList. select_crypto_supported(L) -> Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()], @@ -329,9 +329,7 @@ verify_algorithm(#alg{encrypt = undefined}) -> false; verify_algorithm(#alg{decrypt = undefined}) -> false; verify_algorithm(#alg{compress = undefined}) -> false; verify_algorithm(#alg{decompress = undefined}) -> false; - -verify_algorithm(#alg{kex = Kex}) -> lists:member(Kex, supported_algorithms(kex)); -verify_algorithm(_) -> false. +verify_algorithm(#alg{kex = Kex}) -> lists:member(Kex, supported_algorithms(kex)). %%%---------------------------------------------------------------- %%% -- cgit v1.2.3 From c2471ecc85c74b0489a1801bf5ea24b2cee19ca1 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 16 Oct 2015 14:13:03 +0200 Subject: ssh: dialyzer fix --- lib/ssh/src/ssh.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index b6ee29efbb..049018b21c 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -391,8 +391,9 @@ handle_option([{negotiation_timeout, _} = Opt|Rest], SocketOptions, SshOptions) handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{parallel_login, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); -handle_option([parallel_login|Rest], SocketOptions, SshOptions) -> - handle_option(Rest, SocketOptions, [handle_ssh_option({parallel_login,true}) | SshOptions]); +%% (Is handled by proplists:unfold above:) +%% handle_option([parallel_login|Rest], SocketOptions, SshOptions) -> +%% handle_option(Rest, SocketOptions, [handle_ssh_option({parallel_login,true}) | SshOptions]); handle_option([{minimal_remote_max_packet_size, _} = Opt|Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{id_string, _ID} = Opt|Rest], SocketOptions, SshOptions) -> -- cgit v1.2.3 From 22bb75c811f1922618d4840f5e927333aa231bca Mon Sep 17 00:00:00 2001 From: Luca Favatella Date: Mon, 21 Sep 2015 22:44:02 +0100 Subject: Delete remote types-related dead code in erl_types Code became dead in 854ee8b. --- lib/hipe/cerl/erl_types.erl | 105 ++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 78 deletions(-) (limited to 'lib') diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index cd2d2fe207..6ce407a1a7 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -140,7 +140,6 @@ t_is_port/1, t_is_port/2, t_is_maybe_improper_list/1, t_is_maybe_improper_list/2, t_is_reference/1, t_is_reference/2, - t_is_remote/1, t_is_string/1, t_is_subtype/2, t_is_tuple/1, t_is_tuple/2, @@ -180,7 +179,6 @@ %% t_maybe_improper_list/2, t_product/1, t_reference/0, - t_remote/3, t_string/0, t_struct_from_opaque/2, t_subst/2, @@ -208,7 +206,6 @@ type_is_defined/4, record_field_diffs_to_string/2, subst_all_vars_to_any/1, - subst_all_remote/2, lift_list_to_pos_empty/1, lift_list_to_pos_empty/2, is_opaque_type/2, is_erl_type/1, @@ -280,7 +277,6 @@ -define(number_tag, number). -define(opaque_tag, opaque). -define(product_tag, product). --define(remote_tag, remote). -define(tuple_set_tag, tuple_set). -define(tuple_tag, tuple). -define(union_tag, union). @@ -288,7 +284,7 @@ -type tag() :: ?atom_tag | ?binary_tag | ?function_tag | ?identifier_tag | ?list_tag | ?map_tag | ?matchstate_tag | ?nil_tag | ?number_tag - | ?opaque_tag | ?product_tag | ?remote_tag + | ?opaque_tag | ?product_tag | ?tuple_tag | ?tuple_set_tag | ?union_tag | ?var_tag. -define(float_qual, float). @@ -330,7 +326,6 @@ %% was updated to 2.7 due to this change. -record(opaque, {mod :: module(), name :: atom(), args = [] :: [erl_type()], struct :: erl_type()}). --record(remote, {mod:: module(), name :: atom(), args = [] :: [erl_type()]}). -define(atom(Set), #c{tag=?atom_tag, elements=Set}). -define(bitstr(Unit, Base), #c{tag=?binary_tag, elements=[Unit,Base]}). @@ -350,7 +345,6 @@ -define(map(Pairs), #c{tag=?map_tag, elements=Pairs}). -define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}). -define(product(Types), #c{tag=?product_tag, elements=Types}). --define(remote(RemTypes), #c{tag=?remote_tag, elements=RemTypes}). -define(tuple(Types, Arity, Qual), #c{tag=?tuple_tag, elements=Types, qualifier={Arity, Qual}}). -define(tuple_set(Tuples), #c{tag=?tuple_set_tag, elements=Tuples}). @@ -380,19 +374,18 @@ %% Unions %% --define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_,_]=List}). - --define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none,?none])). --define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none,?none])). --define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none,?none])). --define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none,?none])). --define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none,?none])). --define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none,?none])). --define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none,?none])). --define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none,?none])). --define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none,?none])). --define(remote_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T,?none])). --define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,?none,T])). +-define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_]=List}). + +-define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none])). +-define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none])). +-define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none])). +-define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none])). +-define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none])). +-define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none])). +-define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none])). +-define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none])). +-define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none])). +-define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T])). -define(integer_union(T), ?number_union(T)). -define(float_union(T), ?number_union(T)). -define(nil_union(T), ?list_union(T)). @@ -679,8 +672,8 @@ list_decorate(List, L, Opaques) -> union_decorate(U1, U2, Opaques) -> Union = union_decorate(U1, U2, Opaques, 0, []), - [A,B,F,I,L,N,T,M,_,_R,Map] = U1, - [_,_,_,_,_,_,_,_,Opaque,_,_] = U2, + [A,B,F,I,L,N,T,M,_,Map] = U1, + [_,_,_,_,_,_,_,_,Opaque,_] = U2, List = [A,B,F,I,L,N,T,M,Map], DecList = [Dec || E <- List, @@ -792,21 +785,6 @@ list_struct_from_opaque(Types, Opaques) -> [t_struct_from_opaque(Type, Opaques) || Type <- Types]. %%----------------------------------------------------------------------------- -%% Remote types: these types are used for preprocessing; -%% they should never reach the analysis stage. - --spec t_remote(atom(), atom(), [erl_type()]) -> erl_type(). - -t_remote(Mod, Name, Args) -> - ?remote(set_singleton(#remote{mod = Mod, name = Name, args = Args})). - --spec t_is_remote(erl_type()) -> boolean(). - -t_is_remote(Type) -> - do_opaque(Type, 'universe', fun is_remote/1). - -is_remote(?remote(_)) -> true; -is_remote(_) -> false. -type mod_records() :: dict:dict(module(), type_table()). @@ -2178,8 +2156,6 @@ t_sup(?opaque(Set1), ?opaque(Set2)) -> %% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none; %%t_sup(T1, T2=?opaque(_,_,_)) -> %% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none; -t_sup(?remote(Set1), ?remote(Set2)) -> - ?remote(set_union_no_limit(Set1, Set2)); t_sup(?matchstate(Pres1, Slots1), ?matchstate(Pres2, Slots2)) -> ?matchstate(t_sup(Pres1, Pres2), t_sup(Slots1, Slots2)); t_sup(?nil, ?nil) -> ?nil; @@ -2373,7 +2349,6 @@ force_union(T = ?list(_, _, _)) -> ?list_union(T); force_union(T = ?nil) -> ?list_union(T); force_union(T = ?number(_, _)) -> ?number_union(T); force_union(T = ?opaque(_)) -> ?opaque_union(T); -force_union(T = ?remote(_)) -> ?remote_union(T); force_union(T = ?map(_)) -> ?map_union(T); force_union(T = ?tuple(_, _, _)) -> ?tuple_union(T); force_union(T = ?tuple_set(_)) -> ?tuple_union(T); @@ -2880,8 +2855,8 @@ inf_tuples_in_sets2(_, [], Acc, _Opaques) -> lists:reverse(Acc). inf_union(U1, U2, Opaques) -> OpaqueFun = fun(Union1, Union2, InfFun) -> - [_,_,_,_,_,_,_,_,Opaque,_,_] = Union1, - [A,B,F,I,L,N,T,M,_,_R,Map] = Union2, + [_,_,_,_,_,_,_,_,Opaque,_] = Union1, + [A,B,F,I,L,N,T,M,_,Map] = Union2, List = [A,B,F,I,L,N,T,M,Map], inf_union_collect(List, Opaque, InfFun, [], []) end, @@ -3060,18 +3035,6 @@ t_subst_aux(?union(List), VarMap) -> ?union([t_subst_aux(E, VarMap) || E <- List]); t_subst_aux(T, _VarMap) -> T. - --spec subst_all_remote(erl_type(), erl_type()) -> erl_type(). - -subst_all_remote(Type0, Substitute) -> - Map = - fun(Type) -> - case t_is_remote(Type) of - true -> Substitute; - false -> Type - end - end, - t_map(Map, Type0). %%----------------------------------------------------------------------------- %% Unification @@ -3175,11 +3138,11 @@ unify_union1(?union(List), T1, T2) -> end. unify_union(List) -> - [A,B,F,I,L,N,T,M,O,R,Map] = List, + [A,B,F,I,L,N,T,M,O,Map] = List, if O =:= ?none -> no; true -> S = t_opaque_structure(O), - {yes, t_sup([A,B,F,I,L,N,T,M,S,R,Map])} + {yes, t_sup([A,B,F,I,L,N,T,M,S,Map])} end. -spec is_opaque_type(erl_type(), [erl_type()]) -> boolean(). @@ -3537,10 +3500,10 @@ t_subtract_lists([], [], Acc) -> -spec subtract_union([erl_type(),...], [erl_type(),...]) -> erl_type(). subtract_union(U1, U2) -> - [A1,B1,F1,I1,L1,N1,T1,M1,O1,R1,Map1] = U1, - [A2,B2,F2,I2,L2,N2,T2,M2,O2,R2,Map2] = U2, - List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,R1,Map1], - List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,R2,Map2], + [A1,B1,F1,I1,L1,N1,T1,M1,O1,Map1] = U1, + [A2,B2,F2,I2,L2,N2,T2,M2,O2,Map2] = U2, + List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,Map1], + List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,Map2], Sub1 = subtract_union(List1, List2, 0, []), O = if O1 =:= ?none -> O1; true -> t_subtract(O1, ?union(U2)) @@ -3656,7 +3619,7 @@ t_unopaque(?product(Types), Opaques) -> ?product([t_unopaque(T, Opaques) || T <- Types]); t_unopaque(?function(Domain, Range), Opaques) -> ?function(t_unopaque(Domain, Opaques), t_unopaque(Range, Opaques)); -t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) -> +t_unopaque(?union([A,B,F,I,L,N,T,M,O,Map]), Opaques) -> UL = t_unopaque(L, Opaques), UT = t_unopaque(T, Opaques), UF = t_unopaque(F, Opaques), @@ -3665,7 +3628,7 @@ t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) -> ?opaque(_) = O1 -> {O1, []}; Type -> {?none, [Type]} end, - t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,R,UMap])|UO]); + t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,UMap])|UO]); t_unopaque(T, _) -> T. @@ -3932,16 +3895,6 @@ t_to_string(?float, _RecDict) -> "float()"; t_to_string(?number(?any, ?unknown_qual), _RecDict) -> "number()"; t_to_string(?product(List), RecDict) -> "<" ++ comma_sequence(List, RecDict) ++ ">"; -t_to_string(?remote(Set), RecDict) -> - string:join([case Args =:= [] of - true -> flat_format("~w:~w()", [Mod, Name]); - false -> - ArgString = comma_sequence(Args, RecDict), - flat_format("~w:~w(~s)", [Mod, Name, ArgString]) - end - || #remote{mod = Mod, name = Name, args = Args} <- - set_to_list(Set)], - " | "); t_to_string(?map(Pairs), RecDict) -> "#{" ++ map_pairs_to_string(Pairs,RecDict) ++ "}"; t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()"; @@ -4825,13 +4778,13 @@ do_opaque(?opaque(_) = Type, Opaques, Pred) -> false -> Pred(Type) end; do_opaque(?union(List) = Type, Opaques, Pred) -> - [A,B,F,I,L,N,T,M,O,R,Map] = List, + [A,B,F,I,L,N,T,M,O,Map] = List, if O =:= ?none -> Pred(Type); true -> case Opaques =:= 'universe' orelse is_opaque_type(O, Opaques) of true -> S = t_opaque_structure(O), - do_opaque(t_sup([A,B,F,I,L,N,T,M,S,R,Map]), Opaques, Pred); + do_opaque(t_sup([A,B,F,I,L,N,T,M,S,Map]), Opaques, Pred); false -> Pred(Type) end end; @@ -4865,10 +4818,6 @@ set_union(S1, S2) -> _ -> ?any end. -set_union_no_limit(?any, _) -> ?any; -set_union_no_limit(_, ?any) -> ?any; -set_union_no_limit(S1, S2) -> ordsets:union(S1, S2). - %% The intersection and subtraction can return ?none. %% This should always be handled right away since ?none is not a valid set. %% However, ?any is considered a valid set. -- cgit v1.2.3 From 6af1014df69b4b2c019aead2435e537c20a39f15 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 15 Oct 2015 18:44:11 +0200 Subject: ssh: Implemented ssh_transport:ecdh_validate_public_key (partly) Defined in http://www.secg.org/sec1-v2.pdf '3.2.2 Validation of Elliptic Curve Public Keys' according to RFC 5656 ch 4. More to be done: check singularities, implement reading compressed points.... --- lib/ssh/src/ssh_transport.erl | 56 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index d8574877f2..8b65806dc6 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -625,7 +625,61 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, end. -ecdh_validate_public_key(_, _) -> true. % FIXME: Far too many false positives :) +%%%---------------------------------------------------------------- +%%% +%%% Standards for Efficient Cryptography Group, "Elliptic Curve Cryptography", SEC 1 +%%% Section 3.2.2.1 +%%% + +ecdh_validate_public_key(Key, Curve) -> + case key_size(Curve) of + undefined -> + false; + + Sz -> + case dec_key(Key, Sz) of + {ok,Q} -> + case crypto:ec_curve(Curve) of + {{prime_field,P}, {A, B, _Seed}, + _P0Bin, _OrderBin, _CoFactorBin} -> + on_curve(Q, bin2int(A), bin2int(B), bin2int(P)) + end; + + {error,compressed_not_implemented} -> % Be a bit generous... + true; + + _Error -> + false + end + end. + + +on_curve({X,Y}, A, B, P) when 0 =< X,X =< (P-1), + 0 =< Y,Y =< (P-1) -> + %% Section 3.2.2.1, point 2 + (Y*Y) rem P == (X*X*X + A*X + B) rem P; +on_curve(_, _, _, _) -> + false. + + +bin2int(B) -> + Sz = erlang:bit_size(B), + <> = B, + I. + +key_size(secp256r1) -> 256; +key_size(secp384r1) -> 384; +key_size(secp521r1) -> 528; % Round 521 up to closest 8-bits. +key_size(_) -> undefined. + + +dec_key(Key, NBits) -> + Size = 8 + 2*NBits, + case <> of + <<4:8, X:NBits, Y:NBits>> -> {ok,{X,Y}}; + <<4:8, _/binary>> -> {error,bad_format}; + _ -> {error,compressed_not_implemented} + end. %%%---------------------------------------------------------------- handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> -- cgit v1.2.3 From 16d2e402ca0a4f37f12175f866e1c6c2842303bb Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 16 Oct 2015 10:34:56 +0200 Subject: ssh: wait for subsystem exit in ssh_connection_SUITE:max_channels_option --- lib/ssh/test/ssh_connection_SUITE.erl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib') diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index f0fdf5c0cc..1b93cc9c32 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -700,6 +700,16 @@ max_channels_option(Config) when is_list(Config) -> %%%---- close the shell ok = ssh_connection:send(ConnectionRef, ChannelId0, "exit().\n", 5000), + %%%---- wait for the subsystem to terminate + receive + {ssh_cm,ConnectionRef,{closed,ChannelId0}} -> ok + after 5000 -> + ct:log("Timeout waiting for '{ssh_cm,~p,{closed,~p}}'~n" + "Message queue:~n~p", + [ConnectionRef,ChannelId0,erlang:process_info(self(),messages)]), + ct:fail("exit Timeout",[]) + end, + %%%---- exec #3 success = ssh_connection:exec(ConnectionRef, ChannelId5, "testing3.\n", infinity), receive -- cgit v1.2.3 From c7cb718a480ae03fedb842bc999d516aee7870b3 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 16 Oct 2015 15:44:33 +0200 Subject: ssh: running ssh_algorithms_SUITE tests in parallel --- lib/ssh/test/ssh_algorithms_SUITE.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index 9f388de2a7..2ab83d84e1 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -58,7 +58,7 @@ groups() -> ], AlgoTcSet = - [{Alg, [], specific_test_cases(Tag,Alg,SshcAlgos,SshdAlgos)} + [{Alg, [parallel], specific_test_cases(Tag,Alg,SshcAlgos,SshdAlgos)} || {Tag,Algs} <- ErlAlgos ++ DoubleAlgos, Alg <- Algs], @@ -110,7 +110,8 @@ init_per_group(Group, Config) -> Config; false -> %% An algorithm group - [[{name,Tag}]|_] = ?config(tc_group_path, Config), + Tag = proplists:get_value(name, + hd(?config(tc_group_path, Config))), Alg = Group, PA = case split(Alg) of -- cgit v1.2.3 From c0c2f6a204d83ee89cd179b0a6d5996e248539e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 19 Oct 2015 16:55:24 +0200 Subject: Use full list of bindings when matching on map keys Prior to this patch, the following code would not eval: X = key, (fun(#{X := value}) -> true end)(#{X => value}) That's because the key evaluation was using the new list of bindings introduced on every anonymous fun. Since keys only match on values defined prior to the pattern and do not introduce any new binding, we must use the full and original list of binding. --- lib/stdlib/src/erl_eval.erl | 2 +- lib/stdlib/test/erl_eval_SUITE.erl | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index ca3cc43b19..568eb1c852 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -1184,7 +1184,7 @@ match_tuple([], _, _, Bs, _BBs) -> match_map([{map_field_exact, _, K, V}|Fs], Map, Bs0, BBs) -> Vm = try - {value, Ke, _} = expr(K, Bs0), + {value, Ke, _} = expr(K, BBs), maps:get(Ke,Map) catch error:_ -> throw(nomatch) diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index b9c4ad0a46..50fc62a00e 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1483,6 +1483,16 @@ eep43(Config) when is_list(Config) -> " #{ K1 := 1, K2 := 2, K3 := 3, {2,2} := 4} = Map " "end.", #{ 1 => 1, <<42:301>> => 2, {3,<<42:301>>} => 3, {2,2} => 4}), + check(fun () -> + X = key, + (fun(#{X := value}) -> true end)(#{X => value}) + end, + "begin " + " X = key, " + " (fun(#{X := value}) -> true end)(#{X => value}) " + "end.", + true), + error_check("[camembert]#{}.", {badmap,[camembert]}), error_check("[camembert]#{nonexisting:=v}.", {badmap,[camembert]}), error_check("#{} = 1.", {badmatch,1}), -- cgit v1.2.3 From eea90ecdce24c15d39e77849d51729fcc06b74f8 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 19 Oct 2015 16:02:50 +0200 Subject: ssh: test suites probes ssh client Previously we called the ssh client with the -Q option to query about supported algorithms. Since old clients do not support this and at least one lies, we now set up a fake server at let the ssh client start negotiation instead. Much more robust hopefully. --- lib/ssh/test/ssh_test_lib.erl | 140 +++++++++++++++++++++------------- lib/ssh/test/ssh_to_openssh_SUITE.erl | 2 +- lib/ssh/test/ssh_trpt_test_lib.erl | 5 +- 3 files changed, 90 insertions(+), 57 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index a269192785..2e63ec086b 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -478,7 +478,63 @@ check_ssh_client_support2(P) -> -1 end. -default_algorithms(Host, Port) -> +%%%-------------------------------------------------------------------- +%%% Probe a server or a client about algorithm support + +default_algorithms(sshd) -> + default_algorithms(sshd, "localhost", 22); + +default_algorithms(sshc) -> + default_algorithms(sshc, []). + +default_algorithms(sshd, Host, Port) -> + try run_fake_ssh( + ssh_trpt_test_lib:exec( + [{connect,Host,Port, [{silently_accept_hosts, true}, + {user_interaction, false}]}])) + catch + _C:_E -> + ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), + [] + end. + +default_algorithms(sshc, DaemonOptions) -> + Parent = self(), + %% Start a process handling one connection on the server side: + Srvr = + spawn_link( + fun() -> + Parent ! + {result, self(), + try + {ok,InitialState} = ssh_trpt_test_lib:exec(listen), + Parent ! {hostport,self(),ssh_trpt_test_lib:server_host_port(InitialState)}, + run_fake_ssh( + ssh_trpt_test_lib:exec([{accept, DaemonOptions}], + InitialState)) + catch + _C:_E -> + ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), + [] + end} + end), + + receive + {hostport,Srvr,{_Host,Port}} -> + spawn(fun()-> os:cmd(lists:concat(["ssh -o \"StrictHostKeyChecking no\" -p ",Port," localhost"])) end) + after ?TIMEOUT -> + ct:fail("No server respons 1") + end, + + receive + {result,Srvr,L} -> + L + after ?TIMEOUT -> + ct:fail("No server respons 2") + end. + + +run_fake_ssh({ok,InitialState}) -> KexInitPattern = #ssh_msg_kexinit{ kex_algorithms = '$kex_algorithms', @@ -491,61 +547,35 @@ default_algorithms(Host, Port) -> compression_algorithms_server_to_client = '$compression_algorithms_server_to_client', _ = '_' }, + {ok,E} = ssh_trpt_test_lib:exec([{set_options,[silent]}, + {send, hello}, + receive_hello, + {send, ssh_msg_kexinit}, + {match, KexInitPattern, receive_msg}, + close_socket + ], + InitialState), + [Kex, PubKey, EncC2S, EncS2C, MacC2S, MacS2C, CompC2S, CompS2C] = + ssh_trpt_test_lib:instantiate(['$kex_algorithms', + '$server_host_key_algorithms', + '$encryption_algorithms_client_to_server', + '$encryption_algorithms_server_to_client', + '$mac_algorithms_client_to_server', + '$mac_algorithms_server_to_client', + '$compression_algorithms_client_to_server', + '$compression_algorithms_server_to_client' + ], E), + [{kex, to_atoms(Kex)}, + {public_key, to_atoms(PubKey)}, + {cipher, [{client2server, to_atoms(EncC2S)}, + {server2client, to_atoms(EncS2C)}]}, + {mac, [{client2server, to_atoms(MacC2S)}, + {server2client, to_atoms(MacS2C)}]}, + {compression, [{client2server, to_atoms(CompC2S)}, + {server2client, to_atoms(CompS2C)}]}]. + - try ssh_trpt_test_lib:exec( - [{connect,Host,Port, [{silently_accept_hosts, true}, - {user_interaction, false}]}, - {send,hello}, - receive_hello, - {send, ssh_msg_kexinit}, - {match, KexInitPattern, receive_msg}, - close_socket]) - of - {ok,E} -> - [Kex, PubKey, EncC2S, EncS2C, MacC2S, MacS2C, CompC2S, CompS2C] = - ssh_trpt_test_lib:instantiate(['$kex_algorithms', - '$server_host_key_algorithms', - '$encryption_algorithms_client_to_server', - '$encryption_algorithms_server_to_client', - '$mac_algorithms_client_to_server', - '$mac_algorithms_server_to_client', - '$compression_algorithms_client_to_server', - '$compression_algorithms_server_to_client' - ], E), - [{kex, to_atoms(Kex)}, - {public_key, to_atoms(PubKey)}, - {cipher, [{client2server, to_atoms(EncC2S)}, - {server2client, to_atoms(EncS2C)}]}, - {mac, [{client2server, to_atoms(MacC2S)}, - {server2client, to_atoms(MacS2C)}]}, - {compression, [{client2server, to_atoms(CompC2S)}, - {server2client, to_atoms(CompS2C)}]}]; - _ -> - [] - catch - _:_ -> - [] - end. - - -default_algorithms(sshd) -> - default_algorithms("localhost", 22); -default_algorithms(sshc) -> - case os:find_executable("ssh") of - false -> - []; - _ -> - Cipher = sshc(cipher), - Mac = sshc(mac), - [{kex, sshc(kex)}, - {public_key, sshc(key)}, - {cipher, [{client2server, Cipher}, - {server2client, Cipher}]}, - {mac, [{client2server, Mac}, - {server2client, Mac}]} - ] - end. - +%%-------------------------------------------------------------------- sshc(Tag) -> to_atoms( string:tokens(os:cmd(lists:concat(["ssh -Q ",Tag])), "\n") diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 026fe545c1..ddc097a7eb 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -88,7 +88,7 @@ init_per_group(erlang_server, Config) -> init_per_group(erlang_client, Config) -> CommonAlgs = ssh_test_lib:algo_intersection( ssh:default_algorithms(), - ssh_test_lib:default_algorithms("localhost", 22)), + ssh_test_lib:default_algorithms(sshd)), [{common_algs,CommonAlgs} | Config]; init_per_group(_, Config) -> Config. diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 772e50df87..5080b33249 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -73,7 +73,10 @@ exec(Op, S0=#s{}) -> op(Op, S1)) of S = #s{} -> - print_traces(S), + case proplists:get_value(silent,S#s.opts) of + true -> ok; + _ -> print_traces(S) + end, {ok,S} catch {fail,Reason,Se} -> -- cgit v1.2.3 From e595ac154fdc8a6c6958744f5f6019105b637eaf Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 19 Oct 2015 16:52:53 +0200 Subject: ssh: Removed testcases from ssh_to_openssh_SUITE They are covered in ssh_algorithms_SUITE --- lib/ssh/test/ssh_to_openssh_SUITE.erl | 221 +--------------------------------- 1 file changed, 1 insertion(+), 220 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index ddc097a7eb..b5b997cb53 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -45,7 +45,6 @@ all() -> groups() -> [{erlang_client, [], [erlang_shell_client_openssh_server, - erlang_client_openssh_server_exec, erlang_client_openssh_server_exec_compressed, erlang_client_openssh_server_setenv, erlang_client_openssh_server_publickey_rsa, @@ -54,12 +53,7 @@ groups() -> erlang_client_openssh_server_kexs, erlang_client_openssh_server_nonexistent_subsystem ]}, - {erlang_server, [], [erlang_server_openssh_client_exec, - erlang_server_openssh_client_exec_compressed, - erlang_server_openssh_client_pulic_key_dsa, - erlang_server_openssh_client_cipher_suites, - erlang_server_openssh_client_macs, - erlang_server_openssh_client_kexs]} + {erlang_server, [], [erlang_server_openssh_client_pulic_key_dsa]} ]. init_per_suite(Config) -> @@ -100,18 +94,6 @@ end_per_group(erlang_server, Config) -> end_per_group(_, Config) -> Config. -init_per_testcase(erlang_server_openssh_client_cipher_suites, Config) -> - check_ssh_client_support(Config); - -init_per_testcase(erlang_server_openssh_client_macs, Config) -> - check_ssh_client_support(Config); - -init_per_testcase(erlang_server_openssh_client_kexs, Config) -> - check_ssh_client_support(Config); - -init_per_testcase(erlang_client_openssh_server_kexs, Config) -> - check_ssh_client_support(Config); - init_per_testcase(_TestCase, Config) -> ssh:start(), Config. @@ -257,207 +239,6 @@ erlang_client_openssh_server_kexs(Config) when is_list(Config) -> end end. -%%-------------------------------------------------------------------- -erlang_server_openssh_client_exec() -> - [{doc, "Test that exec command works."}]. - -erlang_server_openssh_client_exec(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - - - ct:sleep(500), - - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.", - - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive answer") - - end, - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_cipher_suites() -> - [{doc, "Test that we can connect with different cipher suites."}]. - -erlang_server_openssh_client_cipher_suites(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - - ct:sleep(500), - - OpenSshCiphers = - ssh_test_lib:to_atoms( - string:tokens(os:cmd("ssh -Q cipher"), "\n")), - ErlCiphers = - proplists:get_value(client2server, - proplists:get_value(cipher, ssh:default_algorithms())), - CommonCiphers = - ssh_test_lib:algo_intersection(ErlCiphers, OpenSshCiphers), - - comment(CommonCiphers), - - lists:foreach( - fun(Cipher) -> - Cmd = lists:concat(["ssh -p ",Port, - " -o UserKnownHostsFile=",KnownHosts," ",Host," ", - " -c ",Cipher," 1+1."]), - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("~p Did not receive answer",[Cipher]) - end - end, CommonCiphers), - - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_macs() -> - [{doc, "Test that we can connect with different MACs."}]. - -erlang_server_openssh_client_macs(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}]), - - - ct:sleep(500), - - OpenSshMacs = - ssh_test_lib:to_atoms( - string:tokens(os:cmd("ssh -Q mac"), "\n")), - ErlMacs = - proplists:get_value(client2server, - proplists:get_value(mac, ssh:default_algorithms())), - CommonMacs = - ssh_test_lib:algo_intersection(ErlMacs, OpenSshMacs), - - comment(CommonMacs), - - lists:foreach( - fun(MAC) -> - Cmd = lists:concat(["ssh -p ",Port, - " -o UserKnownHostsFile=",KnownHosts," ",Host," ", - " -o MACs=",MAC," 1+1."]), - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("~p Did not receive answer",[MAC]) - end - end, CommonMacs), - - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_kexs() -> - [{doc, "Test that we can connect with different KEXs."}]. - -erlang_server_openssh_client_kexs(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {failfun, fun ssh_test_lib:failfun/2}, - {preferred_algorithms, - [{kex,ssh_transport:default_algorithms(kex)}]} - ]), - ct:sleep(500), - - OpenSshKexs = - ssh_test_lib:to_atoms( - string:tokens(os:cmd("ssh -Q kex"), "\n")), - ErlKexs = - proplists:get_value(kex, ssh:default_algorithms()), - CommonKexs = - ssh_test_lib:algo_intersection(ErlKexs, OpenSshKexs), - - comment(CommonKexs), - - lists:foreach( - fun(Kex) -> - Cmd = lists:concat(["ssh -p ",Port, - " -o UserKnownHostsFile=",KnownHosts," ",Host," ", - " -o KexAlgorithms=",Kex," 1+1."]), - ct:log("Cmd: ~p~n", [Cmd]), - - SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:log("~p Did not receive answer",[Kex]) - end - end, CommonKexs), - - ssh:stop_daemon(Pid). - -%%-------------------------------------------------------------------- -erlang_server_openssh_client_exec_compressed() -> - [{doc, "Test that exec command works."}]. - -erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), - KnownHosts = filename:join(PrivDir, "known_hosts"), - - CompressAlgs = [zlib, 'zlib@openssh.com'], % Does not work -%% CompressAlgs = [zlib], - case ssh_test_lib:ssh_supports(CompressAlgs, compression) of - {false,L} -> - {skip, io_lib:format("~p compression is not supported",[L])}; - - true -> - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {preferred_algorithms, - [{compression, CompressAlgs}]}, - {failfun, fun ssh_test_lib:failfun/2}]), - - ct:sleep(500), - - Cmd = "ssh -p " ++ integer_to_list(Port) ++ - " -o UserKnownHostsFile=" ++ KnownHosts ++ " -C "++ Host ++ " 1+1.", - SshPort = open_port({spawn, Cmd}, [binary]), - - receive - {SshPort,{data, <<"2\n">>}} -> - ok - after ?TIMEOUT -> - ct:fail("Did not receive answer") - end, - ssh:stop_daemon(Pid) - end. - %%-------------------------------------------------------------------- erlang_client_openssh_server_setenv() -> [{doc, "Test api function ssh_connection:setenv"}]. -- cgit v1.2.3 From 9b733abf49dd75a42d75d8964b20c37fee4ad7f1 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 20 Oct 2015 15:12:51 +0200 Subject: ssh: delete now obsolete test case group 'hardening_tests' Thoose tests are already moved to other test suites. However, the init_per_group and end_per_group clauses were accidently left --- lib/ssh/test/ssh_basic_SUITE.erl | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 24d8a4e53c..400edb4d2c 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -123,8 +123,6 @@ end_per_suite(_Config) -> ssh:stop(), crypto:stop(). %%-------------------------------------------------------------------- -init_per_group(hardening_tests, Config) -> - init_per_group(dsa_key, Config); init_per_group(dsa_key, Config) -> DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), @@ -229,8 +227,6 @@ init_per_group(dir_options, Config) -> init_per_group(_, Config) -> Config. -end_per_group(hardening_tests, Config) -> - end_per_group(dsa_key, Config); end_per_group(dsa_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:clean_dsa(PrivDir), -- cgit v1.2.3 From eb24b259f026629372f9f8957da72f4302adb904 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 20 Oct 2015 15:49:55 +0200 Subject: ssh: dynamic check of supported algos in ssh_to_openssh_SUITE --- lib/ssh/test/ssh_test_lib.erl | 8 ++++++++ lib/ssh/test/ssh_to_openssh_SUITE.erl | 15 +++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'lib') diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 2e63ec086b..5816b708f2 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -459,6 +459,14 @@ openssh_sanity_check(Config) -> {skip, Str} end. +openssh_supports(ClientOrServer, Tag, Alg) when ClientOrServer == sshc ; + ClientOrServer == sshd -> + SSH_algos = ssh_test_lib:default_algorithms(ClientOrServer), + L = proplists:get_value(Tag, SSH_algos, []), + lists:member(Alg, L) orelse + lists:member(Alg, proplists:get_value(client2server, L, [])) orelse + lists:member(Alg, proplists:get_value(server2client, L, [])). + %%-------------------------------------------------------------------- %% Check if we have a "newer" ssh client that supports these test cases diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index b5b997cb53..168b8a695a 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -94,6 +94,21 @@ end_per_group(erlang_server, Config) -> end_per_group(_, Config) -> Config. + +init_per_testcase(erlang_server_openssh_client_pulic_key_dsa, Config) -> + case ssh_test_lib:openssh_supports(sshc, public_key, 'ssh-dss') of + true -> + init_per_testcase('__default__',Config); + false -> + {skip,"openssh client does not support DSA"} + end; +init_per_testcase(erlang_client_openssh_server_publickey_dsa, Config) -> + case ssh_test_lib:openssh_supports(sshd, public_key, 'ssh-dss') of + true -> + init_per_testcase('__default__',Config); + false -> + {skip,"openssh client does not support DSA"} + end; init_per_testcase(_TestCase, Config) -> ssh:start(), Config. -- cgit v1.2.3 From e30f65485aec78c6bd65e25e5a185100b3f8f042 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Tue, 20 Oct 2015 16:25:13 +0100 Subject: Adjust shutdown strategies for distribution over TLS Change ssl_dist_sup to be considered as a supervisor with infinite shutdown time. Change the ssl_connection_dist instance of tls_connection_sup to have infinite shutdown time. This avoids spurious error messages when shutting down a node that uses distribution over TLS. --- lib/ssl/src/inet_tls_dist.erl | 2 +- lib/ssl/src/ssl_dist_sup.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl index 7367b5c224..a633df1558 100644 --- a/lib/ssl/src/inet_tls_dist.erl +++ b/lib/ssl/src/inet_tls_dist.erl @@ -29,7 +29,7 @@ childspecs() -> {ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []}, - permanent, 2000, worker, [ssl_dist_sup]}]}. + permanent, infinity, supervisor, [ssl_dist_sup]}]}. select(Node) -> case split_node(atom_to_list(Node), $@, []) of diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl index 58efeaf892..0c7fc77db7 100644 --- a/lib/ssl/src/ssl_dist_sup.erl +++ b/lib/ssl/src/ssl_dist_sup.erl @@ -69,7 +69,7 @@ connection_manager_child_spec() -> Name = ssl_connection_dist, StartFunc = {tls_connection_sup, start_link_dist, []}, Restart = permanent, - Shutdown = 4000, + Shutdown = infinity, Modules = [tls_connection_sup], Type = supervisor, {Name, StartFunc, Restart, Shutdown, Type, Modules}. -- cgit v1.2.3 From 32ba359b05658960b86f7587b61b46d1fb2021be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 22 Oct 2015 13:15:25 +0200 Subject: beam_lib: Document all_chunks/1 and build_module/1 beam_lib:all_chunks/1 and beam_lib:build_module/1 can be useful for special-purpose stripping, for example to remove the "Line" chunk. --- lib/stdlib/doc/src/beam_lib.xml | 14 ++++++++++++++ lib/stdlib/src/beam_lib.erl | 17 +++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml index c556180b8b..faf668735e 100644 --- a/lib/stdlib/doc/src/beam_lib.xml +++ b/lib/stdlib/doc/src/beam_lib.xml @@ -223,6 +223,13 @@ + + + Read all chunks from a BEAM file or binary + +

Reads chunk data for all chunks.

+
+
Read selected chunks from a BEAM file or binary @@ -250,6 +257,13 @@ tuple.

+ + + Creates a BEAM module from a list of chunks + +

Builds a BEAM module (as a binary) from a list of chunks.

+
+
Read the BEAM file's module version diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl index b93ce97cd3..cbbab088f4 100644 --- a/lib/stdlib/src/beam_lib.erl +++ b/lib/stdlib/src/beam_lib.erl @@ -308,6 +308,17 @@ make_crypto_key(des3_cbc=Type, String) -> <> = erlang:md5([First|reverse(String)]), {Type,[K1,K2,K3],IVec,8}. +-spec build_module(Chunks) -> {'ok', Binary} when + Chunks :: [{chunkid(), dataB()}], + Binary :: binary(). + +build_module(Chunks0) -> + Chunks = list_to_binary(build_chunks(Chunks0)), + Size = byte_size(Chunks), + 0 = Size rem 4, % Assertion: correct padding? + {ok, <<"FOR1", (Size+4):32, "BEAM", Chunks/binary>>}. + + %% %% Local functions %% @@ -419,12 +430,6 @@ strip_file(File) -> end end. -build_module(Chunks0) -> - Chunks = list_to_binary(build_chunks(Chunks0)), - Size = byte_size(Chunks), - 0 = Size rem 4, % Assertion: correct padding? - {ok, <<"FOR1", (Size+4):32, "BEAM", Chunks/binary>>}. - build_chunks([{Id, Data} | Chunks]) -> BId = list_to_binary(Id), Size = byte_size(Data), -- cgit v1.2.3 From 120975c4fcb57ecd14031ac046f483e56a3daa4d Mon Sep 17 00:00:00 2001 From: Pawel Pikula Date: Thu, 22 Oct 2015 21:02:52 +0200 Subject: fix incorrect number of seconds in 24h macro The previous commit - 7b93f5d8a224a0a076a420294c95a666a763ee60 fixed the macro only in one place. --- lib/ssl/src/ssl_internal.hrl | 3 +++ lib/ssl/src/ssl_manager.erl | 2 -- lib/ssl/src/ssl_session.erl | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index 3851b2bc6e..8c7ed9c0d1 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -78,6 +78,9 @@ -define(ALL_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]). -define(MIN_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]). +-define('24H_in_msec', 86400000). +-define('24H_in_sec', 86400). + -record(ssl_options, { protocol :: tls | dtls, versions :: [ssl_record:ssl_version()], %% ssl_record:atom_version() in API diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index 2e05ba5aa5..cc15678f23 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -57,8 +57,6 @@ clear_pem_cache }). --define('24H_in_msec', 86400000). --define('24H_in_sec', 86400). -define(GEN_UNIQUE_ID_MAX_TRIES, 10). -define(SESSION_VALIDATION_INTERVAL, 60000). -define(CLEAR_PEM_CACHE, 120000). diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index 0d6cc93a20..1849a05314 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -31,8 +31,6 @@ %% Internal application API -export([is_new/2, client_id/4, server_id/6, valid_session/2]). --define('24H_in_sec', 8640). - -type seconds() :: integer(). %%-------------------------------------------------------------------- -- cgit v1.2.3 From 902ed3fe77d674fdbed3ee60ee613861ce2f1943 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Fri, 23 Oct 2015 17:16:38 +0100 Subject: In ssl_tls_dist_proxy, pass along EPMD registration errors The duplicate_name error returned from erl_epmd:register_node elicits a particularly precise error message from net_kernel, so let's pass it along to our caller. Not doing this for the other things that could go wrong here, since for those having the line number will likely aid debugging. --- lib/ssl/src/ssl_tls_dist_proxy.erl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index 273d3b5521..ce742948b7 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -66,9 +66,13 @@ handle_call({listen, Name}, _From, State) -> {ok, TcpAddress} = get_tcp_address(Socket), {ok, WorldTcpAddress} = get_tcp_address(World), {_,Port} = WorldTcpAddress#net_address.address, - {ok, Creation} = erl_epmd:register_node(Name, Port), - {reply, {ok, {Socket, TcpAddress, Creation}}, - State#state{listen={Socket, World}}}; + case erl_epmd:register_node(Name, Port) of + {ok, Creation} -> + {reply, {ok, {Socket, TcpAddress, Creation}}, + State#state{listen={Socket, World}}}; + {error, _} = Error -> + {reply, Error, State} + end; Error -> {reply, Error, State} end; -- cgit v1.2.3 From 285b4fa13914dc4748c1020213a9c65cad3d2738 Mon Sep 17 00:00:00 2001 From: Serge Aleynikov Date: Tue, 2 Jun 2015 08:44:23 -0400 Subject: erts: Add {line_delimiter, byte()} option to inet:setopts/2 A new {line_delimiter, byte()} option allows line-oriented TCP-based protocols to use a custom line delimiting character. It is to be used in conjunction with {packet, line}. This option also works with erlang:decode_packet/3 when its first argument is 'line'. --- lib/kernel/doc/src/inet.xml | 5 +++++ lib/kernel/src/inet.erl | 4 +++- lib/kernel/src/inet_int.hrl | 1 + lib/kernel/test/bif_SUITE.erl | 10 ++++++++++ lib/kernel/test/gen_tcp_api_SUITE.erl | 17 ++++++++++++++++- 5 files changed, 35 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index e5d7ce048a..e6d418dc58 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -981,6 +981,11 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp indicated length are accepted and not considered invalid due to internal buffer limitations.

+ {line_delimiter, Char}(TCP/IP sockets) + +

Sets the line delimiting character for line oriented protocols + (line). Default value is $\n.

+
{priority, Priority}

Set the protocol-defined priority for all packets to be sent diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index da7f04089d..855c6377a3 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -671,7 +671,7 @@ stats() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% connect_options() -> [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, - header, active, packet, packet_size, buffer, mode, deliver, + header, active, packet, packet_size, buffer, mode, deliver, line_delimiter, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw, show_econnreset]. @@ -721,6 +721,8 @@ con_opt([Opt | Opts], #connect_opts{} = R, As) -> {active,N} when is_integer(N), N < 32768, N >= -32768 -> NOpts = lists:keydelete(active, 1, R#connect_opts.opts), con_opt(Opts, R#connect_opts { opts = [{active,N}|NOpts] }, As); + {line_delimiter,C} when is_integer(C), C >= 0, C =< 255 -> + con_add(line_delimiter, C, R, Opts, As); {Name,Val} when is_atom(Name) -> con_add(Name, Val, R, Opts, As); _ -> {error, badarg} end; diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index bfe4c9ec8c..e7c6cf8ae2 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -149,6 +149,7 @@ -define(INET_LOPT_MSGQ_LOWTRMRK, 37). -define(INET_LOPT_NETNS, 38). -define(INET_LOPT_TCP_SHOW_ECONNRESET, 39). +-define(INET_LOPT_LINE_DELIM, 40). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl index c3840f3d16..dd3010567a 100644 --- a/lib/kernel/test/bif_SUITE.erl +++ b/lib/kernel/test/bif_SUITE.erl @@ -33,6 +33,7 @@ spawn_failures/1, run_fun/1, + decode_packet_delim/1, wilderness/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -516,6 +517,15 @@ fetch_proc_vals(Pid) -> {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI), ?line {Ls, P, FA, HS}. +decode_packet_delim(doc) -> + ["Test erlang:packet_delim/3 with {line_delimiter,0} option"]; +decode_packet_delim(suite) -> + []; +decode_packet_delim(Config) when is_list(Config) -> + {ok,<<"abc",0>>,<<"efg",0>>} = + erlang:decode_packet(line, <<"abc",0,"efg",0>>, [{line_delimiter, 0}]), + {more, undefined} = erlang:decode_packet(line, <<"abc",0,"efg",0>>, []). + % This testcase should probably be moved somewhere else wilderness(doc) -> ["Test that memory allocation command line options affecting the" diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index a051d504b2..2febb1bd68 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -31,7 +31,7 @@ init_per_testcase/2, end_per_testcase/2, t_connect_timeout/1, t_accept_timeout/1, t_connect_bad/1, - t_recv_timeout/1, t_recv_eof/1, + t_recv_timeout/1, t_recv_eof/1, t_recv_delim/1, t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1, t_shutdown_async/1, t_fdopen/1, t_fdconnect/1, t_implicit_inet6/1]). @@ -131,6 +131,21 @@ t_recv_eof(Config) when is_list(Config) -> ?line {error, closed} = gen_tcp:recv(Client, 0), ok. +t_recv_delim(doc) -> "Test using message delimiter $X"; +t_recv_delim(suite) -> []; +t_recv_delim(Config) when is_list(Config) -> + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + Opts = [{active,false},{packet,line},{line_delimiter,$X}], + {ok, Client} = gen_tcp:connect(localhost, Port, Opts), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:send(A, "abcXefgX"), + {ok, "abcX"} = gen_tcp:recv(Client, 0, 0), + {ok, "efgX"} = gen_tcp:recv(Client, 0, 0), + ok = gen_tcp:close(Client), + ok = gen_tcp:close(A), + ok. + %%% gen_tcp:shutdown/2 t_shutdown_write(Config) when is_list(Config) -> -- cgit v1.2.3 From 235bf943d762bfdb5638d23b3270f92c50050b0a Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 23 Oct 2015 10:34:49 +0200 Subject: erts: Include test in group so that it is run --- lib/kernel/test/gen_tcp_api_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 2febb1bd68..962471c20c 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -48,7 +48,7 @@ all() -> groups() -> [{t_accept, [], [t_accept_timeout]}, {t_connect, [], [t_connect_timeout, t_connect_bad]}, - {t_recv, [], [t_recv_timeout, t_recv_eof]}]. + {t_recv, [], [t_recv_timeout, t_recv_eof, t_recv_delim]}]. -- cgit v1.2.3 From afac3c7136c48d8630bd400c5454e146915e634f Mon Sep 17 00:00:00 2001 From: Serge Aleynikov Date: Mon, 26 Oct 2015 14:46:54 +0100 Subject: erts: Add {line_delimiter, byte()} option to inet:setopts/2 A new {line_delimiter, byte()} option allows line-oriented TCP-based protocols to use a custom line delimiting character. It is to be used in conjunction with {packet, line}. This option also works with erlang:decode_packet/3 when its first argument is 'line'. --- lib/kernel/doc/src/inet.xml | 5 +++++ lib/kernel/src/inet.erl | 4 +++- lib/kernel/src/inet_int.hrl | 1 + lib/kernel/test/bif_SUITE.erl | 10 ++++++++++ lib/kernel/test/gen_tcp_api_SUITE.erl | 17 ++++++++++++++++- 5 files changed, 35 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index e5d7ce048a..e6d418dc58 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -981,6 +981,11 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp indicated length are accepted and not considered invalid due to internal buffer limitations.

+ {line_delimiter, Char}(TCP/IP sockets) + +

Sets the line delimiting character for line oriented protocols + (line). Default value is $\n.

+
{priority, Priority}

Set the protocol-defined priority for all packets to be sent diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index da7f04089d..855c6377a3 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -671,7 +671,7 @@ stats() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% connect_options() -> [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, - header, active, packet, packet_size, buffer, mode, deliver, + header, active, packet, packet_size, buffer, mode, deliver, line_delimiter, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw, show_econnreset]. @@ -721,6 +721,8 @@ con_opt([Opt | Opts], #connect_opts{} = R, As) -> {active,N} when is_integer(N), N < 32768, N >= -32768 -> NOpts = lists:keydelete(active, 1, R#connect_opts.opts), con_opt(Opts, R#connect_opts { opts = [{active,N}|NOpts] }, As); + {line_delimiter,C} when is_integer(C), C >= 0, C =< 255 -> + con_add(line_delimiter, C, R, Opts, As); {Name,Val} when is_atom(Name) -> con_add(Name, Val, R, Opts, As); _ -> {error, badarg} end; diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index bfe4c9ec8c..e7c6cf8ae2 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -149,6 +149,7 @@ -define(INET_LOPT_MSGQ_LOWTRMRK, 37). -define(INET_LOPT_NETNS, 38). -define(INET_LOPT_TCP_SHOW_ECONNRESET, 39). +-define(INET_LOPT_LINE_DELIM, 40). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl index c3840f3d16..dd3010567a 100644 --- a/lib/kernel/test/bif_SUITE.erl +++ b/lib/kernel/test/bif_SUITE.erl @@ -33,6 +33,7 @@ spawn_failures/1, run_fun/1, + decode_packet_delim/1, wilderness/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -516,6 +517,15 @@ fetch_proc_vals(Pid) -> {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI), ?line {Ls, P, FA, HS}. +decode_packet_delim(doc) -> + ["Test erlang:packet_delim/3 with {line_delimiter,0} option"]; +decode_packet_delim(suite) -> + []; +decode_packet_delim(Config) when is_list(Config) -> + {ok,<<"abc",0>>,<<"efg",0>>} = + erlang:decode_packet(line, <<"abc",0,"efg",0>>, [{line_delimiter, 0}]), + {more, undefined} = erlang:decode_packet(line, <<"abc",0,"efg",0>>, []). + % This testcase should probably be moved somewhere else wilderness(doc) -> ["Test that memory allocation command line options affecting the" diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index a051d504b2..2febb1bd68 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -31,7 +31,7 @@ init_per_testcase/2, end_per_testcase/2, t_connect_timeout/1, t_accept_timeout/1, t_connect_bad/1, - t_recv_timeout/1, t_recv_eof/1, + t_recv_timeout/1, t_recv_eof/1, t_recv_delim/1, t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1, t_shutdown_async/1, t_fdopen/1, t_fdconnect/1, t_implicit_inet6/1]). @@ -131,6 +131,21 @@ t_recv_eof(Config) when is_list(Config) -> ?line {error, closed} = gen_tcp:recv(Client, 0), ok. +t_recv_delim(doc) -> "Test using message delimiter $X"; +t_recv_delim(suite) -> []; +t_recv_delim(Config) when is_list(Config) -> + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + Opts = [{active,false},{packet,line},{line_delimiter,$X}], + {ok, Client} = gen_tcp:connect(localhost, Port, Opts), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:send(A, "abcXefgX"), + {ok, "abcX"} = gen_tcp:recv(Client, 0, 0), + {ok, "efgX"} = gen_tcp:recv(Client, 0, 0), + ok = gen_tcp:close(Client), + ok = gen_tcp:close(A), + ok. + %%% gen_tcp:shutdown/2 t_shutdown_write(Config) when is_list(Config) -> -- cgit v1.2.3 From 61d214cff5fe50b2806f8f977d36bccd412bcfc4 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 23 Oct 2015 10:34:49 +0200 Subject: erts: Include test in group so that it is run --- lib/kernel/test/gen_tcp_api_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 2febb1bd68..962471c20c 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -48,7 +48,7 @@ all() -> groups() -> [{t_accept, [], [t_accept_timeout]}, {t_connect, [], [t_connect_timeout, t_connect_bad]}, - {t_recv, [], [t_recv_timeout, t_recv_eof]}]. + {t_recv, [], [t_recv_timeout, t_recv_eof, t_recv_delim]}]. -- cgit v1.2.3 From cc1026a0e646b3a21b7bd7930fb7294425f1d79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Thu, 5 Jun 2014 12:12:03 +0200 Subject: Fix cerl_trees:label/2 bug with map K/V swap --- lib/compiler/src/cerl_trees.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/cerl_trees.erl b/lib/compiler/src/cerl_trees.erl index 2c9b72a30b..58bb18e34a 100644 --- a/lib/compiler/src/cerl_trees.erl +++ b/lib/compiler/src/cerl_trees.erl @@ -731,8 +731,8 @@ label(T, N, Env) -> {ann_c_map(As, M, Ts), N3}; map_pair -> {Op, N1} = label(map_pair_op(T), N, Env), - {Val, N2} = label(map_pair_key(T), N1, Env), - {Key, N3} = label(map_pair_val(T), N2, Env), + {Key, N2} = label(map_pair_key(T), N1, Env), + {Val, N3} = label(map_pair_val(T), N2, Env), {As, N4} = label_ann(T, N3), {ann_c_map_pair(As,Op,Key,Val), N4}; 'let' -> -- cgit v1.2.3 From fb1c22169c96b51f331c0e7885cdbd0806585da2 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Mon, 26 Oct 2015 15:55:49 +0000 Subject: Make erl -make return non-zero exit code on failure This makes it behave like similar Unix tools. --- lib/tools/src/make.erl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl index c8ef0a04a5..59d02ed648 100644 --- a/lib/tools/src/make.erl +++ b/lib/tools/src/make.erl @@ -24,12 +24,20 @@ %% If Emakefile is missing the current directory is used. -module(make). --export([all/0,all/1,files/1,files/2]). +-export([all_or_nothing/0,all/0,all/1,files/1,files/2]). -include_lib("kernel/include/file.hrl"). -define(MakeOpts,[noexec,load,netload,noload]). +all_or_nothing() -> + case all() of + up_to_date -> + up_to_date; + error -> + halt(1) + end. + all() -> all([]). -- cgit v1.2.3 From dc534440976691ded585e17bdeb92f0fa9a71876 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Wed, 7 Oct 2015 16:34:17 +0200 Subject: observer: Show ets owner pid in crashdump viewers ets popup window Owner pid was silently ignored. Bug fix supplied on erlang-bugs by Leo Liu. --- lib/observer/src/cdv_ets_cb.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/observer/src/cdv_ets_cb.erl b/lib/observer/src/cdv_ets_cb.erl index 9e6e72e08d..bac8b56fc3 100644 --- a/lib/observer/src/cdv_ets_cb.erl +++ b/lib/observer/src/cdv_ets_cb.erl @@ -97,7 +97,7 @@ info_fields() -> [{"Id", id}, {"Name", name}, {"Slot", slot}, - {"Owner", owner}, + {"Owner", pid}, {"Data Structure", data_type} ]}, {"Settings", -- cgit v1.2.3 From 75b95b2e899baba8e254ec4742e0442ed4419efc Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Mon, 12 Oct 2015 15:11:19 +0200 Subject: cdv: Fix crashdump ets table type The type was set in the wrong datastructure. --- lib/observer/src/crashdump_viewer.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index f2ce51b2af..b66b4d59c9 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -1572,7 +1572,7 @@ get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) -> get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{fixed=>Val}},WS); "Type" -> Val = val(Fd), - get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{data_type=>Val}},WS); + get_etsinfo(Fd,EtsTable#ets_table{data_type=Val},WS); "Protection" -> Val = val(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{protection=>Val}},WS); -- cgit v1.2.3 From f4b02cf574552f40ff354261b4c7cf02cb568212 Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Tue, 20 Jan 2015 21:06:13 +0300 Subject: inets: send correct nonstreamed response with streaming httpc_handler should respond with correct and complete responses seeing non-streamed status codes i.e. codes other than 200 or 206. --- lib/inets/src/http_client/httpc_handler.erl | 28 ++++++++++++------------- lib/inets/test/httpc_SUITE.erl | 32 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 6e6cc38c06..0300a80b03 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -163,7 +163,7 @@ info(Pid) -> %% Request should not be streamed stream(BodyPart, #request{stream = none} = Request, _) -> ?hcrt("stream - none", []), - {BodyPart, Request}; + {false, BodyPart, Request}; %% Stream to caller stream(BodyPart, #request{stream = Self} = Request, Code) @@ -172,7 +172,7 @@ stream(BodyPart, #request{stream = Self} = Request, Code) ?hcrt("stream - self", [{stream, Self}, {code, Code}]), httpc_response:send(Request#request.from, {Request#request.id, stream, BodyPart}), - {<<>>, Request}; + {true, <<>>, Request}; %% Stream to file %% This has been moved to start_stream/3 @@ -194,14 +194,14 @@ stream(BodyPart, #request{stream = Fd} = Request, Code) ?hcrt("stream to file", [{stream, Fd}, {code, Code}]), case file:write(Fd, BodyPart) of ok -> - {<<>>, Request}; + {true, <<>>, Request}; {error, Reason} -> exit({stream_to_file_failed, Reason}) end; stream(BodyPart, Request,_) -> % only 200 and 206 responses can be streamed ?hcrt("stream - ignore", [{request, Request}]), - {BodyPart, Request}. + {false, BodyPart, Request}. %%==================================================================== @@ -474,14 +474,14 @@ handle_info({Proto, _Socket, Data}, {Module, whole_body, [Body, Length]} -> ?hcrd("data processed - whole body", [{length, Length}]), {_, Code, _} = StatusLine, - {NewBody, NewRequest} = stream(Body, Request, Code), + {Streamed, NewBody, NewRequest} = stream(Body, Request, Code), %% When we stream we will not keep the already %% streamed data, that would be a waste of memory. NewLength = - case Stream of - none -> + case Streamed of + false -> Length; - _ -> + true -> Length - size(Body) end, @@ -497,7 +497,7 @@ handle_info({Proto, _Socket, Data}, %% The response body is chunk-encoded. Steal decoded %% chunks as much as possible to stream. {_, Code, _} = StatusLine, - {NewBody, NewRequest} = stream(BodySoFar, Request, Code), + {_, NewBody, NewRequest} = stream(BodySoFar, Request, Code), NewState = next_body_chunk(State), NewMFA = {Module, decode_size, [TotalChunk, HexList, @@ -517,7 +517,7 @@ handle_info({Proto, _Socket, Data}, NewChunkSize = ChunkSize - ChunkSizeToSteal, {_, Code, _} = StatusLine, - {NewBody, NewRequest} = stream(StolenBody, Request, Code), + {_, NewBody, NewRequest} = stream(StolenBody, Request, Code), NewState = next_body_chunk(State), NewMFA = {Module, decode_data, [NewChunkSize, NewTotalChunk, @@ -1071,13 +1071,13 @@ handle_http_msg({ChunkedHeaders, Body}, ?hcrt("handle_http_msg", [{chunked_headers, ChunkedHeaders}, {headers, Headers}]), NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders), - {NewBody, NewRequest} = stream(Body, State#state.request, Code), + {_, NewBody, NewRequest} = stream(Body, State#state.request, Code), handle_response(State#state{headers = NewHeaders, body = NewBody, request = NewRequest}); handle_http_msg(Body, #state{status_line = {_,Code, _}} = State) -> ?hcrt("handle_http_msg", [{code, Code}]), - {NewBody, NewRequest} = stream(Body, State#state.request, Code), + {_, NewBody, NewRequest} = stream(Body, State#state.request, Code), handle_response(State#state{body = NewBody, request = NewRequest}). handle_http_body(_, #state{status = {ssl_tunnel, _}, @@ -1133,7 +1133,7 @@ handle_http_body(Body, #state{headers = Headers, handle_response(State#state{headers = NewHeaders, body = NewBody}); _ -> - {NewBody2, _NewRequest} = + {_, NewBody2, _} = stream(NewBody, Request, Code), handle_response(State#state{headers = NewHeaders, body = NewBody2}) @@ -1147,7 +1147,7 @@ handle_http_body(Body, #state{headers = Headers, true -> case httpc_response:whole_body(Body, Length) of {ok, Body} -> - {NewBody, NewRequest} = + {_, NewBody, NewRequest} = stream(Body, Request, Code), handle_response(State#state{body = NewBody, request = NewRequest}); diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 2ad00bdf76..cc0fa5d4d9 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -98,6 +98,7 @@ only_simulated() -> stream_once, stream_single_chunk, stream_no_length, + stream_large_not_200_or_206, no_content_204, tolerate_missing_CR, userinfo, @@ -408,6 +409,13 @@ stream_no_length(Config) when is_list(Config) -> stream_test(Request1, {stream, self}), Request2 = {url(group_name(Config), "/http_1_0_no_length_multiple.html", Config), []}, stream_test(Request2, {stream, self}). +%%------------------------------------------------------------------------- +stream_large_not_200_or_206() -> + [{doc, "Test the option stream for large responses with status codes " + "other than 200 or 206" }]. +stream_large_not_200_or_206(Config) when is_list(Config) -> + Request = {url(group_name(Config), "/large_404_response.html", Config), []}, + {{_,404,_}, _, _} = non_streamed_async_test(Request, {stream, self}). %%------------------------------------------------------------------------- @@ -1117,6 +1125,19 @@ stream_test(Request, To) -> Body = binary_to_list(StreamedBody). +non_streamed_async_test(Request, To) -> + {ok, Response} = + httpc:request(get, Request, [], [{body_format, binary}]), + {ok, RequestId} = + httpc:request(get, Request, [], [{sync, false}, To]), + + receive + {http, {RequestId, Response}} -> + Response; + {http, Msg} -> + ct:fail(Msg) + end. + url(http, End, Config) -> Port = ?config(port, Config), {ok,Host} = inet:gethostname(), @@ -1807,6 +1828,17 @@ handle_uri(_,"/http_1_0_no_length_multiple.html",_,_,Socket,_) -> send(Socket, string:copies("other multiple packets ", 200)), close(Socket); +handle_uri(_,"/large_404_response.html",_,_,Socket,_) -> + %% long body to make sure it will be sent in multiple tcp packets + Body = string:copies("other multiple packets ", 200), + Head = io_lib:format("HTTP/1.1 404 not found\r\n" + "Content-length: ~B\r\n" + "Content-type: text/plain\r\n\r\n", + [length(Body)]), + send(Socket, Head), + send(Socket, Body), + close(Socket); + handle_uri(_,"/once.html",_,_,Socket,_) -> Head = "HTTP/1.1 200 ok\r\n" ++ "Content-Length:32\r\n\r\n", -- cgit v1.2.3 From 45251cd60ebad4ef08ffc7cb0797d1fd7a603eea Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Wed, 23 Sep 2015 16:51:33 +0300 Subject: inets: fix {self, once} for not streamed request httpc should work properly if streaming option {self, once} is chosen and the corresponding response does not get streamed. --- lib/inets/src/http_client/httpc_handler.erl | 31 +++++++++++---------- lib/inets/test/httpc_SUITE.erl | 43 ++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 0300a80b03..1044cffe6f 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -26,6 +26,7 @@ -include_lib("inets/src/http_lib/http_internal.hrl"). -include("httpc_internal.hrl"). +-define(IS_STREAMED(Code), ((Code =:= 200) orelse (Code =:= 206))). %%-------------------------------------------------------------------- %% Internal Application API @@ -167,7 +168,7 @@ stream(BodyPart, #request{stream = none} = Request, _) -> %% Stream to caller stream(BodyPart, #request{stream = Self} = Request, Code) - when ((Code =:= 200) orelse (Code =:= 206)) andalso + when ?IS_STREAMED(Code) andalso ((Self =:= self) orelse (Self =:= {self, once})) -> ?hcrt("stream - self", [{stream, Self}, {code, Code}]), httpc_response:send(Request#request.from, @@ -178,7 +179,7 @@ stream(BodyPart, #request{stream = Self} = Request, Code) %% This has been moved to start_stream/3 %% We keep this for backward compatibillity... stream(BodyPart, #request{stream = Filename} = Request, Code) - when ((Code =:= 200) orelse (Code =:= 206)) andalso is_list(Filename) -> + when ?IS_STREAMED(Code) andalso is_list(Filename) -> ?hcrt("stream - filename", [{stream, Filename}, {code, Code}]), case file:open(Filename, [write, raw, append, delayed_write]) of {ok, Fd} -> @@ -190,7 +191,7 @@ stream(BodyPart, #request{stream = Filename} = Request, Code) %% Stream to file stream(BodyPart, #request{stream = Fd} = Request, Code) - when ((Code =:= 200) orelse (Code =:= 206)) -> + when ?IS_STREAMED(Code) -> ?hcrt("stream to file", [{stream, Fd}, {code, Code}]), case file:write(Fd, BodyPart) of ok -> @@ -485,7 +486,7 @@ handle_info({Proto, _Socket, Data}, Length - size(Body) end, - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), NewMFA = {Module, whole_body, [NewBody, NewLength]}, {noreply, NewState#state{mfa = NewMFA, request = NewRequest}}; @@ -498,7 +499,7 @@ handle_info({Proto, _Socket, Data}, %% chunks as much as possible to stream. {_, Code, _} = StatusLine, {_, NewBody, NewRequest} = stream(BodySoFar, Request, Code), - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), NewMFA = {Module, decode_size, [TotalChunk, HexList, {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}, @@ -518,7 +519,7 @@ handle_info({Proto, _Socket, Data}, {_, Code, _} = StatusLine, {_, NewBody, NewRequest} = stream(StolenBody, Request, Code), - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), NewMFA = {Module, decode_data, [NewChunkSize, NewTotalChunk, {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}, @@ -1119,7 +1120,7 @@ handle_http_body(Body, #state{headers = Headers, [{module, Module}, {function, Function}, {args, Args}]), - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), {noreply, NewState#state{mfa = {Module, Function, Args}}}; {ok, {ChunkedHeaders, NewBody}} -> @@ -1152,7 +1153,7 @@ handle_http_body(Body, #state{headers = Headers, handle_response(State#state{body = NewBody, request = NewRequest}); MFA -> - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), {noreply, NewState#state{mfa = MFA}} end; false -> @@ -1646,21 +1647,21 @@ start_stream({_Version, _Code, _ReasonPhrase}, _Headers, {ok, Request}; start_stream({_Version, Code, _ReasonPhrase}, Headers, #request{stream = self} = Request) - when (Code =:= 200) orelse (Code =:= 206) -> + when ?IS_STREAMED(Code) -> ?hcrt("start stream - self", [{code, Code}]), Msg = httpc_response:stream_start(Headers, Request, ignore), httpc_response:send(Request#request.from, Msg), {ok, Request}; start_stream({_Version, Code, _ReasonPhrase}, Headers, #request{stream = {self, once}} = Request) - when (Code =:= 200) orelse (Code =:= 206) -> + when ?IS_STREAMED(Code) -> ?hcrt("start stream - self:once", [{code, Code}]), Msg = httpc_response:stream_start(Headers, Request, self()), httpc_response:send(Request#request.from, Msg), {ok, Request}; start_stream({_Version, Code, _ReasonPhrase}, _Headers, #request{stream = Filename} = Request) - when ((Code =:= 200) orelse (Code =:= 206)) andalso is_list(Filename) -> + when ?IS_STREAMED(Code) andalso is_list(Filename) -> ?hcrt("start stream", [{code, Code}, {filename, Filename}]), case file:open(Filename, [write, raw, append, delayed_write]) of {ok, Fd} -> @@ -1712,13 +1713,15 @@ end_stream(SL, R) -> next_body_chunk(#state{request = #request{stream = {self, once}}, once = once, - session = Session} = State) -> + session = Session} = State, + Code) when ?IS_STREAMED(Code) -> activate_once(Session), State#state{once = inactive}; next_body_chunk(#state{request = #request{stream = {self, once}}, - once = inactive} = State) -> + once = inactive} = State, + Code) when ?IS_STREAMED(Code) -> State; %% Wait for user to call stream_next -next_body_chunk(#state{session = Session} = State) -> +next_body_chunk(#state{session = Session} = State, _) -> activate_once(Session), State. diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index cc0fa5d4d9..989563cdbc 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -98,6 +98,7 @@ only_simulated() -> stream_once, stream_single_chunk, stream_no_length, + not_streamed_once, stream_large_not_200_or_206, no_content_204, tolerate_missing_CR, @@ -415,7 +416,15 @@ stream_large_not_200_or_206() -> "other than 200 or 206" }]. stream_large_not_200_or_206(Config) when is_list(Config) -> Request = {url(group_name(Config), "/large_404_response.html", Config), []}, - {{_,404,_}, _, _} = non_streamed_async_test(Request, {stream, self}). + {404, _} = not_streamed_test(Request, {stream, self}). +%%------------------------------------------------------------------------- +not_streamed_once() -> + [{doc, "Test not streamed responses with once streaming"}]. +not_streamed_once(Config) when is_list(Config) -> + Request0 = {url(group_name(Config), "/404.html", Config), []}, + {404, _} = not_streamed_test(Request0, {stream, {self, once}}), + Request1 = {url(group_name(Config), "/404_chunked.html", Config), []}, + {404, _} = not_streamed_test(Request1, {stream, {self, once}}). %%------------------------------------------------------------------------- @@ -1125,18 +1134,18 @@ stream_test(Request, To) -> Body = binary_to_list(StreamedBody). -non_streamed_async_test(Request, To) -> - {ok, Response} = +not_streamed_test(Request, To) -> + {ok, {{_,Code,_}, [_ | _], Body}} = httpc:request(get, Request, [], [{body_format, binary}]), {ok, RequestId} = - httpc:request(get, Request, [], [{sync, false}, To]), + httpc:request(get, Request, [], [{body_format, binary}, {sync, false}, To]), - receive - {http, {RequestId, Response}} -> - Response; - {http, Msg} -> - ct:fail(Msg) - end. + receive + {http, {RequestId, {{_, Code, _}, _Headers, Body}}} -> + {Code, binary_to_list(Body)}; + {http, Msg} -> + ct:fail(Msg) + end. url(http, End, Config) -> Port = ?config(port, Config), @@ -1669,6 +1678,11 @@ handle_uri(_,"/307.html",Port,_,Socket,_) -> "Content-Length:" ++ integer_to_list(length(Body)) ++ "\r\n\r\n" ++ Body; +handle_uri(_,"/404.html",_,_,_,_) -> + "HTTP/1.1 404 not found\r\n" ++ + "Content-Length:14\r\n\r\n" ++ + "Page not found"; + handle_uri(_,"/500.html",_,_,_,_) -> "HTTP/1.1 500 Internal Server Error\r\n" ++ "Content-Length:47\r\n\r\n" ++ @@ -1804,6 +1818,15 @@ handle_uri(_,"/once_chunked.html",_,_,Socket,_) -> http_chunk:encode("obar")), http_chunk:encode_last(); +handle_uri(_,"/404_chunked.html",_,_,Socket,_) -> + Head = "HTTP/1.1 404 not found\r\n" ++ + "Transfer-Encoding:Chunked\r\n\r\n", + send(Socket, Head), + send(Socket, http_chunk:encode("Not ")), + send(Socket, + http_chunk:encode("found")), + http_chunk:encode_last(); + handle_uri(_,"/single_chunk.html",_,_,Socket,_) -> Chunk = "HTTP/1.1 200 ok\r\n" ++ "Transfer-Encoding:Chunked\r\n\r\n" ++ -- cgit v1.2.3 From 33ddd3f0699cbb4aa9aea2ec7fcf690d5c498c53 Mon Sep 17 00:00:00 2001 From: Luca Favatella Date: Fri, 16 Oct 2015 00:31:11 +0100 Subject: Teach Dialyzer call to funs `M:F/A` (literal M, F, A) --- lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 22 ++++++++++++++++++ lib/dialyzer/src/dialyzer_callgraph.erl | 27 ++++++++++++++++++++-- .../test/small_SUITE_data/results/fun_arity | 2 ++ .../test/small_SUITE_data/results/non_existing | 1 + 4 files changed, 50 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index c57a22129c..826ac51775 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -624,6 +624,28 @@ find_call_file_and_line(Tree, MFA) -> MFA -> Ann = cerl:get_ann(SubTree), [{get_file(Ann), get_line(Ann)}|Acc]; + {erlang, make_fun, 3} -> + [CA1, CA2, CA3] = cerl:call_args(SubTree), + case + cerl:is_c_atom(CA1) andalso + cerl:is_c_atom(CA2) andalso + cerl:is_c_int(CA3) + of + true -> + case + {cerl:concrete(CA1), + cerl:concrete(CA2), + cerl:concrete(CA3)} + of + MFA -> + Ann = cerl:get_ann(SubTree), + [{get_file(Ann), get_line(Ann)}|Acc]; + _ -> + Acc + end; + false -> + Acc + end; _ -> Acc end; false -> Acc diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl index a1cd2015ca..9e53e171c0 100644 --- a/lib/dialyzer/src/dialyzer_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_callgraph.erl @@ -478,14 +478,37 @@ scan_one_core_fun(TopTree, FunName) -> call -> CalleeM = cerl:call_module(Tree), CalleeF = cerl:call_name(Tree), - A = length(cerl:call_args(Tree)), + CalleeArgs = cerl:call_args(Tree), + A = length(CalleeArgs), case (cerl:is_c_atom(CalleeM) andalso cerl:is_c_atom(CalleeF)) of true -> M = cerl:atom_val(CalleeM), F = cerl:atom_val(CalleeF), case erl_bif_types:is_known(M, F, A) of - true -> Acc; + true -> + case {M, F, A} of + {erlang, make_fun, 3} -> + [CA1, CA2, CA3] = CalleeArgs, + case + cerl:is_c_atom(CA1) andalso + cerl:is_c_atom(CA2) andalso + cerl:is_c_int(CA3) + of + true -> + MM = cerl:atom_val(CA1), + FF = cerl:atom_val(CA2), + AA = cerl:int_val(CA3), + case erl_bif_types:is_known(MM, FF, AA) of + true -> Acc; + false -> [{FunName, {MM, FF, AA}}|Acc] + end; + false -> + Acc + end; + _ -> + Acc + end; false -> [{FunName, {M, F, A}}|Acc] end; false -> diff --git a/lib/dialyzer/test/small_SUITE_data/results/fun_arity b/lib/dialyzer/test/small_SUITE_data/results/fun_arity index 280f5490d0..cc9db65152 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/fun_arity +++ b/lib/dialyzer/test/small_SUITE_data/results/fun_arity @@ -31,5 +31,7 @@ fun_arity.erl:81: Function mfa_ne_1_ko/0 has no local return fun_arity.erl:83: Function mf_ne/1 will never be called fun_arity.erl:89: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 fun_arity.erl:89: Function mfa_nd_0_ko/0 has no local return +fun_arity.erl:90: Call to missing or unexported function fun_arity:mf_nd/0 fun_arity.erl:93: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 fun_arity.erl:93: Function mfa_nd_1_ko/0 has no local return +fun_arity.erl:94: Call to missing or unexported function fun_arity:mf_nd/1 diff --git a/lib/dialyzer/test/small_SUITE_data/results/non_existing b/lib/dialyzer/test/small_SUITE_data/results/non_existing index 58da2bfc8b..b0da5998c7 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/non_existing +++ b/lib/dialyzer/test/small_SUITE_data/results/non_existing @@ -1,2 +1,3 @@ +non_existing.erl:12: Call to missing or unexported function lists:non_existing_fun/1 non_existing.erl:9: Call to missing or unexported function lists:non_existing_call/1 -- cgit v1.2.3 From 8bc6d03ecffa6c3613e477c4ef07a6ed6794f8db Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 22 Oct 2015 17:35:12 +0200 Subject: ssh: testcases for bad service names --- lib/ssh/test/ssh_protocol_SUITE.erl | 99 ++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 743282ce9c..03c2ce53cb 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -46,7 +46,8 @@ suite() -> all() -> [{group,tool_tests}, - {group,kex} + {group,kex}, + {group,service_requests} ]. groups() -> @@ -61,7 +62,13 @@ groups() -> gex_client_init_default_exact, gex_client_init_option_groups, gex_client_init_option_groups_file - ]} + ]}, + {service_requests, [], [bad_service_name, + bad_long_service_name, + bad_very_long_service_name, + empty_service_name, + bad_service_name_then_correct + ]} ]. @@ -114,25 +121,10 @@ end_per_testcase(_TestCase, Config) -> %%% Connect to an erlang server and check that the testlib acts as a client. lib_works_as_client(Config) -> %% Connect and negotiate keys - {ok,InitialState} = - ssh_trpt_test_lib:exec( - [{set_options, [print_ops, print_seqnums, print_messages]}, - {connect, - server_host(Config),server_port(Config), - [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}, - {silently_accept_hosts, true}, - {user_dir, user_dir(Config)}, - {user_interaction, false}]}, - receive_hello, - {send, hello}, - {send, ssh_msg_kexinit}, - {match, #ssh_msg_kexinit{_='_'}, receive_msg}, - {send, ssh_msg_kexdh_init}, - {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, - {send, #ssh_msg_newkeys{}}, - {match, #ssh_msg_newkeys{_='_'}, receive_msg} - ] - ), + {ok,InitialState} = ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}] + ), + {ok,AfterKexState} = connect_and_kex(Config, InitialState), %% Do the authentcation {User,Pwd} = server_user_password(Config), @@ -147,7 +139,7 @@ lib_works_as_client(Config) -> ?STRING(unicode:characters_to_binary(Pwd))>> }}, {match, #ssh_msg_userauth_success{_='_'}, receive_msg} - ], InitialState), + ], AfterKexState), %% Disconnect {ok,_} = @@ -375,6 +367,48 @@ do_gex_client_init(Config, {Min,N,Max}, {_,{G,P}}) -> ] ). + +%%%-------------------------------------------------------------------- +bad_service_name(Config) -> + bad_service_name(Config, "kfglkjf"). + +bad_long_service_name(Config) -> + bad_service_name(Config, + lists:duplicate(?SSH_MAX_PACKET_SIZE div 2, $a)). + +bad_very_long_service_name(Config) -> + bad_service_name(Config, + lists:duplicate(4*?SSH_MAX_PACKET_SIZE, $a)). + +empty_service_name(Config) -> + bad_service_name(Config, ""). + +bad_service_name_then_correct(Config) -> + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, #ssh_msg_service_request{name = "kdjglkfdjgkldfjglkdfjglkfdjglkj"}}, + {send, #ssh_msg_service_request{name = "ssh-connection"}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + + +bad_service_name(Config, Name) -> + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, #ssh_msg_service_request{name = Name}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ @@ -482,3 +516,24 @@ std_connect(Host, Port, Config, Opts) -> 30000). %%%---------------------------------------------------------------- +connect_and_kex(Config) -> + connect_and_kex(Config, ssh_trpt_test_lib:exec([]) ). + +connect_and_kex(Config, InitialState) -> + ssh_trpt_test_lib:exec( + [{connect, + server_host(Config),server_port(Config), + [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}, + {silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}]}, + receive_hello, + {send, hello}, + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, ssh_msg_kexdh_init}, + {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, + {send, #ssh_msg_newkeys{}}, + {match, #ssh_msg_newkeys{_='_'}, receive_msg} + ], + InitialState). -- cgit v1.2.3 From 3dc5591d92876070e004242ff875b3f04ff92c34 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Wed, 28 Oct 2015 18:42:59 +0000 Subject: Avoid crash for SSL connections with nonexistent keyfile Starting an SSL connection with a nonexistent keyfile will obviously return an error: > ssl:connect("www.google.com", 443, [{keyfile, "nonexistent"}]). {error,{options,{keyfile,"nonexistent",{error,enoent}}}} But it also generates an error report with the following backtrace: ** Reason for termination = ** {badarg,[{ets,select_delete, [undefined,[{{{undefined,'_','_'},'_'},[],[true]}]], []}, {ets,match_delete,2,[{file,"ets.erl"},{line,700}]}, {ssl_pkix_db,remove_certs,2,[{file,"ssl_pkix_db.erl"},{line,243}]}, {ssl_connection,terminate,3, [{file,"ssl_connection.erl"},{line,941}]}, {tls_connection,terminate,3, [{file,"tls_connection.erl"},{line,335}]}, {gen_fsm,terminate,7,[{file,"gen_fsm.erl"},{line,610}]}, {gen_fsm,handle_msg,7,[{file,"gen_fsm.erl"},{line,532}]}, {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,240}]}]} This happens because the ssl_connection process receives its cert_db while handling the {start, Timeout} message, but if the handshake fails, the cert_db will never be inserted into the state data, and the terminate function will use 'undefined' as an ETS table name. Avoid this by checking for 'undefined' in the handle_trusted_certs_db function. --- lib/ssl/src/ssl_connection.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index f8afbdb41d..12a56df69f 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1781,7 +1781,7 @@ handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>, cac ok; handle_trusted_certs_db(#state{cert_db_ref = Ref, cert_db = CertDb, - ssl_options = #ssl_options{cacertfile = <<>>}}) -> + ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined -> %% Certs provided as DER directly can not be shared %% with other connections and it is safe to delete them when the connection ends. ssl_pkix_db:remove_trusted_certs(Ref, CertDb); -- cgit v1.2.3 From fcf198456fcd8e80c78b58c6616f7cf1266406cc Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Wed, 28 Oct 2015 17:06:10 +0000 Subject: Report bad options for TLS distribution connections If ssl:ssl_accept/2 returns an error related to options, it's most likely something we want to log. In particular, if the specified certificate file doesn't exist, this is where the error ends up, so we shouldn't just throw the error away. --- lib/ssl/src/ssl_tls_dist_proxy.erl | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index a22af6b960..e7f7fa96a1 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -157,6 +157,11 @@ accept_loop(Proxy, world = Type, Listen, Extra) -> end), ok = ssl:controlling_process(SslSocket, PairHandler), flush_old_controller(PairHandler, SslSocket); + {error, {options, _}} = Error -> + %% Bad options: that's probably our fault. Let's log that. + error_logger:error_msg("Cannot accept TLS distribution connection: ~s~n", + [ssl:format_error(Error)]), + gen_tcp:close(Socket); _ -> gen_tcp:close(Socket) end; -- cgit v1.2.3 From 6563ae580d5023b42f12d55a8b323f0253ae1faa Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 26 Oct 2015 17:08:30 +0100 Subject: ssh: fix spelling error pulic -> public --- lib/ssh/test/ssh_to_openssh_SUITE.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 168b8a695a..d1dfa2efdf 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -53,7 +53,7 @@ groups() -> erlang_client_openssh_server_kexs, erlang_client_openssh_server_nonexistent_subsystem ]}, - {erlang_server, [], [erlang_server_openssh_client_pulic_key_dsa]} + {erlang_server, [], [erlang_server_openssh_client_public_key_dsa]} ]. init_per_suite(Config) -> @@ -95,7 +95,7 @@ end_per_group(_, Config) -> Config. -init_per_testcase(erlang_server_openssh_client_pulic_key_dsa, Config) -> +init_per_testcase(erlang_server_openssh_client_public_key_dsa, Config) -> case ssh_test_lib:openssh_supports(sshc, public_key, 'ssh-dss') of true -> init_per_testcase('__default__',Config); @@ -350,9 +350,9 @@ erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) -> {skip, "no ~/.ssh/id_dsa"} end. %%-------------------------------------------------------------------- -erlang_server_openssh_client_pulic_key_dsa() -> +erlang_server_openssh_client_public_key_dsa() -> [{doc, "Validate using dsa publickey."}]. -erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) -> +erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), KnownHosts = filename:join(PrivDir, "known_hosts"), -- cgit v1.2.3 From 3c7c228a2889e0c83291d99ad45acea7756ded0f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 26 Oct 2015 12:45:14 +0100 Subject: ssh: Adjust the test ssh_renegotiate_SUITE:rekey_limit - Remove random length padding to make the data volume deterministic - Increase data volume limit for re-keying because the kexinit message has grown --- lib/ssh/test/ssh_renegotiate_SUITE.erl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl index 9daa6efc02..ef631d54bd 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE.erl +++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl @@ -89,9 +89,10 @@ rekey_limit(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "rekey.data"), - {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 4500}]), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 6000}, + {max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), @@ -132,13 +133,13 @@ renegotiate1(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate1.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), @@ -170,12 +171,12 @@ renegotiate2(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate2.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), -- cgit v1.2.3 From 30a4adb7d4b534a512a717244ebaeb29c78cddc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 29 Sep 2015 13:59:47 +0200 Subject: epp_SUITE: Add smoke and coverage test of format_error/1 --- lib/stdlib/test/epp_SUITE.erl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 4e5df661b3..2ac2316ce9 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -1528,8 +1528,11 @@ compile_test(Config, Test0) -> warnings(File, Ws) -> case lists:append([W || {F, W} <- Ws, F =:= File]) of - [] -> []; - L -> {warnings, L} + [] -> + []; + L -> + call_format_error(L), + {warnings, L} end. compile_file(File, Opts) -> @@ -1540,12 +1543,20 @@ compile_file(File, Opts) -> end. errs([{File,Es}|L], File) -> + call_format_error(Es), Es ++ errs(L, File); errs([_|L], File) -> errs(L, File); errs([], _File) -> []. +%% Smoke test and coverage of format_error/1. +call_format_error([{_,M,E}|T]) -> + _ = M:format_error(E), + call_format_error(T); +call_format_error([]) -> + ok. + epp_parse_file(File, Opts) -> case epp:parse_file(File, Opts) of {ok, Forms} -> -- cgit v1.2.3 From a657f1f5e4d1d520865497fc0421ebd5f43ca70d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 29 Oct 2015 16:03:36 +0100 Subject: epp_SUITE: Avoid hard-coding list of macros more than once --- lib/stdlib/test/epp_SUITE.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 2ac2316ce9..199d2f193d 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -826,14 +826,14 @@ otp_8130(Config) when is_list(Config) -> "-define(a, 3.14).\n" "t() -> ?a.\n"), ?line {ok,Epp} = epp:open(File, []), - ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE', - 'MACHINE','MODULE','MODULE_STRING'] = macs(Epp), + PreDefMacs = macs(Epp), + ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE', + 'MACHINE','MODULE','MODULE_STRING'] = PreDefMacs, ?line {ok,[{'-',_},{atom,_,file}|_]} = epp:scan_erl_form(Epp), ?line {ok,[{'-',_},{atom,_,module}|_]} = epp:scan_erl_form(Epp), ?line {ok,[{atom,_,t}|_]} = epp:scan_erl_form(Epp), ?line {eof,_} = epp:scan_erl_form(Epp), - ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE', - 'MACHINE','MODULE','MODULE_STRING',a] = macs(Epp), + [a] = macs(Epp) -- PreDefMacs, ?line epp:close(Epp), %% escript -- cgit v1.2.3 From 5066ac923c1dbaa90d63e39b52b60f883284a8ad Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 24 Sep 2015 13:43:32 +0200 Subject: hipe/dialyzer: Remove functions from erl_bif_types --- lib/dialyzer/test/small_SUITE_data/results/bif1 | 3 + .../test/small_SUITE_data/src/bif1/bif1.erl | 16 ++++ .../test/small_SUITE_data/src/bif1/bif1_adt.erl | 12 +++ lib/hipe/cerl/erl_bif_types.erl | 89 ---------------------- 4 files changed, 31 insertions(+), 89 deletions(-) create mode 100644 lib/dialyzer/test/small_SUITE_data/results/bif1 create mode 100644 lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl create mode 100644 lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl (limited to 'lib') diff --git a/lib/dialyzer/test/small_SUITE_data/results/bif1 b/lib/dialyzer/test/small_SUITE_data/results/bif1 new file mode 100644 index 0000000000..289b6f821f --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/bif1 @@ -0,0 +1,3 @@ + +bif1.erl:13: Function string_chars/0 has no local return +bif1.erl:16: The call string:chars(S::65,10,L2::bif1_adt:s()) contains an opaque term as 3rd argument when terms of different types are expected in these positions diff --git a/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl new file mode 100644 index 0000000000..bc746538d3 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl @@ -0,0 +1,16 @@ +-module(bif1). + +%% Other set of warnings due to removed of functions from +%% erl_bif_types. + +-export([ets_rename/0, string_chars/0]). + +ets_rename() -> + A = ets:new(fipp, []), + true = not is_atom(A), + ets:rename(A, fopp). % No warning + +string_chars() -> + L2 = bif1_adt:opaque_string(), + S = $A, + string:chars(S, 10, L2). % Warning diff --git a/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl new file mode 100644 index 0000000000..01b0bccc68 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl @@ -0,0 +1,12 @@ +-module(bif1_adt). + +-export([opaque_string/0]). + +-export_type([s/0]). + +-opaque s() :: string(). + +-spec opaque_string() -> s(). + +opaque_string() -> + "string". diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index c92a4f2c78..622c235638 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -46,7 +46,6 @@ t_bitstr/0, t_boolean/0, t_byte/0, - t_char/0, t_cons/0, t_cons/2, t_cons_hd/1, @@ -87,7 +86,6 @@ t_is_port/2, t_is_maybe_improper_list/2, t_is_reference/2, - t_is_string/1, t_is_subtype/2, t_is_tuple/2, t_list/0, @@ -552,9 +550,6 @@ type(erlang, bit_size, 1, Xs, Opaques) -> type(erlang, byte_size, 1, Xs, Opaques) -> strict(erlang, byte_size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); -type(erlang, disconnect_node, 1, Xs, Opaques) -> - strict(erlang, disconnect_node, 1, Xs, - fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end, Opaques); %% Guard bif, needs to be here. %% Also much more expressive than anything you could write in a spec... type(erlang, element, 2, Xs, Opaques) -> @@ -583,16 +578,9 @@ type(erlang, element, 2, Xs, Opaques) -> %% Guard bif, needs to be here. type(erlang, float, 1, Xs, Opaques) -> strict(erlang, float, 1, Xs, fun (_) -> t_float() end, Opaques); -type(erlang, fun_info, 1, Xs, Opaques) -> - strict(erlang, fun_info, 1, Xs, - fun (_) -> t_list(t_tuple([t_atom(), t_any()])) end, Opaques); -type(erlang, get_cookie, 0, _, _Opaques) -> t_atom(); % | t_atom('nocookie') %% Guard bif, needs to be here. type(erlang, hd, 1, Xs, Opaques) -> strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques); -type(erlang, integer_to_list, 2, Xs, Opaques) -> - strict(erlang, integer_to_list, 2, Xs, - fun (_) -> t_string() end, Opaques); type(erlang, info, 1, Xs, _) -> type(erlang, system_info, 1, Xs); % alias %% All type tests are guard BIF's and may be implemented in ways that %% cannot be expressed in a type spec, why they are kept in erl_bif_types. @@ -796,8 +784,6 @@ type(erlang, make_tuple, 3, Xs, Opaques) -> _Other -> t_tuple() end end, Opaques); -type(erlang, memory, 0, _, _Opaques) -> - t_list(t_tuple([t_atom(), t_non_neg_fixnum()])); type(erlang, nif_error, 1, Xs, Opaques) -> %% this BIF and the next one are stubs for NIFs and never return strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end, Opaques); @@ -813,8 +799,6 @@ type(erlang, round, 1, Xs, Opaques) -> strict(erlang, round, 1, Xs, fun (_) -> t_integer() end, Opaques); %% Guard bif, needs to be here. type(erlang, self, 0, _, _Opaques) -> t_pid(); -type(erlang, set_cookie, 2, Xs, Opaques) -> - strict(erlang, set_cookie, 2, Xs, fun (_) -> t_atom('true') end, Opaques); type(erlang, setelement, 3, Xs, Opaques) -> strict(erlang, setelement, 3, Xs, fun ([X1, X2, X3]) -> @@ -849,19 +833,7 @@ type(erlang, setelement, 3, Xs, Opaques) -> %% Guard bif, needs to be here. type(erlang, size, 1, Xs, Opaques) -> strict(erlang, size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); -type(erlang, spawn, 1, Xs, Opaques) -> - strict(erlang, spawn, 1, Xs, fun (_) -> t_pid() end, Opaques); -type(erlang, spawn, 2, Xs, Opaques) -> - strict(erlang, spawn, 2, Xs, fun (_) -> t_pid() end, Opaques); -type(erlang, spawn, 4, Xs, Opaques) -> - strict(erlang, spawn, 4, Xs, fun (_) -> t_pid() end, Opaques); -type(erlang, spawn_link, 1, Xs, _) -> type(erlang, spawn, 1, Xs); % same -type(erlang, spawn_link, 2, Xs, _) -> type(erlang, spawn, 2, Xs); % same -type(erlang, spawn_link, 4, Xs, _) -> type(erlang, spawn, 4, Xs); % same type(erlang, subtract, 2, Xs, _Opaques) -> type(erlang, '--', 2, Xs); % alias -type(erlang, suspend_process, 1, Xs, Opaques) -> - strict(erlang, suspend_process, 1, Xs, - fun (_) -> t_atom('true') end, Opaques); type(erlang, system_info, 1, Xs, Opaques) -> strict(erlang, system_info, 1, Xs, fun ([Type]) -> @@ -1014,10 +986,6 @@ type(erlang, tuple_to_list, 1, Xs, Opaques) -> end end end, Opaques); -type(erlang, yield, 0, _, _Opaques) -> t_atom('true'); -%%-- ets ---------------------------------------------------------------------- -type(ets, rename, 2, Xs, Opaques) -> - strict(ets, rename, 2, Xs, fun ([_, Name]) -> Name end, Opaques); %%-- hipe_bifs ---------------------------------------------------------------- type(hipe_bifs, add_ref, 2, Xs, Opaques) -> strict(hipe_bifs, add_ref, 2, Xs, fun (_) -> t_nil() end, Opaques); @@ -1677,25 +1645,6 @@ type(lists, zipwith3, 4, Xs, Opaques) -> fun ([F,_As,_Bs,_Cs]) -> t_sup(t_list(t_fun_range(F, Opaques)), t_nil()) end, Opaques); -%%-- string ------------------------------------------------------------------- -type(string, chars, 2, Xs, Opaques) -> % NOTE: added to avoid loss of info - strict(string, chars, 2, Xs, fun (_) -> t_string() end, Opaques); -type(string, chars, 3, Xs, Opaques) -> % NOTE: added to avoid loss of info - strict(string, chars, 3, Xs, - fun ([Char, N, Tail]) -> - case t_is_nil(Tail) of - true -> - type(string, chars, 2, [Char, N]); - false -> - case t_is_string(Tail) of - true -> - t_string(); - false -> - t_sup(t_sup(t_string(), Tail), t_cons(Char, Tail)) - end - end - end, Opaques); - %%----------------------------------------------------------------------------- type(M, F, A, Xs, _O) when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 -> @@ -2300,8 +2249,6 @@ arg_types(erlang, bit_size, 1) -> %% Guard bif, needs to be here. arg_types(erlang, byte_size, 1) -> [t_binary()]; -arg_types(erlang, disconnect_node, 1) -> - [t_node()]; arg_types(erlang, halt, 0) -> []; arg_types(erlang, halt, 1) -> @@ -2321,17 +2268,11 @@ arg_types(erlang, element, 2) -> %% Guard bif, needs to be here. arg_types(erlang, float, 1) -> [t_number()]; -arg_types(erlang, fun_info, 1) -> - [t_fun()]; -arg_types(erlang, get_cookie, 0) -> - []; %% Guard bif, needs to be here. arg_types(erlang, hd, 1) -> [t_cons()]; arg_types(erlang, info, 1) -> arg_types(erlang, system_info, 1); % alias -arg_types(erlang, integer_to_list, 2) -> - [t_integer(), t_from_range(2, 36)]; arg_types(erlang, is_atom, 1) -> [t_any()]; arg_types(erlang, is_binary, 1) -> @@ -2378,8 +2319,6 @@ arg_types(erlang, make_tuple, 2) -> [t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument arg_types(erlang, make_tuple, 3) -> [t_non_neg_fixnum(), t_any(), t_list(t_tuple([t_pos_integer(), t_any()]))]; -arg_types(erlang, memory, 0) -> - []; arg_types(erlang, nif_error, 1) -> [t_any()]; arg_types(erlang, nif_error, 2) -> @@ -2396,29 +2335,13 @@ arg_types(erlang, round, 1) -> %% Guard bif, needs to be here. arg_types(erlang, self, 0) -> []; -arg_types(erlang, set_cookie, 2) -> - [t_node(), t_atom()]; arg_types(erlang, setelement, 3) -> [t_pos_integer(), t_tuple(), t_any()]; %% Guard bif, needs to be here. arg_types(erlang, size, 1) -> [t_sup(t_tuple(), t_binary())]; -arg_types(erlang, spawn, 1) -> %% TODO: Tuple? - [t_fun()]; -arg_types(erlang, spawn, 2) -> %% TODO: Tuple? - [t_node(), t_fun()]; -arg_types(erlang, spawn, 4) -> %% TODO: Tuple? - [t_node(), t_atom(), t_atom(), t_list()]; -arg_types(erlang, spawn_link, 1) -> - arg_types(erlang, spawn, 1); % same -arg_types(erlang, spawn_link, 2) -> - arg_types(erlang, spawn, 2); % same -arg_types(erlang, spawn_link, 4) -> - arg_types(erlang, spawn, 4); % same arg_types(erlang, subtract, 2) -> arg_types(erlang, '--', 2); -arg_types(erlang, suspend_process, 1) -> - [t_pid()]; arg_types(erlang, system_info, 1) -> [t_sup([t_atom(), % documented t_tuple([t_atom(), t_any()]), % documented @@ -2437,11 +2360,6 @@ arg_types(erlang, tuple_size, 1) -> [t_tuple()]; arg_types(erlang, tuple_to_list, 1) -> [t_tuple()]; -arg_types(erlang, yield, 0) -> - []; -%%------- ets ----------------------------------------------------------------- -arg_types(ets, rename, 2) -> - [t_atom(), t_atom()]; %%------- hipe_bifs ----------------------------------------------------------- arg_types(hipe_bifs, add_ref, 2) -> [t_mfa(), t_tuple([t_mfa(), @@ -2638,13 +2556,6 @@ arg_types(lists, zipwith, 3) -> [t_fun([t_any(), t_any()], t_any()), t_list(), t_list()]; arg_types(lists, zipwith3, 4) -> [t_fun([t_any(), t_any(), t_any()], t_any()), t_list(), t_list(), t_list()]; - -%%------- string -------------------------------------------------------------- -arg_types(string, chars, 2) -> - [t_char(), t_non_neg_integer()]; -arg_types(string, chars, 3) -> - [t_char(), t_non_neg_integer(), t_any()]; -%%----------------------------------------------------------------------------- arg_types(M, F, A) when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 -> unknown. % safe approximation for all functions. -- cgit v1.2.3 From 5483c81d3093830dbcc132bfb1426c59ed2a8e57 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 5 Oct 2015 09:22:24 +0200 Subject: runtime_tools: Explain that dbg:stop only clears local trace patterns --- lib/runtime_tools/doc/src/dbg.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml index d31ccd834d..5daf2c4940 100644 --- a/lib/runtime_tools/doc/src/dbg.xml +++ b/lib/runtime_tools/doc/src/dbg.xml @@ -1028,9 +1028,9 @@ hello Stop the dbgserver and the tracing of all processes.

Stops the dbg server and clears all trace flags for - all processes and all trace patterns for all functions. Also + all processes and all local trace patterns for all functions. Also shuts down all trace clients and closes all trace ports.

-

Note that no trace patterns are affected by this +

Note that no global trace patterns are affected by this function.

@@ -1038,8 +1038,7 @@ hello stop_clear() -> ok Stop the dbgserver and the tracing of all processes, and clears trace patterns. -

Same as stop/0, but also clears all trace patterns on local - and global functions calls.

+

Same as stop/0, but also clears all trace patterns on global functions calls.

-- cgit v1.2.3 From a541756c4ab173a63969f1789f82b56d22b00fa2 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 2 Nov 2015 17:14:00 +0100 Subject: ssh: Make tests for bad packet_len and field lengths inside packets Includes a ssh_transport:pack/3 function for generating invalid packets --- lib/ssh/src/ssh_transport.erl | 13 +++++-- lib/ssh/test/ssh_protocol_SUITE.erl | 68 ++++++++++++++++++++++++++++++++++++- lib/ssh/test/ssh_trpt_test_lib.erl | 9 ++++- 3 files changed, 85 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 8b65806dc6..d622ec27fc 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -45,7 +45,7 @@ handle_kex_ecdh_init/2, handle_kex_ecdh_reply/2, extract_public_key/1, - unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1, + unpack/3, decompress/2, ssh_packet/2, pack/2, pack/3, msg_data/1, sign/3, verify/4]). %%%---------------------------------------------------------------------------- @@ -929,11 +929,18 @@ ssh_packet(Msg, Ssh) -> BinMsg = ssh_message:encode(Msg), pack(BinMsg, Ssh). +pack(Data, Ssh=#ssh{}) -> + pack(Data, Ssh, 0). + +%%% Note: pack/3 is only to be called from tests that wants +%%% to deliberetly send packets with wrong PacketLength! +%%% Use pack/2 for all other purposes! pack(Data0, #ssh{encrypt_block_size = BlockSize, send_sequence = SeqNum, send_mac = MacAlg, send_mac_key = MacKey, random_length_padding = RandomLengthPadding} - = Ssh0) when is_binary(Data0) -> + = Ssh0, + PacketLenDeviationForTests) when is_binary(Data0) -> {Ssh1, Data} = compress(Ssh0, Data0), PL = (BlockSize - ((4 + 1 + size(Data)) rem BlockSize)) rem BlockSize, MinPaddingLen = if PL < 4 -> PL + BlockSize; @@ -946,7 +953,7 @@ pack(Data0, #ssh{encrypt_block_size = BlockSize, end, PaddingLen = MinPaddingLen + ExtraPaddingLen, Padding = ssh_bits:random(PaddingLen), - PacketLen = 1 + PaddingLen + size(Data), + PacketLen = 1 + PaddingLen + size(Data) + PacketLenDeviationForTests, PacketData = <>, {Ssh2, EncPacket} = encrypt(Ssh1, PacketData), diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 03c2ce53cb..b84ccac885 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -47,7 +47,9 @@ suite() -> all() -> [{group,tool_tests}, {group,kex}, - {group,service_requests} + {group,service_requests}, + {group,packet_size_error}, + {group,field_size_error} ]. groups() -> @@ -56,6 +58,12 @@ groups() -> lib_match, lib_no_match ]}, + {packet_size_error, [], [packet_length_too_large, + packet_length_too_short]}, + + {field_size_error, [], [service_name_length_too_large, + service_name_length_too_short]}, + {kex, [], [no_common_alg_server_disconnects, no_common_alg_client_disconnects, gex_client_init_default_noexact, @@ -409,6 +417,64 @@ bad_service_name(Config, Name) -> receive_msg} ], InitialState). +%%%-------------------------------------------------------------------- +packet_length_too_large(Config) -> bad_packet_length(Config, +4). + +packet_length_too_short(Config) -> bad_packet_length(Config, -4). + +bad_packet_length(Config, LengthExcess) -> + PacketFun = + fun(Msg, Ssh) -> + BinMsg = ssh_message:encode(Msg), + ssh_transport:pack(BinMsg, Ssh, LengthExcess) + end, + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, {special, + #ssh_msg_service_request{name="ssh-userauth"}, + PacketFun}}, + %% Prohibit remote decoder starvation: + {send, #ssh_msg_service_request{name="ssh-userauth"}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + +%%%-------------------------------------------------------------------- +service_name_length_too_large(Config) -> bad_service_name_length(Config, +4). + +service_name_length_too_short(Config) -> bad_service_name_length(Config, -4). + + +bad_service_name_length(Config, LengthExcess) -> + PacketFun = + fun(#ssh_msg_service_request{name=Service}, Ssh) -> + BinName = list_to_binary(Service), + BinMsg = + <>, + ssh_transport:pack(BinMsg, Ssh) + end, + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, {special, + #ssh_msg_service_request{name="ssh-userauth"}, + PacketFun} }, + %% Prohibit remote decoder starvation: + {send, #ssh_msg_service_request{name="ssh-userauth"}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl index 5080b33249..4269529ae8 100644 --- a/lib/ssh/test/ssh_trpt_test_lib.erl +++ b/lib/ssh/test/ssh_trpt_test_lib.erl @@ -386,7 +386,14 @@ send(S0, Line) when is_binary(Line) -> fun(X) when X==true;X==detail -> {"Send line~n~p~n",[Line]} end), send_bytes(Line, S#s{return_value = Line}); -%%% Msg = #ssh_msg_*{} +send(S0, {special,Msg,PacketFun}) when is_tuple(Msg), + is_function(PacketFun,2) -> + S = opt(print_messages, S0, + fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), + {Packet, C} = PacketFun(Msg, S#s.ssh), + send_bytes(Packet, S#s{ssh = C, %%inc_send_seq_num(C), + return_value = Msg}); + send(S0, Msg) when is_tuple(Msg) -> S = opt(print_messages, S0, fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end), -- cgit v1.2.3 From b9dde77481d2f6ae988118a79abd06b134129075 Mon Sep 17 00:00:00 2001 From: Gary Coulbourne Date: Thu, 15 Oct 2015 15:04:06 -0400 Subject: Fix spelling error in "characters_to_list" --- lib/stdlib/doc/src/unicode.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml index 19ddf1cbd6..966eec49f5 100644 --- a/lib/stdlib/doc/src/unicode.xml +++ b/lib/stdlib/doc/src/unicode.xml @@ -133,7 +133,7 @@ latin1, or have characters encoded as one of the UTF-encodings, which is given as the InEncoding parameter. Only when the InEncoding is one of the UTF - encodings, integers in the list are allowed to be grater than + encodings, integers in the list are allowed to be greater than 255.

If InEncoding is latin1, the Data parameter -- cgit v1.2.3 From 9b44b2f8300ddee82e5a021570066042ea08e681 Mon Sep 17 00:00:00 2001 From: Sergey Savenko Date: Fri, 30 Oct 2015 15:07:22 +0300 Subject: OtpInputStream: external fun terms in read_any() Term tag matching switch statement was missing external fun tag. --- lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java index 35280f9571..fa0815fbf0 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java @@ -1243,6 +1243,9 @@ public class OtpInputStream extends ByteArrayInputStream { case OtpExternal.funTag: return new OtpErlangFun(this); + case OtpExternal.externalFunTag: + return new OtpErlangExternalFun(this); + default: throw new OtpErlangDecodeException("Uknown data type: " + tag); } -- cgit v1.2.3 From c505918a86fb9ac8c19e47cd751a9db4e2d9efb2 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 29 Oct 2015 19:51:04 +0100 Subject: ssh: pwdfun/4 and simple tests Also solves OTP-13053 --- lib/ssh/src/ssh.erl | 4 +- lib/ssh/src/ssh.hrl | 1 + lib/ssh/src/ssh_auth.erl | 49 +++++++---- lib/ssh/test/ssh_options_SUITE.erl | 161 ++++++++++++++++++++++++++++++++++++- 4 files changed, 199 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 049018b21c..6f79b48091 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -462,7 +462,9 @@ handle_ssh_option({password, Value} = Opt) when is_list(Value) -> Opt; handle_ssh_option({user_passwords, Value} = Opt) when is_list(Value)-> Opt; -handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value) -> +handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,2) -> + Opt; +handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,4) -> Opt; handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) -> Opt; diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index fc9d60c500..4ad936f742 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -138,6 +138,7 @@ kb_tries_left = 0, % integer(), num tries left for "keyboard-interactive" userauth_preference, available_host_keys, + pwdfun_user_state, authenticated = false }). diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 04749fcf8e..4272eb3c52 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -174,15 +174,15 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User, #ssh{opts = Opts, userauth_supported_methods = Methods} = Ssh) -> Password = unicode:characters_to_list(BinPwd), - case check_password(User, Password, Opts) of - true -> + case check_password(User, Password, Opts, Ssh) of + {true,Ssh1} -> {authorized, User, - ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false -> + ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh1)}; + {false,Ssh1} -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, - partial_success = false}, Ssh)} + partial_success = false}, Ssh1)} end; handle_userauth_request(#ssh_msg_userauth_request{user = User, @@ -335,16 +335,16 @@ handle_userauth_info_response(#ssh_msg_userauth_info_response{num_responses = 1, kb_tries_left = KbTriesLeft, user = User, userauth_supported_methods = Methods} = Ssh) -> - case check_password(User, unicode:characters_to_list(Password), Opts) of - true -> + case check_password(User, unicode:characters_to_list(Password), Opts, Ssh) of + {true,Ssh1} -> {authorized, User, - ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)}; - false -> + ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh1)}; + {false,Ssh1} -> {not_authorized, {User, {error,"Bad user or password"}}, ssh_transport:ssh_packet(#ssh_msg_userauth_failure{ authentications = Methods, partial_success = false}, - Ssh#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} + Ssh1#ssh{kb_tries_left = max(KbTriesLeft-1, 0)} )} end; @@ -387,13 +387,34 @@ user_name(Opts) -> {ok, User} end. -check_password(User, Password, Opts) -> +check_password(User, Password, Opts, Ssh) -> case proplists:get_value(pwdfun, Opts) of undefined -> Static = get_password_option(Opts, User), - Password == Static; - Cheker -> - Cheker(User, Password) + {Password == Static, Ssh}; + + Checker when is_function(Checker,2) -> + {Checker(User, Password), Ssh}; + + Checker when is_function(Checker,4) -> + #ssh{pwdfun_user_state = PrivateState, + peer = {_,PeerAddr={_,_}} + } = Ssh, + case Checker(User, Password, PeerAddr, PrivateState) of + true -> + {true,Ssh}; + false -> + {false,Ssh}; + {true,NewState} -> + {true, Ssh#ssh{pwdfun_user_state=NewState}}; + {false,NewState} -> + {false, Ssh#ssh{pwdfun_user_state=NewState}}; + disconnect -> + throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, + description = + "Unable to connect using the available authentication methods", + language = ""}) + end end. get_password_option(Opts, User) -> diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index cf15ca4253..6a201d401f 100644 --- a/lib/ssh/test/ssh_options_SUITE.erl +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -45,6 +45,9 @@ max_sessions_ssh_connect_sequential/1, server_password_option/1, server_userpassword_option/1, + server_pwdfun_option/1, + server_pwdfun_4_option/1, + server_pwdfun_4_option_repeat/1, ssh_connect_arg4_timeout/1, ssh_connect_negtimeout_parallel/1, ssh_connect_negtimeout_sequential/1, @@ -83,6 +86,9 @@ all() -> connectfun_disconnectfun_client, server_password_option, server_userpassword_option, + server_pwdfun_option, + server_pwdfun_4_option, + server_pwdfun_4_option_repeat, {group, dir_options}, ssh_connect_timeout, ssh_connect_arg4_timeout, @@ -188,7 +194,9 @@ init_per_testcase(_TestCase, Config) -> Config. end_per_testcase(TestCase, Config) when TestCase == server_password_option; - TestCase == server_userpassword_option -> + TestCase == server_userpassword_option; + TestCase == server_pwdfun_option; + TestCase == server_pwdfun_4_option -> UserDir = filename:join(?config(priv_dir, Config), nopubkey), ssh_test_lib:del_dirs(UserDir), end_per_testcase(Config); @@ -271,6 +279,157 @@ server_userpassword_option(Config) when is_list(Config) -> {user_dir, UserDir}]), ssh:stop_daemon(Pid). +%%-------------------------------------------------------------------- +%%% validate to server that uses the 'pwdfun' option +server_pwdfun_option(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + CHKPWD = fun("foo",Pwd) -> Pwd=="bar"; + (_,_) -> false + end, + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, PrivDir}, + {pwdfun,CHKPWD}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "bar"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:close(ConnectionRef), + + Reason = "Unable to connect using the available authentication methods", + + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:stop_daemon(Pid). + + +%%-------------------------------------------------------------------- +%%% validate to server that uses the 'pwdfun/4' option +server_pwdfun_4_option(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + PWDFUN = fun("foo",Pwd,{_,_},undefined) -> Pwd=="bar"; + ("fie",Pwd,{_,_},undefined) -> {Pwd=="bar",new_state}; + ("bandit",_,_,_) -> disconnect; + (_,_,_,_) -> false + end, + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, PrivDir}, + {pwdfun,PWDFUN}]), + ConnectionRef1 = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "bar"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:close(ConnectionRef1), + + ConnectionRef2 = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "fie"}, + {password, "bar"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:close(ConnectionRef2), + + Reason = "Unable to connect using the available authentication methods", + + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "fie"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "vego"}, + {password, "foo"}, + {user_interaction, false}, + {user_dir, UserDir}]), + + {error, Reason} = + ssh:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "bandit"}, + {password, "pwd breaking"}, + {user_interaction, false}, + {user_dir, UserDir}]), + ssh:stop_daemon(Pid). + + +%%-------------------------------------------------------------------- +server_pwdfun_4_option_repeat(Config) -> + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), + %% Test that the state works + Parent = self(), + PWDFUN = fun("foo",P="bar",_,S) -> Parent!{P,S},true; + (_,P,_,S=undefined) -> Parent!{P,S},{false,1}; + (_,P,_,S) -> Parent!{P,S}, {false,S+1} + end, + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, PrivDir}, + {auth_methods,"keyboard-interactive"}, + {pwdfun,PWDFUN}]), + + %% Try with passwords "incorrect", "Bad again" and finally "bar" + KIFFUN = fun(_,_,_) -> + K={k,self()}, + case get(K) of + undefined -> + put(K,1), + ["incorrect"]; + 2 -> + put(K,3), + ["bar"]; + S-> + put(K,S+1), + ["Bad again"] + end + end, + + ConnectionRef2 = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user, "foo"}, + {keyboard_interact_fun, KIFFUN}, + {user_dir, UserDir}]), + ssh:close(ConnectionRef2), + ssh:stop_daemon(Pid), + + lists:foreach(fun(Expect) -> + receive + Expect -> ok; + Other -> ct:fail("Expect: ~p~nReceived ~p",[Expect,Other]) + after + 2000 -> ct:fail("Timeout expecting ~p",[Expect]) + end + end, [{"incorrect",undefined}, + {"Bad again",1}, + {"bar",2}]). + %%-------------------------------------------------------------------- system_dir_option(Config) -> DirUnread = proplists:get_value(unreadable_dir,Config), -- cgit v1.2.3 From 193ccf4009eb346ca5dd43679b219e395016b03d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 30 Oct 2015 11:33:40 +0100 Subject: ssh: enable users to give option keyboard_interact_fun It is on purpose not documented. It needs more thinking before being finalized. --- lib/ssh/src/ssh.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 6f79b48091..693b55a09e 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -337,6 +337,8 @@ handle_option([{pwdfun, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{key_cb, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{keyboard_interact_fun, _} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); %%Backwards compatibility handle_option([{allow_user_interaction, Value} | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option({user_interaction, Value}) | SshOptions]); @@ -468,6 +470,8 @@ handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,4) -> Opt; handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) -> Opt; +handle_ssh_option({keyboard_interact_fun, Value} = Opt) when is_function(Value,3) -> + Opt; handle_ssh_option({compression, Value} = Opt) when is_atom(Value) -> Opt; handle_ssh_option({exec, {Module, Function, _}} = Opt) when is_atom(Module), -- cgit v1.2.3 From 17517fb5ef4e9e7e6913a6eb4527f862ede29271 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 30 Oct 2015 12:25:16 +0100 Subject: ssh: make corrections of keyboard-interactive client * Newlines should be added after Name and Instructions field according to rfc4256. * There was an error in the argument list of the last clause of ssh_auth:keyboard_interact_get_responses/9 * Correct client kb-interactive behaviour at auth failure --- lib/ssh/src/ssh_auth.erl | 11 ++++++++--- lib/ssh/src/ssh_connection_handler.erl | 18 ++++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 4272eb3c52..4967a2e4cd 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -364,6 +364,11 @@ method_preference(Algs) -> [{"publickey", ?MODULE, publickey_msg, [A]} | Acc] end, [{"password", ?MODULE, password_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, + {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}, {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []} ], Algs). @@ -472,14 +477,14 @@ keyboard_interact_get_responses(false, undefined, undefined, _, _, _, [Prompt|_] ssh_no_io:read_line(Prompt, Opts); %% Throws error as keyboard interaction is not allowed keyboard_interact_get_responses(true, undefined, _,IoCb, Name, Instr, PromptInfos, Opts, _) -> keyboard_interact(IoCb, Name, Instr, PromptInfos, Opts); -keyboard_interact_get_responses(true, Fun, _, Name, Instr, PromptInfos, _, _, NumPrompts) -> +keyboard_interact_get_responses(true, Fun, _Pwd, _IoCb, Name, Instr, PromptInfos, _Opts, NumPrompts) -> keyboard_interact_fun(Fun, Name, Instr, PromptInfos, NumPrompts). keyboard_interact(IoCb, Name, Instr, Prompts, Opts) -> - if Name /= "" -> IoCb:format("~s", [Name]); + if Name /= "" -> IoCb:format("~s~n", [Name]); true -> ok end, - if Instr /= "" -> IoCb:format("~s", [Instr]); + if Instr /= "" -> IoCb:format("~s~n", [Instr]); true -> ok end, lists:map(fun({Prompt, true}) -> IoCb:read_line(Prompt, Opts); diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 7fb86c1108..a2d1b5b810 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -627,14 +627,24 @@ userauth_keyboard_interactive(#ssh_msg_userauth_info_response{} = Msg, retry_fun(User, Address, Reason, Opts), send_msg(Reply, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} - end. - + end; +userauth_keyboard_interactive(Msg = #ssh_msg_userauth_failure{}, + #state{ssh_params = Ssh0 = + #ssh{role = client, + userauth_preference = Prefs0}} + = State) -> + Prefs = [{Method,M,F,A} || {Method,M,F,A} <- Prefs0, + Method =/= "keyboard-interactive"], + userauth(Msg, State#state{ssh_params = Ssh0#ssh{userauth_preference=Prefs}}). + -userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_failure{}, State) -> +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_failure{}, + #state{ssh_params = #ssh{role = client}} = State) -> userauth(Msg, State); -userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_success{}, State) -> +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_success{}, + #state{ssh_params = #ssh{role = client}} = State) -> userauth(Msg, State). %%-------------------------------------------------------------------- -- cgit v1.2.3 From 53bfbb61333af35cde29bb786817856925dcedf0 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 2 Nov 2015 13:08:13 +0100 Subject: ssh: Document pwdfun --- lib/ssh/doc/src/ssh.xml | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 2b190c98b6..31a5e71401 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -471,12 +471,43 @@ kex is implicit but public_key is set explicitly.

- boolean()}]]> + boolean()}]]> + +

Provides a function for password validation. This could used for calling an external system or if + passwords should be stored as a hash. The fun returns: + + true if the user and password is valid and + false otherwise. + +

+

This fun can also be used to make delays in authentication tries for example by calling + timer:sleep/1. To facilitate counting of failed tries + the State variable could be used. This state is per connection only. The first time the pwdfun + is called for a connection, the State variable has the value undefined. + The pwdfun can return - in addition to the values above - a new state + as: + + {true, NewState:any()} if the user and password is valid or + {false, NewState:any()} if the user or password is invalid + +

+

A third usage is to block login attempts from a missbehaving peer. The State described above + can be used for this. In addition to the responses above, the following return value is introduced: + + disconnect if the connection should be closed immediately after sending a SSH_MSG_DISCONNECT + message. + +

+
+ + boolean()}]]>

Provides a function for password validation. This function is called with user and password as strings, and returns if the password is valid and otherwise.

+

This option ({pwdfun,fun/2}) is the same as a subset of the previous + ({pwdfun,fun/4}). It is kept for compatibility.

-- cgit v1.2.3 From 19f3eafbb237af7b6a9d81ebbddae19c41418f8b Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 3 Nov 2015 14:53:30 +0100 Subject: ssh: changes after doc review --- lib/ssh/doc/src/ssh.xml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 31a5e71401..f530a68dd9 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -60,6 +60,29 @@
+
+ OPTIONS +

The exact behaviour of some functions can be adjusted with the use of options which are documented together + with the functions. Generally could each option be used at most one time in each function call. If given two or more + times, the effect is not predictable unless explicitly documented.

+

The options are of different kinds:

+ + Limits +

which alters limits in the system, for example number of simultaneous login attempts.

+ + Timeouts +

which give some defined behaviour if too long time elapses before a given event or action, + for example time to wait for an answer.

+ + Callbacks +

which gives the caller of the function the possibility to execute own code on some events, + for example calling an own logging function or to perform an own login function

+ + Behaviour +

which changes the systems behaviour.

+
+
+
DATA TYPES

Type definitions that are used more than once in @@ -471,7 +494,7 @@ kex is implicit but public_key is set explicitly.

- boolean()}]]> + boolean() | disconnect | {boolean(),any()} }]]>

Provides a function for password validation. This could used for calling an external system or if passwords should be stored as a hash. The fun returns: -- cgit v1.2.3 From c50a9a6562a14f3a9fbd2071e3b19eed8c9c9b4b Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 21 Oct 2015 17:25:42 +0200 Subject: ssh, public_key: random selection of diffie-hellman moduli Also tool (public_key:gen_moduli_hrl) to convert an openssh moduli file to erlang format. --- lib/public_key/doc/src/public_key.xml | 31 +++ lib/public_key/priv/convert.escript | 50 +++++ lib/public_key/priv/generate | 25 +++ lib/public_key/priv/ssh_moduli | 193 +++++++++++++++++ lib/public_key/src/Makefile | 7 +- lib/public_key/src/pubkey_moduli.hrl | 395 ++++++++++++++++++++++++++++++++++ lib/public_key/src/pubkey_ssh.erl | 50 ++++- lib/public_key/src/public_key.erl | 9 + lib/ssh/doc/src/ssh.xml | 2 + lib/ssh/src/ssh.erl | 9 +- lib/ssh/src/ssh_transport.erl | 65 ++---- lib/ssh/src/ssh_transport.hrl | 35 +-- lib/ssh/test/ssh_algorithms_SUITE.erl | 74 +++++-- lib/ssh/test/ssh_protocol_SUITE.erl | 28 +-- 14 files changed, 852 insertions(+), 121 deletions(-) create mode 100755 lib/public_key/priv/convert.escript create mode 100755 lib/public_key/priv/generate create mode 100644 lib/public_key/priv/ssh_moduli create mode 100644 lib/public_key/src/pubkey_moduli.hrl (limited to 'lib') diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index b247618efc..7f68138497 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -299,6 +299,37 @@ + + dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> {ok, {Size,Group}} | {error,Error} + Selects a group for Diffie-Hellman key exchange + + MinSize = positive_integer() + SuggestedSize = positive_integer() + MaxSize = positive_integer() + Groups = undefined | [{Size,[{G,P}]}] + Size = positive_integer() + Group = {G,P} + G = positive_integer() + P = positive_integer() + + +

Selects a group for Diffie-Hellman key exchange with the key size in the range MinSize...MaxSize + and as close to SuggestedSize as possible. If Groups == undefined a default set will be + used, otherwise the group is selected from Groups.

+

First is a size as close as possible to SuggestedSize selected. Then is one group with that key size + randomly selected from the list. If no size within the limits of MinSize and MaxSize is + available, {error,no_group_found} is returned.

+

The default list is in lib/public_key/priv/ssh_moduli. The format is as produced by the openssh tool + ssh-keygen -G followed by ssh-keygen -T. When that list is changed, make should be run in + lib/public_key to make it available for dh_gex_group/4.

+ +

If you change the default ssh_moduli file, be sure to run ssh-keygen -T as described + in the ssh-keygen manual. Failure to do so correctly will compromise the security of applications + relying on this function.

+
+ + + encrypt_private(PlainText, Key) -> binary() Public-key encryption using the private key. diff --git a/lib/public_key/priv/convert.escript b/lib/public_key/priv/convert.escript new file mode 100755 index 0000000000..c7ea48c686 --- /dev/null +++ b/lib/public_key/priv/convert.escript @@ -0,0 +1,50 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +main([InFile,OutFile]) -> + {ok,In} = file:open(InFile,read), + {ok,Out} = file:open(OutFile,write), + write_file(Out, read_file(In)), + file:close(In), + file:close(Out). + +write_file(D, {ok,Ms}) -> + io:format(D,'-define(dh_default_groups,~n ~p~n ).~n',[Ms]). + +one_line(Line, Acc) when is_binary(Line) -> + one_line(binary_to_list(Line), Acc); +one_line("#"++_, Acc) -> + Acc; +one_line(Line, Acc) when is_list(Line) -> + try + [_Time,_Type,_Tests,_Tries,Size,G,P] = string:tokens(Line," \r\n"), + [{list_to_integer(Size), + {list_to_integer(G), list_to_integer(P,16)} + } | Acc] + catch + _:_ -> io:format("*** skip line ~p",[Line]), + Acc + end. + + +collect_per_size(L) -> + lists:foldr( + fun({Sz,GP}, [{Sz,GPs}|Acc]) -> [{Sz,[GP|GPs]}|Acc]; + ({Sz,GP}, Acc) -> [{Sz,[GP]}|Acc] + end, [], lists:sort(L)). + + +read_file(D) -> + read_file(D, []). + +read_file(D, Acc) -> + case io:get_line(D,"") of + {error,Error} -> + {error,Error}; + eof -> + {ok, collect_per_size(Acc)}; + Data -> + read_file(D, one_line(Data,Acc)) + end. + + diff --git a/lib/public_key/priv/generate b/lib/public_key/priv/generate new file mode 100755 index 0000000000..da47e99b91 --- /dev/null +++ b/lib/public_key/priv/generate @@ -0,0 +1,25 @@ +#!/bin/bash + +# Generate ssh moduli files for the sizes in $moduli + +moduli="1024 1536 2048 3072 4096 6144 7168 8192" + +# In arg 1: size +# Out: a file "moduli-$1" (for example: $1=2048 -> file "moduli.2048" +function one_modulus() { + candidates=candidate-$1 + ssh-keygen -G $candidates -b $1 + ssh-keygen -T moduli-$1 -f $candidates + rm $candidates +} + + +# Generate in background +for m in $moduli +do + one_modulus $m & +done + +# When all files moduli-* are generated, do: +# cat moduli-* > ssh_moduli + diff --git a/lib/public_key/priv/ssh_moduli b/lib/public_key/priv/ssh_moduli new file mode 100644 index 0000000000..446f4b8bf4 --- /dev/null +++ b/lib/public_key/priv/ssh_moduli @@ -0,0 +1,193 @@ +20151021104105 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D182EB7 +20151021104106 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D27F94F +20151021104107 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D398EB7 +20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4B850F +20151021104108 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4BF35B +20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5031DF +20151021104109 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5A4933 +20151021104110 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D6434BF +20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D70676B +20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D7235E3 +20151021104113 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D963493 +20151021104114 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DAABAA7 +20151021104115 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DC2E333 +20151021104116 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE16A7B +20151021104117 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE2C5D3 +20151021104118 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DFF382F +20151021104119 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E158F13 +20151021104122 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E4D9FEB +20151021104123 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E5C1FDB +20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9BB69B +20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9F62D3 +20151021104127 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EAA1C27 +20151021104128 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EBC3313 +20151021104129 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EC0733B +20151021104130 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EDB7AD3 +20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF56457 +20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF5A9CF +20151021104133 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9F13CBB3 +20151021104218 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BAAFFDF +20151021104222 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BCB6D93 +20151021104225 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE660BB +20151021104226 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE676C3 +20151021104229 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF3E23B +20151021104230 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF95757 +20151021104241 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C59BEA7 +20151021104242 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6231B3 +20151021104244 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6879BF +20151021104250 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C9B678F +20151021104252 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CA66A4B +20151021104253 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CAB5543 +20151021104256 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CB96933 +20151021104300 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CDA8493 +20151021104308 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D18C0C7 +20151021104310 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D1DA5BF +20151021104318 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D4AB15F +20151021104325 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D7DE42F +20151021104329 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DA03D3B +20151021104335 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DD88BFF +20151021104338 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DE82B5F +20151021104342 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E07AF43 +20151021104343 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E091E6F +20151021104346 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E28B90F +20151021104347 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E2A24F3 +20151021104401 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EB074A7 +20151021104403 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EC01B0F +20151021104406 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED2186F +20151021104407 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED55AAB +20151021104411 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EF58773 +20151021104414 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F0B3267 +20151021104423 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F4DF61B +20151021104434 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F9BBB0B +20151021104442 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17FDD6AFB +20151021104350 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE5E381EF +20151021104414 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE641C193 +20151021104422 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE659F523 +20151021104427 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE660E217 +20151021104438 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6842F73 +20151021104441 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE689683B +20151021104455 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6C41E3B +20151021104512 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE71E3BFF +20151021104525 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75C804F +20151021104527 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75DC48B +20151021104535 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE7738983 +20151021104543 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE787027B +20151021104610 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8075A1B +20151021104625 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE84F79B3 +20151021104628 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE859F617 +20151021104641 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8948E2F +20151021104646 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8A571B3 +20151021104659 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8CEA637 +20151021104705 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E590FF +20151021104707 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E7943F +20151021104731 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE95A975F +20151021104741 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE985F923 +20151021104745 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE996E20B +20151021104806 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE9FACFD7 +20151021104827 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA562C43 +20151021104839 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA8F25E3 +20151021104939 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB1DA0B +20151021104941 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB86153 +20151021105002 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC1B8883 +20151021105019 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC71316F +20151021105035 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECB1D113 +20151021105042 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECC3F3AB +20151021105045 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECCC109B +20151021105101 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED16353B +20151021105106 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED24854F +20151021105109 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED2AE4B3 +20151021105116 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED472CF7 +20151021104612 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E360CD0C3 +20151021104628 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3620FBE7 +20151021104701 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E36490F57 +20151021105014 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E377ACADB +20151021105125 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E37E6DE07 +20151021105320 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E38C2387F +20151021105649 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3A61E46B +20151021105815 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B0A6A4B +20151021105848 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B47D2C3 +20151021105948 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BBBB953 +20151021110011 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BE3B83B +20151021110036 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3C0A3F1B +20151021110201 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB1970F +20151021110208 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB70C2B +20151021110235 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CE4E4DF +20151021110424 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3DB68CD7 +20151021110525 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3E290717 +20151021110655 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3ED6DA83 +20151021110731 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F14C563 +20151021110831 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F85477F +20151021111418 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E420DE56B +20151021111430 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E421DBA2F +20151021111624 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E42F39A93 +20151021111916 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E44302363 +20151021112222 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4585795F +20151021112245 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E45A1DAFF +20151021112339 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4601674F +20151021112437 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46691977 +20151021112521 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46AF3AD3 +20151021112532 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46BCAE97 +20151021112708 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E476520D3 +20151021112724 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E477B3317 +20151021105143 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BA7321EB +20151021105537 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BB3AF34B +20151021105816 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BBC51883 +20151021110444 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BD1A86C7 +20151021111341 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BEDB7BBB +20151021111438 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BF0297AB +20151021111935 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BFF381FF +20151021113820 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C433A1BF +20151021113833 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C43B426B +20151021113900 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45007D3 +20151021113921 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45D8C3B +20151021113941 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4685D5F +20151021114203 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4F95D97 +20151021114417 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C57ED2FF +20151021114645 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C612EC33 +20151021114825 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C67219F7 +20151021114922 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C6A942BB +20151021115945 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C91E14DB +20151021120515 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CA5F5DB3 +20151021120715 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CAD0D497 +20151021121027 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CB8F9D6F +20151021121241 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC0F677F +20151021121518 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC9CC647 +20151021121600 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CCC0ADC3 +20151021121734 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD1BC68B +20151021121759 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD2A7DBF +20151021122003 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CDA3D323 +20151021122542 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CED8D107 +20151021122856 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CF8DFEE7 +20151021123548 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D11CAC4F +20151021123633 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D1426BBB +20151021124201 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D2A62F0B +20151021124454 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D353F0FB +20151021124620 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D3AE526F +20151021125224 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D535C4CB +20151021130254 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D7B5CA43 +20151021111833 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239959D5A7 +20151021112931 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239A078C1B +20151021123021 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239EC676DF +20151021131523 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A2B9FC6B +20151021141029 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A7BD762B +20151021143421 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A9C3EFDF +20151021144912 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB1077AF +20151021145200 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB49943B +20151021145825 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ABE06353 +20151021150910 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ACDA0223 +20151021153131 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AE91738F +20151021154038 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF40D013 +20151021154300 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF75AD97 +20151021155008 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B01C9553 +20151021162240 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B319431B +20151021162649 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B35A3D2B +20151021163640 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B439E263 +20151021171004 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B748B983 +20151021172144 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B8609B5B +20151021173002 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B9021E9F +20151021182612 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23BE0C1EDB +20151021190053 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C120FF97 +20151021192934 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C3BEB637 +20151021113847 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE37347869A3 +20151021133636 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373914ECA3 +20151021140108 2 6 100 8191 5 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373A17959F diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile index 621cedadcd..ca91fd5a4a 100644 --- a/lib/public_key/src/Makefile +++ b/lib/public_key/src/Makefile @@ -50,7 +50,7 @@ MODULES = \ HRL_FILES = $(INCLUDE)/public_key.hrl -INTERNAL_HRL_FILES = +INTERNAL_HRL_FILES = pubkey_moduli.hrl ERL_FILES = $(MODULES:%=%.erl) @@ -86,6 +86,11 @@ ERL_COMPILE_FLAGS += $(PUB_KEY_ERL_FLAGS) \ debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(HRL_FILES) +$(EBIN)/pubkey_ssh.$(EMULATOR): pubkey_moduli.hrl + +pubkey_moduli.hrl: ../priv/ssh_moduli + escript ../priv/convert.escript $< $@ + clean: rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) rm -f core diff --git a/lib/public_key/src/pubkey_moduli.hrl b/lib/public_key/src/pubkey_moduli.hrl new file mode 100644 index 0000000000..e4beecc12a --- /dev/null +++ b/lib/public_key/src/pubkey_moduli.hrl @@ -0,0 +1,395 @@ +-define(dh_default_groups, + [{1023, + [{2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840821904219}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840822843699}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840824293227}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840824411619}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840826770579}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840829698867}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840831699579}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840831788499}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840835116819}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840838791147}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840839741403}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840843908763}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840844149459}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840846037779}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840846316347}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840848087763}, + {2, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840851778483}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840818511543}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840819546447}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840820698807}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840821875983}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840822182367}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840823493823}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840828115623}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840833652783}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840844852263}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840849785943}, + {5, + 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840849803727}]}, + {1535, + [{2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891121581459}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891123347643}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891123353283}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891124232763}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891131462067}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891135933003}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891136255299}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891137177907}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891139347603}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891152305467}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891159084867}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891161343219}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891172563627}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891174672243}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891180467739}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891185564427}, + {2, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891189869307}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891119456223}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891124590423}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891130908327}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891131873727}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891135211407}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891143426247}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891143747007}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891146699103}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891150054447}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891155995647}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891157019487}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891159178863}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891161250063}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891170145447}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891171171087}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891172350063}, + {5, + 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891176092263}]}, + {2047, + [{2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127673160083}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127674746147}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127677513587}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127677855803}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127681703483}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127691773067}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127693199747}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127694475899}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127702886939}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127707613619}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127713247667}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127727962403}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127729070603}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127741606979}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127745340899}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127764392459}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127764820307}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127771318403}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127781167379}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127782355883}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127782887579}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127787746619}, + {2, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127789102259}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127666983407}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127675200023}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127687609343}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127691690063}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127708300823}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127712140847}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127715948087}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127717449983}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127717581887}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127725119327}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127735619543}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127776932207}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127788684623}, + {5, + 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127790955767}]}, + {3071, + [{2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199506260163}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199530244827}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199578944619}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199589988939}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199594013379}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199601609043}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199604230203}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199606755099}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199618079787}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199653718659}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199657776483}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199707657579}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199722711699}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199743456099}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199785339603}, + {2, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199797260499}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199507581927}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199510208343}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199537327623}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199551703167}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199617722127}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199621084383}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199634824407}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199642326807}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199665149823}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199708695087}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199765825887}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199767685887}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199773947727}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199780743543}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199786221207}, + {5, + 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199798706967}]}, + {4095, + [{2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328641094123}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328654189387}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328663242883}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328715041723}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328717604779}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328805204587}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328806565843}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328807451707}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328836115507}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328845968059}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328887178459}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328908234163}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328948166083}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328954136203}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328963052323}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329023777723}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329047093003}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329058480379}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329090057419}, + {2, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329132001859}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328685618887}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328733393407}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328804704703}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328808160607}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328817663383}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328826409727}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328842353143}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328915670167}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328928173423}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328936548223}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328945813063}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328955100607}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328983302407}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328995176167}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329021303887}, + {5, + 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329064403567}]}, + {6143, + [{2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255204878912539}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205024824427}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205108938283}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205168452667}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205178336083}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205194695203}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205234987027}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205249389907}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205299503899}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205303762219}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205318419043}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205369723267}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205388065627}, + {2, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205483192027}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255204867528103}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255204958533343}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205142917087}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205164709807}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205223494543}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205238451607}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205398650527}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205534891927}, + {5, + 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205578782263}]}, + {8191, + [{2, + 938991641448887958659860711024139841840373070892857314837350127283993531354468803860225599873491818506054401963417489724433963777795696041544477412963807403300832656512849715212168703537706302853428971073305304224008208665300028518281475780493382070018498379488833882168221853720545474425047940975435356027594634176129712250061883354535324982741923143373986406603949677080360223989497048086447454366625852264609369284140522273595340921542019308988041920995057608746115976973659704188342646944998285431473302075966106608530908140377765357842459486869512398523240695806503711124427370056638597159539032058092571318621818616699716647464298881944582194013388150591419588422793657857267906072494480713650129757905856314362270238621284311461743652666256381611674809565144562467655186251867429369336740018623120262859220669942243740953355278814789244133782043857008487446798345197999966787658254507117076710455244182794239065255535191498857182705725985655379455993825553257619502588673174759329362518373537685585117537004065137523099625519490356398330532110250061129576411957409731201790054967354938147031111368166150009421041430118523249245874882140875551501824754839814848195806919150975076831338899823813371473496616326897054534509843640848822974414341233324307292275820287661792887177523563243279340678632061899626115667671047274195425889742755327012266774742591229119994211561599405909368902449776535330722644597809098307346948888547387746758109319767106289995123864514603259977184876246412673772519845777697496361969177346826245108557971745523905955370437517039028495325595180934057507336816903052766590118820327869839202378278312909402987412274414739124292902164277499512007446916921747463997761815820546816791093343347969046462095463611789365326128045878985464594892022442144072282717352526544915821855299863549245012366815543939396712522935345161074836470227392836664033041735035699615758782980717425699108612161567924880267630103820215946940542401779795959759774248414245436455737309858403883625882609790799283421857564831362243562647683958370353023343221966296655134926556805244483888769178095889844741765908328185625663202823312608064683035802724504683124396450612201783060593269112984065572954508643688374585823409316161924407053191442613988480926581084892323451281350937867676271858142177713557970909833234285545964647506859724327822527317869059455132036566677244407755994867168874825546516623190701762311472512591018622127119388239627852234680483324150442403}, + {2, + 938991641448887958659860711024139841840373070892857314837350127283993531354468803860225599873491818506054401963417489724433963777795696041544477412963807403300832656512849715212168703537706302853428971073305304224008208665300028518281475780493382070018498379488833882168221853720545474425047940975435356027594634176129712250061883354535324982741923143373986406603949677080360223989497048086447454366625852264609369284140522273595340921542019308988041920995057608746115976973659704188342646944998285431473302075966106608530908140377765357842459486869512398523240695806503711124427370056638597159539032058092571318621818616699716647464298881944582194013388150591419588422793657857267906072494480713650129757905856314362270238621284311461743652666256381611674809565144562467655186251867429369336740018623120262859220669942243740953355278814789244133782043857008487446798345197999966787658254507117076710455244182794239065255535191498857182705725985655379455993825553257619502588673174759329362518373537685585117537004065137523099625519490356398330532110250061129576411957409731201790054967354938147031111368166150009421041430118523249245874882140875551501824754839814848195806919150975076831338899823813371473496616326897054534509843640848822974414341233324307292275820287661792887177523563243279340678632061899626115667671047274195425889742755327012266774742591229119994211561599405909368902449776535330722644597809098307346948888547387746758109319767106289995123864514603259977184876246412673772519845777697496361969177346826245108557971745523905955370437517039028495325595180934057507336816903052766590118820327869839202378278312909402987412274414739124292902164277499512007446916921747463997761815820546816791093343347969046462095463611789365326128045878985464594892022442144072282717352526544915821855299863549245012366815543939396712522935345161074836470227392836664033041735035699615758782980717425699108612161567924880267630103820215946940542401779795959759774248414245436455737309858403883625882609790799283421857564831362243562647683958370353023343221966296655134926556805244483888769178095889844741765908328185625663202823312608064683035802724504683124396450612201783060593269112984065572954508643688374585823409316161924407053191442613988480926581084892323451281350937867676271858142177713557970909833234285545964647506859724327822527317869059455132036566677244407755994867168874825546516623190701762311472512591018622127119388239627852234680483324227808419}, + {5, + 938991641448887958659860711024139841840373070892857314837350127283993531354468803860225599873491818506054401963417489724433963777795696041544477412963807403300832656512849715212168703537706302853428971073305304224008208665300028518281475780493382070018498379488833882168221853720545474425047940975435356027594634176129712250061883354535324982741923143373986406603949677080360223989497048086447454366625852264609369284140522273595340921542019308988041920995057608746115976973659704188342646944998285431473302075966106608530908140377765357842459486869512398523240695806503711124427370056638597159539032058092571318621818616699716647464298881944582194013388150591419588422793657857267906072494480713650129757905856314362270238621284311461743652666256381611674809565144562467655186251867429369336740018623120262859220669942243740953355278814789244133782043857008487446798345197999966787658254507117076710455244182794239065255535191498857182705725985655379455993825553257619502588673174759329362518373537685585117537004065137523099625519490356398330532110250061129576411957409731201790054967354938147031111368166150009421041430118523249245874882140875551501824754839814848195806919150975076831338899823813371473496616326897054534509843640848822974414341233324307292275820287661792887177523563243279340678632061899626115667671047274195425889742755327012266774742591229119994211561599405909368902449776535330722644597809098307346948888547387746758109319767106289995123864514603259977184876246412673772519845777697496361969177346826245108557971745523905955370437517039028495325595180934057507336816903052766590118820327869839202378278312909402987412274414739124292902164277499512007446916921747463997761815820546816791093343347969046462095463611789365326128045878985464594892022442144072282717352526544915821855299863549245012366815543939396712522935345161074836470227392836664033041735035699615758782980717425699108612161567924880267630103820215946940542401779795959759774248414245436455737309858403883625882609790799283421857564831362243562647683958370353023343221966296655134926556805244483888769178095889844741765908328185625663202823312608064683035802724504683124396450612201783060593269112984065572954508643688374585823409316161924407053191442613988480926581084892323451281350937867676271858142177713557970909833234285545964647506859724327822527317869059455132036566677244407755994867168874825546516623190701762311472512591018622127119388239627852234680483324244759967}]}] + ). diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl index 82042550a0..9b281aa482 100644 --- a/lib/public_key/src/pubkey_ssh.erl +++ b/lib/public_key/src/pubkey_ssh.erl @@ -20,8 +20,12 @@ -module(pubkey_ssh). -include("public_key.hrl"). +-include("pubkey_moduli.hrl"). --export([decode/2, encode/2 + +-export([decode/2, encode/2, + dh_gex_group/4, + dh_gex_group_sizes/0 ]). -define(UINT32(X), X:32/unsigned-big-integer). @@ -76,6 +80,50 @@ encode(Entries, Type) -> do_encode(Type, Key, Attributes) end, Entries)). +%%-------------------------------------------------------------------- +-spec dh_gex_group(integer(), integer(), integer(), + undefined | [{integer(),[{integer(),integer()}]}]) -> + {ok,{integer(),{integer(),integer()}}} | {error,any()} . +%% +%% Description: Returns Generator and Modulus given MinSize, WantedSize +%% and MaxSize +%%-------------------------------------------------------------------- +dh_gex_group(Min, N, Max, undefined) -> + dh_gex_group(Min, N, Max, ?dh_default_groups); +dh_gex_group(Min, N, Max, Groups) -> + case select_by_keylen(Min-10, N, Max+10, Groups) of + {ok,{Sz,GPs}} -> + {ok, {Sz,lists:nth(crypto:rand_uniform(1, 1+length(GPs)), GPs)}}; + Other -> + Other + end. + +dh_gex_group_sizes()-> + [KeyLen || {KeyLen,_} <- ?dh_default_groups]. + +%% Select the one with K closest to N but within the interval [Min,Max] + +select_by_keylen(Min, N, Max, [{K,_Gs}|Groups]) when K < Min -> + select_by_keylen(Min, N, Max, Groups); +select_by_keylen(Min, N, Max, [{K,Gs}|Groups]) when K =< Max -> + {ok, select_by_keylen(Min, N, Max, Groups, {K,Gs})}; +select_by_keylen(_Min, _N, _Max, _) -> + {error,no_group_found}. + +select_by_keylen(_Min, _N, Max, [{K,_Gs}|_Groups], GPprev) when K > Max -> + GPprev; +select_by_keylen(Min, N, Max, [{K,Gs}|Groups], {Kprev,GsPrev}) -> + if + N == K -> {K,Gs}; + N > K -> select_by_keylen(Min, N, Max, Groups, {K,Gs}); + N < K, (K-N) < (N-Kprev) -> {K,Gs}; + N < K -> {Kprev,GsPrev} + end; +select_by_keylen(_Min, _N, _Max, [],GPprev) -> + %% is between Min and Max + GPprev. + + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 8288f68f7f..a79badef24 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -35,6 +35,8 @@ decrypt_private/2, decrypt_private/3, encrypt_public/2, encrypt_public/3, decrypt_public/2, decrypt_public/3, + dh_gex_group/4, + dh_gex_group_sizes/0, sign/3, verify/4, generate_key/1, compute_key/2, compute_key/3, @@ -372,6 +374,13 @@ encrypt_private(PlainText, Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), crypto:private_encrypt(rsa, PlainText, format_rsa_private_key(Key), Padding). +%%-------------------------------------------------------------------- +dh_gex_group_sizes() -> + pubkey_ssh:dh_gex_group_sizes(). + +dh_gex_group(Min, N, Max, Groups) -> + pubkey_ssh:dh_gex_group(Min, N, Max, Groups). + %%-------------------------------------------------------------------- -spec generate_key(#'DHParameter'{} | {namedCurve, Name ::oid()} | #'ECParameters'{}) -> {Public::binary(), Private::binary()} | diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 2b190c98b6..66f872490c 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -467,6 +467,8 @@ kex is implicit but public_key is set explicitly.

Sets the groups that the server may choose among when diffie-hellman-group-exchange is negotiated. See RFC 4419 for details.

+

The default list is fetched from the public_key application. +

If the parameter is {file,filename()}, the file must exist and have one or more three-tuples terminated by a dot. The interpretation is as if the tuples had been given directly in the option. The file is read when the daemon starts.

diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 049018b21c..8d36c847de 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -33,7 +33,8 @@ default_algorithms/0, stop_listener/1, stop_listener/2, stop_listener/3, stop_daemon/1, stop_daemon/2, stop_daemon/3, - shell/1, shell/2, shell/3]). + shell/1, shell/2, shell/3 + ]). %%-------------------------------------------------------------------- -spec start() -> ok | {error, term()}. @@ -423,7 +424,11 @@ handle_ssh_option({preferred_algorithms,[_|_]} = Opt) -> handle_ssh_option({dh_gex_groups,L=[{I1,I2,I3}|_]}) when is_integer(I1), I1>0, is_integer(I2), I2>0, is_integer(I3), I3>0 -> - {dh_gex_groups, lists:map(fun({N,G,P}) -> {N,{G,P}} end, L)}; + {dh_gex_groups, public_key:moduli_collect_per_size( + lists:map(fun({N,G,P}) when is_integer(N),N>0, + is_integer(G),G>0, + is_integer(P),P>0 -> {N,{G,P}} end, L) + )}; handle_ssh_option({dh_gex_groups,{file,File=[C|_]}}=Opt) when is_integer(C), C>0 -> %% A string, (file name) case file:consult(File) of diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index d622ec27fc..35bfadb1df 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -446,14 +446,23 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, max = Max}, Ssh0=#ssh{opts=Opts}) when Min= %% server - {G, P} = dh_gex_group(Min, NBits, Max, proplists:get_value(dh_gex_groups,Opts)), - {Public, Private} = generate_key(dh, [P,G]), - {SshPacket, Ssh} = - ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), - {ok, SshPacket, - Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, - keyex_info = {Min, Max, NBits} - }}; + case public_key:dh_gex_group(Min, NBits, Max, + proplists:get_value(dh_gex_groups,Opts)) of + {ok, {_Sz, {G,P}}} -> + {Public, Private} = generate_key(dh, [P,G]), + {SshPacket, Ssh} = + ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), + {ok, SshPacket, + Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, + keyex_info = {Min, Max, NBits} + }}; + {error,_} -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "No possible diffie-hellman-group-exchange group found", + language = ""}) + end; + handle_kex_dh_gex_request(_, _) -> throw({{error,bad_ssh_msg_kex_dh_gex_request}, #ssh_msg_disconnect{ @@ -1482,44 +1491,10 @@ peer_name({Host, _}) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -dh_group('diffie-hellman-group1-sha1') -> element(2, ?dh_group1); -dh_group('diffie-hellman-group14-sha1') -> element(2, ?dh_group14). - -dh_gex_default_groups() -> ?dh_default_groups. - - -dh_gex_group(Min, N, Max, undefined) -> - dh_gex_group(Min, N, Max, dh_gex_default_groups()); -dh_gex_group(Min, N, Max, Groups) -> - %% First try to find an exact match. If not an exact match, select the largest possible. - {_Size,Group} = - lists:foldl( - fun(_, {I,G}) when I==N -> - %% If we have an exact match already: use that one - {I,G}; - ({I,G}, _) when I==N -> - %% If we now found an exact match: use that very one - {I,G}; - ({I,G}, {Imax,_Gmax}) when Min=Imax -> % b) {I,G} is larger than current max - %% A group within the limits and better than the one we have - {I,G}; - (_, IGmax) -> - %% Keep the one we have - IGmax - end, {-1,undefined}, Groups), - - case Group of - undefined -> - throw(#ssh_msg_disconnect{ - code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "No possible diffie-hellman-group-exchange group found", - language = ""}); - _ -> - Group - end. - +dh_group('diffie-hellman-group1-sha1') -> ?dh_group1; +dh_group('diffie-hellman-group14-sha1') -> ?dh_group14. +%%%---------------------------------------------------------------- generate_key(Algorithm, Args) -> {Public,Private} = crypto:generate_key(Algorithm, Args), {crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}. diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl index 337f455279..fd43326f0d 100644 --- a/lib/ssh/src/ssh_transport.hrl +++ b/lib/ssh/src/ssh_transport.hrl @@ -229,40 +229,13 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% rfc 2489, ch 6.2 +%%% Size 1024 -define(dh_group1, - {1024, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}}). + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}). %%% rfc 3526, ch3 +%%% Size 2048 -define(dh_group14, - {2048, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch4 --define(dh_group15, - {3072, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch5 --define(dh_group16, - {4096, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch6 --define(dh_group17, - {6144, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF}}). - -%%% rfc 3526, ch7 --define(dh_group18, - {8192, - {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF}}). - --define(dh_default_groups, [?dh_group1, - ?dh_group14, - ?dh_group15, - ?dh_group16, - ?dh_group17, - ?dh_group18] ). + {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}). -endif. % -ifdef(ssh_transport). diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index 2ab83d84e1..85415a17de 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -83,7 +83,7 @@ init_per_suite(Config) -> ssh_test_lib:default_algorithms(sshc), ssh_test_lib:default_algorithms(sshd), {?DEFAULT_DH_GROUP_MIN,?DEFAULT_DH_GROUP_NBITS,?DEFAULT_DH_GROUP_MAX}, - [KeyLen || {KeyLen,_} <- ?dh_default_groups], + public_key:dh_gex_group_sizes(), ?MAX_NUM_ALGORITHMS ]), ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]), @@ -171,20 +171,51 @@ simple_exec(Config) -> {Host,Port} = ?config(srvr_addr, Config), ssh_test_lib:std_simple_exec(Host, Port, Config). +%%-------------------------------------------------------------------- +%% Testing if no group matches +simple_exec_groups_no_match_too_small(Config) -> + try simple_exec_group({400,500,600}, Config) + of + _ -> ct:fail("Exec though no group available") + catch + error:{badmatch,{error,"No possible diffie-hellman-group-exchange group found"}} -> + ok + end. + +simple_exec_groups_no_match_too_large(Config) -> + try simple_exec_group({9200,9500,9700}, Config) + of + _ -> ct:fail("Exec though no group available") + catch + error:{badmatch,{error,"No possible diffie-hellman-group-exchange group found"}} -> + ok + end. + %%-------------------------------------------------------------------- %% Testing all default groups -simple_exec_group14(Config) -> simple_exec_group(2048, Config). -simple_exec_group15(Config) -> simple_exec_group(3072, Config). -simple_exec_group16(Config) -> simple_exec_group(4096, Config). -simple_exec_group17(Config) -> simple_exec_group(6144, Config). -simple_exec_group18(Config) -> simple_exec_group(8192, Config). - -simple_exec_group(I, Config) -> - Min = I-100, - Max = I+100, - {Host,Port} = ?config(srvr_addr, Config), - ssh_test_lib:std_simple_exec(Host, Port, Config, - [{dh_gex_limits,{Min,I,Max}}]). +simple_exec_groups(Config) -> + Sizes = interpolate( public_key:dh_gex_group_sizes() ), + lists:foreach( + fun(Sz) -> + ct:log("Try size ~p",[Sz]), + ct:comment(Sz), + case simple_exec_group(Sz, Config) of + expected -> ct:log("Size ~p ok",[Sz]); + _ -> ct:log("Size ~p not ok",[Sz]) + end + end, Sizes), + ct:comment("~p",[lists:map(fun({_,I,_}) -> I; + (I) -> I + end,Sizes)]). + + +interpolate([I1,I2|Is]) -> + OneThird = (I2-I1) div 3, + [I1, + {I1, I1 + OneThird, I2}, + {I1, I1 + 2*OneThird, I2} | interpolate([I2|Is])]; +interpolate(Is) -> + Is. %%-------------------------------------------------------------------- %% Use the ssh client of the OS to connect @@ -283,11 +314,10 @@ specific_test_cases(Tag, Alg, SshcAlgos, SshdAlgos) -> case {Tag,Alg} of {kex,_} when Alg == 'diffie-hellman-group-exchange-sha1' ; Alg == 'diffie-hellman-group-exchange-sha256' -> - [simple_exec_group14, - simple_exec_group15, - simple_exec_group16, - simple_exec_group17, - simple_exec_group18]; + [simple_exec_groups, + simple_exec_groups_no_match_too_large, + simple_exec_groups_no_match_too_small + ]; _ -> [] end. @@ -331,3 +361,11 @@ setup_pubkey(Config) -> ssh_test_lib:setup_dsa_known_host(DataDir, UserDir), Config. + +simple_exec_group(I, Config) when is_integer(I) -> + simple_exec_group({I,I,I}, Config); +simple_exec_group({Min,I,Max}, Config) -> + {Host,Port} = ?config(srvr_addr, Config), + ssh_test_lib:std_simple_exec(Host, Port, Config, + [{dh_gex_limits,{Min,I,Max}}]). + diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index b84ccac885..9d54f14ff6 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -66,8 +66,6 @@ groups() -> {kex, [], [no_common_alg_server_disconnects, no_common_alg_client_disconnects, - gex_client_init_default_noexact, - gex_client_init_default_exact, gex_client_init_option_groups, gex_client_init_option_groups_file ]}, @@ -91,9 +89,7 @@ end_per_suite(Config) -> init_per_testcase(no_common_alg_server_disconnects, Config) -> start_std_daemon(Config, [{preferred_algorithms,[{public_key,['ssh-rsa']}]}]); -init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; - TC == gex_client_init_default_exact ; - TC == gex_client_init_option_groups ; +init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; TC == gex_client_init_option_groups_file -> Opts = case TC of gex_client_init_option_groups -> @@ -113,9 +109,7 @@ init_per_testcase(_TestCase, Config) -> end_per_testcase(no_common_alg_server_disconnects, Config) -> stop_std_daemon(Config); -end_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; - TC == gex_client_init_default_exact ; - TC == gex_client_init_option_groups ; +end_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; TC == gex_client_init_option_groups_file -> stop_std_daemon(Config); end_per_testcase(_TestCase, Config) -> @@ -332,28 +326,16 @@ no_common_alg_client_disconnects(Config) -> end. %%%-------------------------------------------------------------------- -gex_client_init_default_noexact(Config) -> - do_gex_client_init(Config, {2000, 3000, 4000}, - %% Warning, app knowledege: - ?dh_group15). - - -gex_client_init_default_exact(Config) -> - do_gex_client_init(Config, {2000, 2048, 4000}, - %% Warning, app knowledege: - ?dh_group14). - - gex_client_init_option_groups(Config) -> do_gex_client_init(Config, {2000, 2048, 4000}, - {'n/a',{3,41}}). + {3,41}). gex_client_init_option_groups_file(Config) -> do_gex_client_init(Config, {2000, 2048, 4000}, - {'n/a',{5,61}}). + {5,61}). -do_gex_client_init(Config, {Min,N,Max}, {_,{G,P}}) -> +do_gex_client_init(Config, {Min,N,Max}, {G,P}) -> {ok,_} = ssh_trpt_test_lib:exec( [{set_options, [print_ops, print_seqnums, print_messages]}, -- cgit v1.2.3 From 961bb51d1b73c6ff2ad5f08e0a4c13fbfc2fbb98 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 23 Oct 2015 18:33:05 +0200 Subject: ssh: option dh_gex_groups with tag ssh_moduli_file Makes this existing option also accept a file in openssh format OTP-13052 --- lib/ssh/doc/src/ssh.xml | 4 +- lib/ssh/src/ssh.erl | 105 ++++++++++++++++----- lib/ssh/test/ssh_protocol_SUITE.erl | 11 +++ .../ssh_protocol_SUITE_data/dh_group_test.moduli | 3 + 4 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test.moduli (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 66f872490c..1e4dd91eb6 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -462,7 +462,7 @@ kex is implicit but public_key is set explicitly.

- +

Sets the groups that the server may choose among when diffie-hellman-group-exchange is negotiated. See RFC 4419 for details. @@ -471,6 +471,8 @@ kex is implicit but public_key is set explicitly.

If the parameter is {file,filename()}, the file must exist and have one or more three-tuples terminated by a dot. The interpretation is as if the tuples had been given directly in the option. The file is read when the daemon starts.

+

If the parameter is {ssh_moduli_file,filename()}, the file must exist and be in ssh-keygen moduli file format. The file is read when the daemon starts. +

boolean()}]]> diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 8d36c847de..9befceb51b 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -421,28 +421,59 @@ handle_ssh_option({user_interaction, Value} = Opt) when is_boolean(Value) -> Opt; handle_ssh_option({preferred_algorithms,[_|_]} = Opt) -> handle_pref_algs(Opt); -handle_ssh_option({dh_gex_groups,L=[{I1,I2,I3}|_]}) when is_integer(I1), I1>0, - is_integer(I2), I2>0, - is_integer(I3), I3>0 -> - {dh_gex_groups, public_key:moduli_collect_per_size( - lists:map(fun({N,G,P}) when is_integer(N),N>0, - is_integer(G),G>0, - is_integer(P),P>0 -> {N,{G,P}} end, L) - )}; -handle_ssh_option({dh_gex_groups,{file,File=[C|_]}}=Opt) when is_integer(C), C>0 -> - %% A string, (file name) - case file:consult(File) of - {ok, List} -> - try handle_ssh_option({dh_gex_groups,List}) of - {dh_gex_groups,_} = NewOpt -> - NewOpt - catch - _:_ -> - throw({error, {{eoptions, Opt}, "Bad format in file"}}) - end; - Error -> - throw({error, {{eoptions, Opt},{"Error reading file",Error}}}) - end; + +handle_ssh_option({dh_gex_groups,L0}) when is_list(L0) -> + {dh_gex_groups, + collect_per_size( + lists:foldl( + fun({N,G,P}, Acc) when is_integer(N),N>0, + is_integer(G),G>0, + is_integer(P),P>0 -> + [{N,{G,P}} | Acc]; + ({N,{G,P}}, Acc) when is_integer(N),N>0, + is_integer(G),G>0, + is_integer(P),P>0 -> + [{N,{G,P}} | Acc]; + ({N,GPs}, Acc) when is_list(GPs) -> + lists:foldr(fun({Gi,Pi}, Acci) when is_integer(Gi),Gi>0, + is_integer(Pi),Pi>0 -> + [{N,{Gi,Pi}} | Acci] + end, Acc, GPs) + end, [], L0))}; + +handle_ssh_option({dh_gex_groups,{Tag,File=[C|_]}}=Opt) when is_integer(C), C>0, + Tag == file ; + Tag == ssh_moduli_file -> + {ok,GroupDefs} = + case Tag of + file -> + file:consult(File); + ssh_moduli_file -> + case file:open(File,[read]) of + {ok,D} -> + try + {ok,Moduli} = read_moduli_file(D, 1, []), + file:close(D), + {ok, Moduli} + catch + _:_ -> + throw({error, {{eoptions, Opt}, "Bad format in file "++File}}) + end; + {error,enoent} -> + throw({error, {{eoptions, Opt}, "File not found:"++File}}); + {error,Error} -> + throw({error, {{eoptions, Opt}, io_lib:format("Error reading file ~s: ~p",[File,Error])}}) + end + end, + + try + handle_ssh_option({dh_gex_groups,GroupDefs}) + catch + _:_ -> + throw({error, {{eoptions, Opt}, "Bad format in file: "++File}}) + end; + + handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0, is_integer(I), I>=Min, is_integer(Max), Max>=I -> @@ -665,3 +696,33 @@ directory_exist_readable(Dir) -> +collect_per_size(L) -> + lists:foldr( + fun({Sz,GP}, [{Sz,GPs}|Acc]) -> [{Sz,[GP|GPs]}|Acc]; + ({Sz,GP}, Acc) -> [{Sz,[GP]}|Acc] + end, [], lists:sort(L)). + +read_moduli_file(D, I, Acc) -> + case io:get_line(D,"") of + {error,Error} -> + {error,Error}; + eof -> + {ok, Acc}; + "#" ++ _ -> read_moduli_file(D, I+1, Acc); + <<"#",_/binary>> -> read_moduli_file(D, I+1, Acc); + Data -> + Line = if is_binary(Data) -> binary_to_list(Data); + is_list(Data) -> Data + end, + try + [_Time,_Type,_Tests,_Tries,Size,G,P] = string:tokens(Line," \r\n"), + M = {list_to_integer(Size), + {list_to_integer(G), list_to_integer(P,16)} + }, + read_moduli_file(D, I+1, [M|Acc]) + catch + _:_ -> + read_moduli_file(D, I+1, Acc) + end + end. + diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 9d54f14ff6..0292c8d149 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -67,6 +67,7 @@ groups() -> {kex, [], [no_common_alg_server_disconnects, no_common_alg_client_disconnects, gex_client_init_option_groups, + gex_client_init_option_groups_moduli_file, gex_client_init_option_groups_file ]}, {service_requests, [], [bad_service_name, @@ -90,6 +91,7 @@ init_per_testcase(no_common_alg_server_disconnects, Config) -> start_std_daemon(Config, [{preferred_algorithms,[{public_key,['ssh-rsa']}]}]); init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; + TC == gex_client_init_option_groups_moduli_file ; TC == gex_client_init_option_groups_file -> Opts = case TC of gex_client_init_option_groups -> @@ -98,6 +100,10 @@ init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; DataDir = ?config(data_dir, Config), F = filename:join(DataDir, "dh_group_test"), [{dh_gex_groups, {file,F}}]; + gex_client_init_option_groups_moduli_file -> + DataDir = ?config(data_dir, Config), + F = filename:join(DataDir, "dh_group_test.moduli"), + [{dh_gex_groups, {ssh_moduli_file,F}}]; _ -> [] end, @@ -110,6 +116,7 @@ init_per_testcase(_TestCase, Config) -> end_per_testcase(no_common_alg_server_disconnects, Config) -> stop_std_daemon(Config); end_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; + TC == gex_client_init_option_groups_moduli_file ; TC == gex_client_init_option_groups_file -> stop_std_daemon(Config); end_per_testcase(_TestCase, Config) -> @@ -335,6 +342,10 @@ gex_client_init_option_groups_file(Config) -> do_gex_client_init(Config, {2000, 2048, 4000}, {5,61}). +gex_client_init_option_groups_moduli_file(Config) -> + do_gex_client_init(Config, {2000, 2048, 4000}, + {5,16#B7}). + do_gex_client_init(Config, {Min,N,Max}, {G,P}) -> {ok,_} = ssh_trpt_test_lib:exec( diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test.moduli b/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test.moduli new file mode 100644 index 0000000000..f6995ba4c9 --- /dev/null +++ b/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test.moduli @@ -0,0 +1,3 @@ +20151021104105 2 6 100 2222 5 B7 +20151021104106 2 6 100 1111 5 4F + -- cgit v1.2.3 From 18b9fc4c61f487007c8bff3bbb52f9466f3454ce Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 26 Oct 2015 15:56:13 +0100 Subject: ssh: extend 'dh_gex_limits' to server side OTP-13066 --- lib/ssh/doc/src/ssh.xml | 11 +++++++++++ lib/ssh/src/ssh.erl | 5 +++++ lib/ssh/src/ssh_transport.erl | 29 +++++++++++++++++++++++++---- lib/ssh/test/ssh_protocol_SUITE.erl | 19 ++++++++++++++++--- 4 files changed, 57 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 1e4dd91eb6..7c1b9ea0dc 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -475,6 +475,17 @@ kex is implicit but public_key is set explicitly.

+ + +

Limits what a client can ask for in diffie-hellman-group-exchange. The effective value will be + MaxUsed = min(MaxClient,Max), MinUsed = max(MinClient,Min). +

+

If MaxUsed < MinUses in a key exchange, it will fail with a disconnect. +

+

See RFC 4419 for the function of the max an min values. +

+
+ boolean()}]]>

Provides a function for password validation. This function is called diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 9befceb51b..39cf441090 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -474,9 +474,14 @@ handle_ssh_option({dh_gex_groups,{Tag,File=[C|_]}}=Opt) when is_integer(C), C>0, end; +handle_ssh_option({dh_gex_limits,{Min,Max}} = Opt) when is_integer(Min), Min>0, + is_integer(Max), Max>=Min -> + %% Server + Opt; handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0, is_integer(I), I>=Min, is_integer(Max), Max>=I -> + %% Client Opt; handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 35bfadb1df..d61fc76c0a 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -441,13 +441,14 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = PeerPubHostKey, %%% %%% diffie-hellman-group-exchange-sha1 %%% -handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, +handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min0, n = NBits, - max = Max}, - Ssh0=#ssh{opts=Opts}) when Min= + max = Max0}, + Ssh0=#ssh{opts=Opts}) when Min0= %% server + {Min, Max} = adjust_gex_min_max(Min0, Max0, Opts), case public_key:dh_gex_group(Min, NBits, Max, - proplists:get_value(dh_gex_groups,Opts)) of + proplists:get_value(dh_gex_groups,Opts)) of {ok, {_Sz, {G,P}}} -> {Public, Private} = generate_key(dh, [P,G]), {SshPacket, Ssh} = @@ -471,6 +472,26 @@ handle_kex_dh_gex_request(_, _) -> language = ""} }). + +adjust_gex_min_max(Min0, Max0, Opts) -> + case proplists:get_value(dh_gex_limits, Opts) of + undefined -> + {Min0, Max0}; + {Min1, Max1} -> + Min2 = max(Min0, Min1), + Max2 = min(Max0, Max1), + if + Min2 =< Max2 -> + {Min2, Max2}; + Max2 < Min2 -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "No possible diffie-hellman-group-exchange group possible", + language = ""}) + end + end. + + handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) -> %% client {Public, Private} = generate_key(dh, [P,G]), diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 0292c8d149..3a7f47c2dd 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -67,6 +67,7 @@ groups() -> {kex, [], [no_common_alg_server_disconnects, no_common_alg_client_disconnects, gex_client_init_option_groups, + gex_server_gex_limit, gex_client_init_option_groups_moduli_file, gex_client_init_option_groups_file ]}, @@ -92,7 +93,8 @@ init_per_testcase(no_common_alg_server_disconnects, Config) -> init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; TC == gex_client_init_option_groups_moduli_file ; - TC == gex_client_init_option_groups_file -> + TC == gex_client_init_option_groups_file ; + TC == gex_server_gex_limit -> Opts = case TC of gex_client_init_option_groups -> [{dh_gex_groups, [{2345, 3, 41}]}]; @@ -104,6 +106,12 @@ init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; DataDir = ?config(data_dir, Config), F = filename:join(DataDir, "dh_group_test.moduli"), [{dh_gex_groups, {ssh_moduli_file,F}}]; + gex_server_gex_limit -> + [{dh_gex_groups, [{ 500, 3, 18}, + {1000, 7, 91}, + {3000, 5, 61}]}, + {dh_gex_limits,{500,1500}} + ]; _ -> [] end, @@ -117,7 +125,8 @@ end_per_testcase(no_common_alg_server_disconnects, Config) -> stop_std_daemon(Config); end_per_testcase(TC, Config) when TC == gex_client_init_option_groups ; TC == gex_client_init_option_groups_moduli_file ; - TC == gex_client_init_option_groups_file -> + TC == gex_client_init_option_groups_file ; + TC == gex_server_gex_limit -> stop_std_daemon(Config); end_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). @@ -337,7 +346,6 @@ gex_client_init_option_groups(Config) -> do_gex_client_init(Config, {2000, 2048, 4000}, {3,41}). - gex_client_init_option_groups_file(Config) -> do_gex_client_init(Config, {2000, 2048, 4000}, {5,61}). @@ -346,6 +354,11 @@ gex_client_init_option_groups_moduli_file(Config) -> do_gex_client_init(Config, {2000, 2048, 4000}, {5,16#B7}). +gex_server_gex_limit(Config) -> + do_gex_client_init(Config, {1000, 3000, 4000}, + {7,91}). + + do_gex_client_init(Config, {Min,N,Max}, {G,P}) -> {ok,_} = ssh_trpt_test_lib:exec( -- cgit v1.2.3 From 447a9b574f26cc81ed09be4ec1afafea8de924c5 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 3 Nov 2015 15:07:30 +0100 Subject: ssh: changes after doc review --- lib/ssh/doc/src/ssh.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 7c1b9ea0dc..06bc39f8fe 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -477,13 +477,14 @@ kex is implicit but public_key is set explicitly.

-

Limits what a client can ask for in diffie-hellman-group-exchange. The effective value will be +

Limits the key Sizes what a client can ask for in diffie-hellman-group-exchange. + The effective value will be MaxUsed = min(MaxClient,Max), MinUsed = max(MinClient,Min). + The default value is {0,infinity}.

-

If MaxUsed < MinUses in a key exchange, it will fail with a disconnect. -

-

See RFC 4419 for the function of the max an min values. +

If MaxUsed < MinUsed in a key exchange, it will fail with a disconnect.

+

See RFC 4419 for the function of the Max an Min values.

boolean()}]]> -- cgit v1.2.3 From 02aca536aec93edd799d67615e47bdb7b5babf4a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 9 Oct 2015 13:02:25 +0200 Subject: [kernel] Correct documentation Fix mistakes found by 'xmllint'. --- lib/kernel/doc/src/app.xml | 2 +- lib/kernel/doc/src/application.xml | 5 +++-- lib/kernel/doc/src/auth.xml | 8 ++++---- lib/kernel/doc/src/code.xml | 4 ++-- lib/kernel/doc/src/disk_log.xml | 12 ++++++------ lib/kernel/doc/src/erl_ddll.xml | 22 +++++++++++----------- lib/kernel/doc/src/error_logger.xml | 2 +- lib/kernel/doc/src/file.xml | 25 ++++++++++++------------- lib/kernel/doc/src/gen_sctp.xml | 14 ++++++++------ lib/kernel/doc/src/gen_tcp.xml | 5 +++-- lib/kernel/doc/src/gen_udp.xml | 4 ++-- lib/kernel/doc/src/inet.xml | 30 +++++++++++++++--------------- lib/kernel/doc/src/inet_res.xml | 31 ++++++++++++++++++++----------- lib/kernel/doc/src/net_adm.xml | 4 ++-- lib/kernel/doc/src/notes.xml | 7 +++---- lib/kernel/doc/src/os.xml | 4 ++-- 16 files changed, 95 insertions(+), 84 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml index 1591d589af..d6d6167923 100644 --- a/lib/kernel/doc/src/app.xml +++ b/lib/kernel/doc/src/app.xml @@ -191,7 +191,7 @@ RTDeps [ApplicationVersion] [] start phases must be a subset of the set of phases defined for the primary application. Refer to OTP Design Principles for more information.

- runtime_dependencies + runtime_dependencies

A list of application versions that the application depends on. An example of such an application version is "kernel-3.0". Application versions specified as runtime diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml index 0fe774a73f..4d8e6ce94b 100644 --- a/lib/kernel/doc/src/application.xml +++ b/lib/kernel/doc/src/application.xml @@ -60,8 +60,9 @@ - tuple_of(T) -

A tuple where the elements are of type T.

+ tuple_of(T) +

+ A tuple where the elements are of type T.

diff --git a/lib/kernel/doc/src/auth.xml b/lib/kernel/doc/src/auth.xml index 9ebc6f8f1a..71b1863e96 100644 --- a/lib/kernel/doc/src/auth.xml +++ b/lib/kernel/doc/src/auth.xml @@ -50,7 +50,7 @@ be established in this case. Returns no if Node does not exist or communication is not authorized (it has another cookie than auth thinks it has).

-

Use net_adm:ping(Node) +

Use net_adm:ping(Node) instead.

@@ -71,7 +71,7 @@

Use - erlang:set_cookie(node(), Cookie) + erlang:set_cookie(node(), Cookie) instead.

@@ -94,8 +94,8 @@

Sets the magic cookie of Node to Cookie, and verifies the status of the authorization. Equivalent to calling - erlang:set_cookie(Node, Cookie), followed by - auth:is_auth(Node).

+ erlang:set_cookie(Node, Cookie), followed by + auth:is_auth(Node).

diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 7cdedfa0ba..4e3be35079 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -180,7 +180,7 @@ example, the call erl_prim_loader:list_dir( "/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)" would list the contents of a directory inside an archive. - See erl_prim_loader(3)

. + See erl_prim_loader(3).

An application archive file and a regular application directory may coexist. This may be useful when there is a need of having @@ -242,7 +242,7 @@ particular useful to set the flag to relaxed when you want to elaborate with code loading from archives without editing the boot script. The default is relaxed. See init(3)

+ marker="erts:init">init(3)

diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 32488a9f01..7d4a9687ea 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -233,11 +233,11 @@ + Asynchronously log an item onto a disk log. - Asynchronously log an item onto a disk log.

The alog/2 and balog/2 functions asynchronously append an item to a disk log. The function alog/2 is @@ -288,8 +288,8 @@ - Block a disk log. +

With a call to block/1,2 a process can block a log. If the blocking process is not an owner of the log, a temporary @@ -663,8 +663,8 @@ - Close a disk log on one node. +

The function lclose/1 closes a local log or an individual distributed log on the current node. @@ -744,6 +744,7 @@ + Open a disk log file. @@ -753,7 +754,6 @@ - Open a disk log file.

The ArgL parameter is a list of options which have the following meanings:

@@ -1043,8 +1043,8 @@ If
- Flush the contents of a disk log to the disk. +

The sync/1 function ensures that the contents of the log are actually written to the disk. @@ -1086,8 +1086,8 @@ If - Unblock a disk log. +

The unblock/1 function unblocks a log. A log can only be unblocked by the blocking process. diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml index d622725ba0..8d71883cf4 100644 --- a/lib/kernel/doc/src/erl_ddll.xml +++ b/lib/kernel/doc/src/erl_ddll.xml @@ -388,14 +388,14 @@ remove a monitor.

The function accepts the following parameters:

- Tag + Tag

The monitor tag is always driver as this function can only be used to create driver monitors. In the future, driver monitors will be integrated with process monitors, why this parameter has to be given for consistence.

- Item + Item

The Item parameter specifies which driver one wants to monitor (the name of the driver) as well as @@ -642,7 +642,7 @@

The function accepts the following parameters:

- Path + Path

The filesystem path to the directory where the driver object file is situated. The filename of the object file @@ -665,7 +665,7 @@ to have only one loader of a driver one wants to upgrade in a running system!

- Name + Name

The name parameter is the name of the driver to be used in subsequent calls to open_port. The @@ -678,14 +678,14 @@ with this Name parameter, much as a beam-file's module name much correspond to its filename.

- OptionList + OptionList

A number of options can be specified to control the loading operation. The options are given as a list of two-tuples, the tuples having the following values and meanings:

- {driver_options, DriverOptionList} + {driver_options, DriverOptionList}

This option is to provide options that will change its general behavior and will "stick" to the driver @@ -701,7 +701,7 @@ when the last user calls try_unload/2, or the last process having loaded the driver exits.

- {monitor, MonitorOption} + {monitor, MonitorOption}

A MonitorOption tells try_load/3 to trigger a driver monitor under certain @@ -732,7 +732,7 @@ {monitor, pending_driver} in production code (see the monitor discussion above).

- {reload,ReloadOption} + {reload, ReloadOption}

This option is used when one wants to reload a driver from disk, most often in a @@ -910,13 +910,13 @@

The function accepts the following parameters:

- Name + Name

The name parameter is the name of the driver to be unloaded. The name can be specified either as an iolist() or as an atom().

- OptionList + OptionList

The OptionList argument can be used to specify certain behavior regarding ports as well as triggering @@ -934,7 +934,7 @@ unloads, one should use the driver option kill_ports when loading the driver instead.

- {monitor, MonitorOption} + {monitor, MonitorOption}

This option creates a driver monitor if the condition given in MonitorOption is true. The valid diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index f83fe53084..92e14c2bef 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -299,12 +299,12 @@ ok + Enable or disable error printouts to a file - Enable or disable error printouts to a file

Enables or disables printout of standard events to a file.

This is done by adding or deleting the standard event handler diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 4954568086..9cd4cfa712 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -87,9 +87,10 @@ - fd() + fd() -

A file descriptor representing a file opened in + A file descriptor representing a file opened in raw mode.

@@ -491,7 +492,7 @@ List files in a directory -

Lists all files in a directory, except files +

Lists all files in a directory, except files with "raw" names. Returns {ok, Filenames} if successful. Otherwise, it returns {error, Reason}. @@ -1307,15 +1308,15 @@

The current system access to the file.

- atime = date_time() | integer() >= 0 + atime = date_time() | integer() >= 0

The last time the file was read.

- mtime = date_time() | integer() >= 0 + mtime = date_time() | integer() >= 0

The last time the file was written.

- ctime = date_time() | integer() >=0 + ctime = date_time() | integer() >=0

The interpretation of this time field depends on the operating system. On Unix, it is the last time @@ -1745,7 +1746,7 @@ See gen_tcp:controlling_process/2

If the OS used does not support sendfile, an Erlang fallback using file:read and gen_tcp:send is used.

-

The option list can contain the following options: +

The option list can contain the following options:

chunk_size The chunk size used by the erlang fallback to send @@ -1760,7 +1761,6 @@ the sendfile call will return {error,einval}. Introduced in Erlang/OTP 17.0. Default is false. -

@@ -1851,22 +1851,21 @@ Type local will interpret the time set as local, universal will interpret it as universal time and posix must be seconds since or before unix time epoch which is 1970-01-01 00:00 UTC. - Default is {time, local}. + Default is {time, local}.

If the raw option is set, the file server will not be called and only informations about local files will be returned.

-

The following fields are used from the record, if they are given.

- atime = date_time() | integer() >= 0 + atime = date_time() | integer() >= 0

The last time the file was read.

- mtime = date_time() | integer() >= 0 + mtime = date_time() | integer() >= 0

The last time the file was written.

- ctime = date_time() | integer() >= 0 + ctime = date_time() | integer() >= 0

On Unix, any value give for this field will be ignored (the "ctime" for the file will be set to the current diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml index b704d90613..456108a2fe 100644 --- a/lib/kernel/doc/src/gen_sctp.xml +++ b/lib/kernel/doc/src/gen_sctp.xml @@ -77,9 +77,10 @@ - assoc_id() + assoc_id() -

An opaque term returned in for example #sctp_paddr_change{} +

+ An opaque term returned in for example #sctp_paddr_change{} that identifies an association for an SCTP socket. The term is opaque except for the special value 0 that has a meaning such as "the whole endpoint" or "all future associations". @@ -98,9 +99,10 @@ - sctp_socket() + sctp_socket() -

Socket identifier returned from open/*.

+

+ Socket identifier returned from open/*.

@@ -146,7 +148,7 @@ Addr and Port. The Timeout, is expressed in milliseconds. A socket can be associated with multiple peers.

-

WARNING:Using a value of Timeout less than +

WARNING:Using a value of Timeout less than the maximum time taken by the OS to establish an association (around 4.5 minutes if the default values from RFC 4960 are used) can result in inconsistent or incorrect return values. This is especially @@ -170,7 +172,7 @@

The number of outbound and inbound streams can be set by giving an sctp_initmsg option to connect as in:

-
  connect(Socket, Ip, Port,
+
  connect(Socket, Ip, Port>,
         [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,
                                      max_instreams=MaxInStreams}}])        

All options Opt are set on the socket before the diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index 8d9f09cea7..6a19e76c4f 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -78,9 +78,10 @@ do_recv(Sock, Bs) -> - socket() + socket() -

As returned by accept/1,2 and connect/3,4.

+

+ As returned by accept/1,2 and connect/3,4.

diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml index 6f34aba43c..79cd87dcef 100644 --- a/lib/kernel/doc/src/gen_udp.xml +++ b/lib/kernel/doc/src/gen_udp.xml @@ -43,9 +43,9 @@ - socket() + socket() -

As returned by open/1,2.

+

As returned by open/1,2.

diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index e6d418dc58..088d78c1d6 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -4,7 +4,7 @@
- 19972013 + 19972015 Ericsson AB. All Rights Reserved. @@ -117,8 +117,9 @@ fe80::204:acff:fe17:bf38 - socket() -

See gen_tcp(3) + socket() +

+ See gen_tcp(3) and gen_udp(3).

@@ -222,7 +223,7 @@ fe80::204:acff:fe17:bf38

Do not rely too much on the order of Flag atoms or - Ifopt tuples. There are some rules, though: + Ifopt tuples. There are some rules, though:

Immediately after {addr,_} follows {netmask,_} @@ -238,7 +239,6 @@ fe80::204:acff:fe17:bf38 tuple concerns that address. -

The {hwaddr,_} tuple is not returned on Solaris since the hardware address historically belongs to the link layer and only @@ -379,14 +379,14 @@ fe80::204:acff:fe17:bf38 Convert IPv6 / IPV4 adress to ascii -

Parses an ip_address() and returns an IPv4 or IPv6 address string.

+

Parses an ip_address() and returns an IPv4 or IPv6 address string.

Parse an IPv4 address -

Parses an IPv4 address string and returns an ip4_address(). +

Parses an IPv4 address string and returns an ip4_address(). Accepts a shortened IPv4 shortened address string.

@@ -394,14 +394,14 @@ fe80::204:acff:fe17:bf38 Parse an IPv4 address strict. -

Parses an IPv4 address string containing four fields, i.e not shortened, and returns an ip4_address().

+

Parses an IPv4 address string containing four fields, i.e not shortened, and returns an ip4_address().

Parse an IPv6 address -

Parses an IPv6 address string and returns an ip6_address(). +

Parses an IPv6 address string and returns an ip6_address(). If an IPv4 address string is passed, an IPv4-mapped IPv6 address is returned.

@@ -409,22 +409,22 @@ fe80::204:acff:fe17:bf38 Parse an IPv6 address strict. -

Parses an IPv6 address string and returns an ip6_address(). - Does not accept IPv4 adresses.

+

Parses an IPv6 address string and returns an ip6_address(). + Does not accept IPv4 adresses.

Parse an IPv4 or IPv6 address. -

Parses an IPv4 or IPv6 address string and returns an ip4_address() or ip6_address(). Accepts a shortened IPv4 address string.

+

Parses an IPv4 or IPv6 address string and returns an ip4_address() or ip6_address(). Accepts a shortened IPv4 address string.

Parse an IPv4 or IPv6 address strict. -

Parses an IPv4 or IPv6 address string and returns an ip4_address() or ip6_address(). Does not accept a shortened IPv4 address string.

+

Parses an IPv4 or IPv6 address string and returns an ip4_address() or ip6_address(). Does not accept a shortened IPv4 address string.

@@ -862,10 +862,10 @@ fe80::204:acff:fe17:bf38 CAP_SYS_ADMIN according to the documentation for setns(2). However, during testing also CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH has proven to be necessary. - Example: + Example:

setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp - Note also that the filesystem containing the virtual machine +

Note also that the filesystem containing the virtual machine executable (beam.smp in the example above) has to be local, mounted without the nosetuid flag, support extended attributes and that diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml index 6a2c9b1955..851a36aba9 100644 --- a/lib/kernel/doc/src/inet_res.xml +++ b/lib/kernel/doc/src/inet_res.xml @@ -4,7 +4,7 @@

- 20092013 + 20092015 Ericsson AB. All Rights Reserved. @@ -77,8 +77,11 @@ query is tried for the alt_nameservers.

+
+ Resolver Types +

The following data types concern the resolver:

+
-

Resolver types:

@@ -88,8 +91,13 @@ - -

DNS types:

+
+
+ DNS Types +

+ The following data types concern the DNS client:

+
+

A string with no adjacent dots.

@@ -106,7 +114,7 @@

This is the start of a hiearchy of opaque data structures that can be examined with access functions in inet_dns that return lists of {Field,Value} tuples. The arity 2 functions - just return the value for a given field. + just return the value for a given field.

 dns_msg() = DnsMsg
     inet_dns:msg(DnsMsg) ->
@@ -154,18 +162,19 @@ dns_rr() = DnsRr
                      | {version, integer()}
                      | {z, integer()}
                      | {data, dns_data()} ]
-    inet_dns:rr(DnsRr, Field) -> Value
+    inet_dns:rr(DnsRr, Field) -> Value
-There is an info function for the types above: +

There is an info function for the types above:

+
 inet_dns:record_type(dns_msg()) -> msg;
 inet_dns:record_type(dns_header()) -> header;
 inet_dns:record_type(dns_query()) -> dns_query;
 inet_dns:record_type(dns_rr()) -> rr;
-inet_dns:record_type(_) -> undefined.
+inet_dns:record_type(_) -> undefined.
-So; inet_dns:(inet_dns:record_type(X))(X) will convert -any of these data structures into a {Field,Value} list.

+

So; inet_dns:(inet_dns:record_type(X))(X) will convert +any of these data structures into a {Field,Value} list.

@@ -272,7 +281,7 @@ any of these data structures into a {Field,Value} list.

Resolve a DNS record of the given type and class for the given name. The returned dns_msg() can be examined using access functions in inet_db as described - in DNS types. + in DNS Types.

If Name is an ip_address(), the domain name to query for is generated as the standard reverse diff --git a/lib/kernel/doc/src/net_adm.xml b/lib/kernel/doc/src/net_adm.xml index 1072be44a5..4ef9d361f6 100644 --- a/lib/kernel/doc/src/net_adm.xml +++ b/lib/kernel/doc/src/net_adm.xml @@ -89,8 +89,8 @@ - Lookup and connect to all nodes at all hosts in .hosts.erlang +

This function calls names(Host) for all hosts which are specified in the Erlang host file .hosts.erlang, @@ -110,8 +110,8 @@ - Lookup and connect to all nodes at specified hosts +

As world/0,1, but the hosts are given as argument instead of being read from .hosts.erlang.

diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 76db0c201f..268a8404f1 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -1218,7 +1218,7 @@

Fix returned error from gen_tcp:accept/1,2 when - running out of ports + running out of ports.

The {error, enfile} return value is badly misleading and confusing for this case, since the Posix ENFILE errno @@ -1227,7 +1227,7 @@ {error, system_limit}, which is consistent with e.g. various file(3) functions. inet:format_error/1 has also been updated to support system_limit in the same manner - as file:format_error/1. (Thanks to Per Hedeland)

+ as file:format_error/1. (Thanks to Per Hedeland)

Own Id: OTP-9990

@@ -1422,7 +1422,6 @@ Own Id: OTP-9764

-

Correct callback spec in application module

Refine warning about callback specs with extra ranges

Cleanup @@ -1433,7 +1432,7 @@ analysis

Fix crash in Dialyzer

Variable substitution was not generalizing any unknown variables.

-

+

Own Id: OTP-9776

diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml index 2d2a690fea..682d4a2eac 100644 --- a/lib/kernel/doc/src/os.xml +++ b/lib/kernel/doc/src/os.xml @@ -171,8 +171,8 @@ DirOut = os:cmd("dir"), % on Win32 platform
- Timestamp = {MegaSecs, Secs, MicroSecs} Current OS system time on the erlang:timestamp/0 format + Timestamp = {MegaSecs, Secs, MicroSecs}

Returns current OS system time @@ -205,7 +205,7 @@ format_utc_timestamp() -> 29 Apr 2009 9:55:30.051711

OS system time can also be retreived by - os:system_time/0, + os:system_time/0, and os:system_time/1.

-- cgit v1.2.3 From de432f4ea9a8c29c931f30dd504662be1a01464d Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 12 Oct 2015 14:28:39 +0200 Subject: [stdlib] Correct documentation Fix mistakes found by 'xmllint'. --- lib/stdlib/doc/src/array.xml | 4 +-- lib/stdlib/doc/src/assert_hrl.xml | 11 +++---- lib/stdlib/doc/src/beam_lib.xml | 4 +-- lib/stdlib/doc/src/binary.xml | 4 +-- lib/stdlib/doc/src/c.xml | 2 +- lib/stdlib/doc/src/calendar.xml | 4 +-- lib/stdlib/doc/src/dets.xml | 56 ++++++++++++++++++------------------ lib/stdlib/doc/src/digraph.xml | 6 ++-- lib/stdlib/doc/src/digraph_utils.xml | 5 ++-- lib/stdlib/doc/src/epp.xml | 2 +- lib/stdlib/doc/src/erl_anno.xml | 34 +++++++++++----------- lib/stdlib/doc/src/erl_parse.xml | 2 +- lib/stdlib/doc/src/erl_pp.xml | 4 +-- lib/stdlib/doc/src/erl_scan.xml | 36 +++++++++++------------ lib/stdlib/doc/src/erl_tar.xml | 3 +- lib/stdlib/doc/src/ets.xml | 13 +++++---- lib/stdlib/doc/src/file_sorter.xml | 52 ++++++++++++++++----------------- lib/stdlib/doc/src/gen_event.xml | 4 +-- lib/stdlib/doc/src/gen_fsm.xml | 2 +- lib/stdlib/doc/src/gen_server.xml | 2 +- lib/stdlib/doc/src/io.xml | 18 ++++++------ lib/stdlib/doc/src/lists.xml | 6 ++-- lib/stdlib/doc/src/math.xml | 2 +- lib/stdlib/doc/src/notes.xml | 53 +++++++++++++++++++--------------- lib/stdlib/doc/src/random.xml | 12 ++++++-- lib/stdlib/doc/src/re.xml | 16 +++++------ lib/stdlib/doc/src/sofs.xml | 5 ++-- lib/stdlib/doc/src/supervisor.xml | 2 +- lib/stdlib/doc/src/sys.xml | 4 +-- lib/stdlib/doc/src/timer.xml | 8 ------ lib/stdlib/doc/src/zip.xml | 2 +- 31 files changed, 192 insertions(+), 186 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml index 28b4435938..0f33e2621c 100644 --- a/lib/stdlib/doc/src/array.xml +++ b/lib/stdlib/doc/src/array.xml @@ -164,7 +164,7 @@ the default value cannot be confused with the values of set entries.

-

Equivalent to from_list(List, undefined).

+

Equivalent to from_list(List, undefined).

@@ -184,7 +184,7 @@ the default value cannot be confused with the values of set entries.

-

Equivalent to from_orddict(Orddict, undefined).

+

Equivalent to from_orddict(Orddict, undefined).

diff --git a/lib/stdlib/doc/src/assert_hrl.xml b/lib/stdlib/doc/src/assert_hrl.xml index b85be514d8..ef4f928e57 100644 --- a/lib/stdlib/doc/src/assert_hrl.xml +++ b/lib/stdlib/doc/src/assert_hrl.xml @@ -76,9 +76,6 @@ erlc -DNOASSERT=true *.erl -
-
-
Macros @@ -94,12 +91,12 @@ erlc -DNOASSERT=true *.erl assertMatch(GuardedPattern, Expr)

Tests that Expr completes normally yielding a value - that matches GuardedPattern. For example: + that matches GuardedPattern. For example:

- ?assertMatch({bork, _}, f())

-

Note that a guard when ... can be included: + ?assertMatch({bork, _}, f()) +

Note that a guard when ... can be included:

- ?assertMatch({bork, X} when X > 0, f())

+ ?assertMatch({bork, X} when X > 0, f())
assertNotMatch(GuardedPattern, Expr) diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml index faf668735e..7c89c8b43e 100644 --- a/lib/stdlib/doc/src/beam_lib.xml +++ b/lib/stdlib/doc/src/beam_lib.xml @@ -4,7 +4,7 @@
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -71,6 +71,7 @@ using strip/1, strip_files/1 and/or strip_release/1.

+
Reconstructing source code

Here is an example of how to reconstruct source code from @@ -152,7 +153,6 @@ keys.

-
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml index 063f3048e0..2682198fe5 100644 --- a/lib/stdlib/doc/src/binary.xml +++ b/lib/stdlib/doc/src/binary.xml @@ -299,8 +299,8 @@ - Searches for the first match of a pattern in a binary +

Searches for the first occurrence of Pattern in Subject and @@ -353,8 +353,8 @@ - Searches for all matches of a pattern in a binary +

Works like match/2, but the Subject is searched until diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml index a0f18bd899..e5238fa7db 100644 --- a/lib/stdlib/doc/src/c.xml +++ b/lib/stdlib/doc/src/c.xml @@ -121,12 +121,12 @@ compile:file(File, Options ++ [report_errors, report_w lc(Files) -> ok + Compile a list of files Files = [File] File = file:filename() - Compile a list of files

Compiles a list of files by calling compile:file(File, [report_errors, report_warnings]) for each File in Files.

diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml index a8d933dc83..853184dc0f 100644 --- a/lib/stdlib/doc/src/calendar.xml +++ b/lib/stdlib/doc/src/calendar.xml @@ -130,11 +130,11 @@ + Compute the number of days from year 0 up to the given date - Compute the number of days from year 0 up to the given date

This function computes the number of gregorian days starting with year 0 and ending at the given date.

@@ -347,11 +347,11 @@ + Check if a date is valid - Check if a date is valid

This function checks if a date is a valid.

diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml index 14237b6f90..a0d3f95b6a 100644 --- a/lib/stdlib/doc/src/dets.xml +++ b/lib/stdlib/doc/src/dets.xml @@ -316,20 +316,20 @@ bytes.

-

{filename, file:name()}, +

{filename, file:name()}, the name of the file where objects are stored.

-

{keypos, keypos()} - , the position of the key.

+

{keypos, keypos() + }, the position of the key.

{size, integer() >= 0}, the number of objects stored in the table.

-

{type, type()}, - the type of the table.

+

{type, type() + }, the type of the table.

@@ -345,12 +345,12 @@ allowed:

-

{access, access()} - , the access mode.

+

{access, access() + }, the access mode.

-

{auto_save, - auto_save()}, the auto save interval.

+

{auto_save, + auto_save()}, the auto save interval.

{bchunk_format, binary()}, an opaque binary @@ -730,16 +730,16 @@ ok tuples where the following values are allowed:

-

{access, - access()}. It is possible to open +

{access, + access()}. It is possible to open existing tables in read-only mode. A table which is opened in read-only mode is not subjected to the automatic file reparation algorithm if it is later opened after a crash. The default value is read_write.

-

{auto_save, - auto_save()}, the auto save +

{auto_save, + auto_save()}, the auto save interval. If the interval is an integer Time, the table is flushed to disk whenever it is not accessed for Time milliseconds. A table that has been flushed @@ -749,18 +749,18 @@ ok is 180000 (3 minutes).

-

{estimated_no_objects, - no_slots()}. Equivalent to the +

{estimated_no_objects, + no_slots()}. Equivalent to the min_no_slots option.

-

{file, - file:name()}, the name of the file to be +

{file, + file:name()}, the name of the file to be opened. The default value is the name of the table.

-

{max_no_slots, - no_slots()}, the maximum number +

{max_no_slots, + no_slots()}, the maximum number of slots that will be used. The default value as well as the maximal value is 32 M. Note that a higher value may increase the fragmentation of the table, and conversely, @@ -769,16 +769,16 @@ ok 9 tables.

-

{min_no_slots, - no_slots()}. Application +

{min_no_slots, + no_slots()}. Application performance can be enhanced with this flag by specifying, when the table is created, the estimated number of different keys that will be stored in the table. The default value as well as the minimum value is 256.

-

{keypos, - keypos()}, the position of the +

{keypos, + keypos()}, the position of the element of each object to be used as key. The default value is 1. The ability to explicitly state the key position is most convenient when we want to store Erlang @@ -815,12 +815,12 @@ ok already open.

-

{type, type()}, +

{type, type()}, the type of the table. The default value is set.

-

{version, - version()}, the version of the format +

{version, + version()}, the version of the format used for the table. The default value is 9. Tables on the format used before OTP R8 can be created by giving the value 8. A version 8 table can be converted to @@ -1036,8 +1036,8 @@ ok specification that matches all objects.

-

{select, - match_spec()}. As for select +

{select, + match_spec()}. As for select the table is traversed by calling dets:select/3 and dets:select/1. The difference is that the match specification is explicitly given. This is how to diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml index 49dc68e103..291be6c08b 100644 --- a/lib/stdlib/doc/src/digraph.xml +++ b/lib/stdlib/doc/src/digraph.xml @@ -103,13 +103,15 @@

A digraph as returned by new/0,1.

- edge() + edge() +

- vertex() + vertex() +

diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml index 6a4db2e963..639069543c 100644 --- a/lib/stdlib/doc/src/digraph_utils.xml +++ b/lib/stdlib/doc/src/digraph_utils.xml @@ -122,8 +122,9 @@ - digraph() -

A digraph as returned by digraph:new/0,1.

+ digraph() +

+ A digraph as returned by digraph:new/0,1.

diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml index fe2944bbf7..8c901f57ec 100644 --- a/lib/stdlib/doc/src/epp.xml +++ b/lib/stdlib/doc/src/epp.xml @@ -39,7 +39,7 @@ by compile to preprocess macros and include files before the actual parsing takes place.

The Erlang source file encoding is selected by a + id="encoding"/>encoding is selected by a comment in one of the first two lines of the source file. The first string that matches the regular expression coding\s*[:=]\s*([-a-zA-Z0-9])+ selects the encoding. If diff --git a/lib/stdlib/doc/src/erl_anno.xml b/lib/stdlib/doc/src/erl_anno.xml index be0ffe6f4d..ddc8b8c765 100644 --- a/lib/stdlib/doc/src/erl_anno.xml +++ b/lib/stdlib/doc/src/erl_anno.xml @@ -44,7 +44,7 @@

This module implements an abstract type that is used by the Erlang Compiler and its helper modules for holding data such as column, line number, and text. The data type is a collection of - annotations as + annotations as described in the following.

The Erlang Token Scanner returns tokens with a subset of the following annotations, depending on the options:

@@ -102,8 +102,8 @@ - anno() -

A collection of annotations.

+ anno() +

A collection of annotations.

@@ -133,8 +133,8 @@ - Return the column +

Returns the column of the annotations Anno.

@@ -142,8 +142,8 @@
- Return the end location of the text +

Returns the end location of the text of the annotations Anno. If there is no text, @@ -153,8 +153,8 @@ - Return the filename +

Returns the filename of the annotations Anno. If there is no filename, undefined is returned. @@ -180,8 +180,8 @@ - Return the generated Boolean +

Returns true if the annotations Anno has been marked as generated. The default is to return @@ -199,8 +199,8 @@ - Return the line +

Returns the line of the annotations Anno.

@@ -208,8 +208,8 @@
- Return the location +

Returns the location of the annotations Anno.

@@ -217,16 +217,16 @@
- Create a new collection of annotations +

Creates a new collection of annotations given a location.

- Modify the filename +

Modifies the filename of the annotations Anno.

@@ -234,8 +234,8 @@
- Modify the generated marker +

Modifies the generated marker of the annotations Anno. @@ -244,8 +244,8 @@ - Modify the line +

Modifies the line of the annotations Anno.

@@ -253,8 +253,8 @@
- Modify the location +

Modifies the location of the annotations Anno.

@@ -262,8 +262,8 @@
- Modify the record marker +

Modifies the record marker of the annotations Anno.

@@ -271,8 +271,8 @@
- Modify the text +

Modifies the text of the annotations Anno.

@@ -280,8 +280,8 @@
- Return the text +

Returns the text of the annotations Anno. If there is no text, undefined is returned. diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml index fdd776b7f1..0938b5dec3 100644 --- a/lib/stdlib/doc/src/erl_parse.xml +++ b/lib/stdlib/doc/src/erl_parse.xml @@ -174,8 +174,8 @@ - Convert an Erlang term into an abstract form +

Converts the Erlang data structure Data into an abstract form of type AbsTerm.

diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml index c9d9e2723d..4b8a571c81 100644 --- a/lib/stdlib/doc/src/erl_pp.xml +++ b/lib/stdlib/doc/src/erl_pp.xml @@ -48,8 +48,8 @@ -

The optional argument - HookFunction, shown in the functions described below, +

The optional argument + HookFunction, shown in the functions described below, defines a function which is called when an unknown form occurs where there should be a valid expression.

diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml index 18e988e286..342f491dd0 100644 --- a/lib/stdlib/doc/src/erl_scan.xml +++ b/lib/stdlib/doc/src/erl_scan.xml @@ -181,10 +181,10 @@ + Re-entrant scanner An opaque continuation - Re-entrant scanner

This is the re-entrant scanner which scans characters until a dot ('.' followed by a white space) or @@ -324,9 +324,9 @@ + Return information about a token - Return information about a token

Returns a list containing information about the token Token. If one single @@ -345,28 +345,28 @@

The following TokenInfoTuples with corresponding TokenItems are valid:

- {category, - category()} + {category, + category()}

The category of the token.

- {column, - column()} + {column, + column()}

The column where the token begins.

{length, integer() > 0}

The length of the token's text.

- {line, - line()} + {line, + line()}

The line where the token begins.

- {location, - location()} + {location, + location()}

The line and column where the token begins, or just the line if the column unknown.

- {symbol, - symbol()} + {symbol, + symbol()}

The token's symbol.

{text, string()} @@ -416,19 +416,19 @@

The following AttributeInfoTuples with corresponding AttributeItems are valid:

- {column, - column()} + {column, + column()}

The column where the token begins.

{length, integer() > 0}

The length of the token's text.

- {line, - line()} + {line, + line()}

The line where the token begins.

- {location, - location()} + {location, + location()}

The line and column where the token begins, or just the line if the column unknown.

diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml index 0fa5a55c5b..898b55df72 100644 --- a/lib/stdlib/doc/src/erl_tar.xml +++ b/lib/stdlib/doc/src/erl_tar.xml @@ -442,7 +442,7 @@ structure like a file descriptor, a sftp channel id or such. The different Fun clauses operates on that very term.

-

The fun clauses parameter lists are: +

The fun clauses parameter lists are:

(write, {UserPrivate,DataToWrite}) Write the term DataToWrite using UserPrivate @@ -457,7 +457,6 @@ -

A complete Fun parameter for reading and writing on files using the file module could be:

diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index ee2bf96cb7..7b01109ff8 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -132,9 +132,10 @@
- continuation() + continuation() -

Opaque continuation used by +

+ Opaque continuation used by select/1,3, select_reverse/1,3, @@ -448,13 +449,13 @@ Error: fun containing local Erlang function calls {owner, pid()}

The pid of the owner of the table.
- {protection, access()}

+ {protection, access()}

The table access rights.
{size, integer() >= 0

The number of objects inserted in the table.
- {type, type()}

+ {type, type()}

The table type.
{read_concurrency, boolean()}

@@ -1626,6 +1627,7 @@ true + Update a counter object in an ETS table. @@ -1633,7 +1635,6 @@ true - Update a counter object in an ETS table.

This function provides an efficient way to update one or more counters, without the hassle of having to look up an object, update @@ -1700,11 +1701,11 @@ true + Updates the Pos:th element of the object with a given key in an ETS table. - Updates the Pos:th element of the object with a given key in an ETS table.

This function provides an efficient way to update one or more elements within an object, without the hassle of having to look up, diff --git a/lib/stdlib/doc/src/file_sorter.xml b/lib/stdlib/doc/src/file_sorter.xml index 30e09c17b0..f033eebec7 100644 --- a/lib/stdlib/doc/src/file_sorter.xml +++ b/lib/stdlib/doc/src/file_sorter.xml @@ -223,82 +223,82 @@ output(L) -> -
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml index 1efac1535a..c4bab45781 100644 --- a/lib/stdlib/doc/src/gen_event.xml +++ b/lib/stdlib/doc/src/gen_event.xml @@ -716,7 +716,7 @@ gen_event:stop -----> Module:terminate/2 the purposes described below.

This function is called by a gen_event process when:

- + One of sys:get_status/1,2 is invoked to get the gen_event status. Opt is set @@ -740,7 +740,7 @@ gen_event:stop -----> Module:terminate/2 customises the details of the current state of the event handler. Any term is allowed for Status. The gen_event module uses Status as follows:

- + When sys:get_status/1,2 is called, gen_event ensures that its return value contains Status in place of the event handler's actual state term. diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index a8d7fadeb4..4d594b8eb2 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -805,7 +805,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 module state data.

This function is called by a gen_fsm process when:

- + One of sys:get_status/1,2 is invoked to get the gen_fsm status. Opt is set to diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index c31e869db8..6d04771cd4 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -673,7 +673,7 @@ gen_server:abcast -----> Module:handle_cast/2 module state.

This function is called by a gen_server process when:

- + One of sys:get_status/1,2 is invoked to get the gen_server status. Opt is set diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml index edf3c51b4c..4655c8662f 100644 --- a/lib/stdlib/doc/src/io.xml +++ b/lib/stdlib/doc/src/io.xml @@ -132,8 +132,8 @@ - Read a specified number of characters +

Reads Count characters from standard input (IoDevice), prompting it with Prompt. It @@ -162,8 +162,8 @@ - Read a line +

Reads a line from the standard input (IoDevice), prompting it with Prompt. It returns:

@@ -300,8 +300,8 @@ - Read a term +

Reads a term Term from the standard input (IoDevice), prompting it with Prompt. It @@ -330,8 +330,8 @@ - Read a term +

Reads a term Term from IoDevice, prompting it with Prompt. Reading starts at location @@ -698,8 +698,8 @@ ok - Read formatted input +

Reads characters from the standard input (IoDevice), prompting it with Prompt. Interprets the characters in @@ -870,8 +870,8 @@ enter>: alan : joe - Read and tokenize Erlang expressions +

Reads data from the standard input (IoDevice), prompting it with Prompt. Reading starts at location @@ -919,8 +919,8 @@ enter>1.0er. - Read and tokenize an Erlang form +

Reads data from the standard input (IoDevice), prompting it with Prompt. Starts reading @@ -939,9 +939,9 @@ enter>1.0er. + Read, tokenize and parse Erlang expressions - Read, tokenize and parse Erlang expressions

Reads data from the standard input (IoDevice), prompting it with @@ -990,9 +990,9 @@ enter>abc("hey". + Read, tokenize and parse an Erlang form - Read, tokenize and parse an Erlang form

Reads data from the standard input (IoDevice), prompting it with Prompt. Starts reading at diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml index 46edd9fe16..89ba5238b5 100644 --- a/lib/stdlib/doc/src/lists.xml +++ b/lib/stdlib/doc/src/lists.xml @@ -283,8 +283,8 @@ flatmap(Fun, List1) -> - 1..tuple_size(Tuple) Search for an element in a list of tuples + 1..tuple_size(Tuple)

Searches the list of tuples TupleList for a tuple whose Nth element compares equal to Key. @@ -311,8 +311,8 @@ flatmap(Fun, List1) -> - 1..tuple_size(Tuple) Test for membership of a list of tuples + 1..tuple_size(Tuple)

Returns true if there is a tuple in TupleList whose Nth element compares equal to Key, otherwise @@ -346,8 +346,8 @@ flatmap(Fun, List1) -> - 1..tuple_size(Tuple) Search for an element in a list of tuples + 1..tuple_size(Tuple)

Searches the list of tuples TupleList for a tuple whose Nth element compares equal to Key. diff --git a/lib/stdlib/doc/src/math.xml b/lib/stdlib/doc/src/math.xml index 31e838d741..aee6c3f238 100644 --- a/lib/stdlib/doc/src/math.xml +++ b/lib/stdlib/doc/src/math.xml @@ -72,9 +72,9 @@ + Diverse math functions - Diverse math functions

A collection of math functions which return floats. Arguments are numbers.

diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index bdd0680038..c84ca9c8ad 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -154,8 +154,9 @@ Correct maps module error exceptions

Bad input to maps module function will now yield the - following exceptions: {badmap,NotMap} - or, badarg

+ following exceptions:

+ {badmap, NotMap}, or badarg. +

Own Id: OTP-12657

@@ -253,12 +254,11 @@

proc_lib:stop/1,3 is used by the following functions:

-

gen_server:stop/1,3 (new) gen_fsm:stop/1,3 (new) gen_event:stop/1,3 (modified to be synchronous) wx_object:stop/1,3 - (new)

+ (new)

Own Id: OTP-11173 Aux Id: seq12353

@@ -865,8 +865,7 @@ also implemented by the generic behaviours gen_server, gen_event and gen_fsm.

- The potential incompatibility refers to

-

+ The potential incompatibility refers to:

The previous behaviour of intercepting the system message and passing a tuple of size 2 as the last argument to sys:handle_system_msg/6 is no longer @@ -874,7 +873,7 @@ StateFun in sys:replace_state/2,3 fails is changed from being totally silent to possibly (if the callback module does not catch) throw an exception in the - client process.

+ client process.

(Thanks to James Fish and Steve Vinoski)

@@ -1036,22 +1035,28 @@

EEP43: New data type - Maps

- With Maps you may for instance: M0 = - #{ a => 1, b => 2}, % create - associations M1 = M0#{ a := 10 }, % - update values M2 = M1#{ "hi" => - "hello"}, % add new associations #{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values

+ With Maps you may for instance:

+ + M0 = #{ a => 1, b => 2}, % create + associations + M1 = M0#{ a := 10 }, % update values + M2 = M1#{ "hi" => + "hello"}, % add new associations + #{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values +

For information on how to use Maps please see Map Expressions in the Reference Manual.

The current implementation is without the following - features: No variable keys - No single value access No map - comprehensions

+ features:

+ + No variable keys + No single value access + No map comprehensions +

Note that Maps is experimental during OTP 17.0.

@@ -1802,13 +1807,15 @@ supervisor or for the problematic child.

This introduces some incompatibilities in stdlib due to - new return values from supervisor: + new return values from supervisor:

+ restart_child/2 can now return {error,restarting} delete_child/2 can now return {error,restarting} which_children/1 returns a list of {Id,Child,Type,Mods}, where Child, in addition to the old pid() or 'undefined', now also can be - 'restarting'.

+ 'restarting'. +

*** POTENTIAL INCOMPATIBILITY ***

@@ -1824,10 +1831,10 @@ Own Id: OTP-9782 Aux Id: seq11964

-

Use universal time as base in error logger +

Use universal time as base in error logger

Previous conversion used the deprecated - calendar:local_time_to_universal_time/1

+ calendar:local_time_to_universal_time/1

Own Id: OTP-9854

@@ -2584,10 +2591,10 @@ Own Id: OTP-8989 Aux Id: seq11741

-

Fix exception generation in the io module +

Fix exception generation in the io module

Some functions did not generate correct badarg exception - on a badarg exception.

+ on a badarg exception.

Own Id: OTP-9045

diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml index 91a4012ce9..a1bf67d332 100644 --- a/lib/stdlib/doc/src/random.xml +++ b/lib/stdlib/doc/src/random.xml @@ -76,9 +76,15 @@ dictionary, and returns the old state.

One easy way of obtaining a unique value to seed with is to:

- random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()) +random:seed(erlang:phash2([node()]), + erlang:monotonic_time(), + erlang:unique_integer()) +

See + erlang:phash2/1, + node/0, + erlang:monotonic_time/0, and + + erlang:unique_integer/0) for details.

diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml index 46b382a6be..8c19926b10 100644 --- a/lib/stdlib/doc/src/re.xml +++ b/lib/stdlib/doc/src/re.xml @@ -205,8 +205,8 @@ This option makes it possible to include comments inside complicated patterns. N - See compile/2 above. Match a subject against regular expression and capture subpatterns + See compile/2 above.

Executes a regexp matching, returning match/{match, @@ -881,11 +881,11 @@ nomatch - - +

PERL LIKE REGULAR EXPRESSIONS SYNTAX -

The following sections contain reference material for the +

+ The following sections contain reference material for the regular expressions used by this module. The regular expression reference is based on the PCRE documentation, with changes in cases where the re module behaves differently to the PCRE library.

@@ -2070,7 +2070,7 @@ supported, and an error is given if they are encountered.

By default, in UTF modes, characters with values greater than 255 do not match any of the POSIX character classes. However, if the PCRE_UCP option is passed -to pcre_compile(), some of the classes are changed so that Unicode +to pcre_compile(), some of the classes are changed so that Unicode character properties are used. This is achieved by replacing the POSIX classes by other sequences, as follows:

@@ -2078,10 +2078,10 @@ by other sequences, as follows:

[:alnum:] becomes \p{Xan} [:alpha:] becomes \p{L} [:blank:] becomes \h - [:digit:] becomes \p{Nd} + [:digit:] becomes \p{Nd} [:lower:] becomes \p{Ll} [:space:] becomes \p{Xps} - [:upper:] becomes \p{Lu} + [:upper:] becomes \p{Lu} [:word:] becomes \p{Xwd} @@ -3059,7 +3059,7 @@ default newline convention is in force:

abc #comment \n still comment

-

On encountering the # character, pcre_compile() skips along, looking for +

On encountering the # character, pcre_compile() skips along, looking for a newline in the pattern. The sequence \n is still literal at this stage, so it does not terminate the comment. Only an actual character with the code value 0x0a (the default newline) does so.

diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml index 5d7648d9a1..53f6ca957a 100644 --- a/lib/stdlib/doc/src/sofs.xml +++ b/lib/stdlib/doc/src/sofs.xml @@ -398,8 +398,9 @@ fun(S) -> sofs:partition(1, S) end - tuple_of(T) -

A tuple where the elements are of type T.

+ tuple_of(T) +

+ A tuple where the elements are of type T.

diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index f08b752998..24ff251ce3 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -353,7 +353,7 @@

Dynamically adds a child specification to the supervisor SupRef which starts the corresponding child process.

-

SupRef can be:

+

SupRef can be:

the pid, Name, if the supervisor is locally registered, diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index 6ec515849e..d400f72e1d 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -238,8 +238,8 @@

These functions are intended only to help with debugging. They are provided for convenience, allowing developers to avoid having to create their own state extraction functions and also avoid having to interactively extract state from the return values of - get_status/1 or - get_status/2 while debugging.

+ get_status/1 or + get_status/2 while debugging.

The value of State varies for different types of processes. For a gen_server process, the returned State diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml index e002f519b9..7609487300 100644 --- a/lib/stdlib/doc/src/timer.xml +++ b/lib/stdlib/doc/src/timer.xml @@ -85,7 +85,6 @@ Send Messageto Pidafter a specified Time. -

send_after/3 @@ -99,7 +98,6 @@

Same as send_after(Time, self(), Message).

-

@@ -109,7 +107,6 @@ Send an exit signal with Reasonafter a specified Time. -

exit_after/3 @@ -130,7 +127,6 @@

Same as exit_after(Time, self(), kill).

-

@@ -147,7 +143,6 @@ Send Messagerepeatedly at intervals of Time. -

send_interval/3 @@ -161,7 +156,6 @@

Same as send_interval(Time, self(), Message).

-

@@ -192,7 +186,6 @@ Function, Arguments) or apply(Fun, Arguments) In microseconds -

tc/3 @@ -213,7 +206,6 @@ -

diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml index 4500995c34..186c8ac724 100644 --- a/lib/stdlib/doc/src/zip.xml +++ b/lib/stdlib/doc/src/zip.xml @@ -126,7 +126,7 @@ -

The name of a zip file.

+

The name of a zip file.

-- cgit v1.2.3 From 588cb79c699d304cae4ed1eb2ec305319a766331 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:01:37 +0200 Subject: [tools] Correct documentation Fix mistakes found by 'xmllint'. --- lib/tools/doc/src/eprof.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml index 7dccd927ca..8e37d49c99 100644 --- a/lib/tools/doc/src/eprof.xml +++ b/lib/tools/doc/src/eprof.xml @@ -131,13 +131,13 @@ analyze() -> ok analyze(Type) -> ok analyze(Type,Options) -> ok + Display profiling results per process. Type = procs | total Options = [{filter, Filter} | {sort, Sort} Filter = [{calls, integer()} | {time, float()}] Sort = time | calls | mfa - Display profiling results per process.

Call this function when profiling has been stopped to display the results per process, that is:

-- cgit v1.2.3 From 3e6aa9c3e3763522eac4b4948573739429476bed Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:01:50 +0200 Subject: [test_server] Correct documentation Fix mistakes found by 'xmllint'. --- lib/test_server/doc/src/notes.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml index 939a07dcef..da956de9ef 100644 --- a/lib/test_server/doc/src/notes.xml +++ b/lib/test_server/doc/src/notes.xml @@ -298,7 +298,7 @@ configuration function or test specification term), the affected test cases get the status user_skipped instead.

This update has meant a few changes that - may affect Common Test users in various ways: + may affect Common Test users in various ways:

The test results and statistics will be affected, which is important to know when running regression tests and comparing results to previous test runs. @@ -318,7 +318,7 @@ auto_skipped rather than user_skipped as before. The event messages that Common Test generates during test runs have been affected by this - update. For details see OTP-11524.

+ update. For details see OTP-11524.

Own Id: OTP-11305 Aux Id: OTP-11524

@@ -445,7 +445,7 @@ that were not opened with the {encoding,utf8} option. If then the argument contained unicode characters above 255, the file descriptor would crash. This has been corrected - by the following modifications: Since the + by the following modifications:

Since the 'unexpected_io' log file is used only when the test case HTML file is not available (e.g. between test cases), this file is now also a HTML file and as other @@ -467,7 +467,7 @@ path to the last run.<timestamp> directory, is now dependent on the file name mode of the VM. If file names are expected to be unicode, then the 'last_name' file is - UTF-8 encoded, else it is latin1 encoded.

+ UTF-8 encoded, else it is latin1 encoded.

Also, ~tp has been changed back to ~p unless it is somehow likely that the argument includes strings. It is @@ -615,7 +615,7 @@

- Update common test modules to handle unicode + Update common test modules to handle Unicode:

Use UTF-8 encoding for all HTML files, except the HTML version of the test suite generated with erl2html2:convert, which will have the same encoding as @@ -626,7 +626,7 @@ unicode:characters_to_list and unicode:characters_to_binary for conversion between binaries and strings instead of binary_to_list and - list_to_binary.

+ list_to_binary.
-- cgit v1.2.3 From 42eddf467f01e38502310a0f34770ed73ff74319 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:02:55 +0200 Subject: [hipe] Correct documentation Fix mistakes found by 'xmllint'. --- lib/hipe/doc/src/hipe_app.xml | 17 ++++++++--------- lib/hipe/doc/src/notes.xml | 32 ++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml index 98fec900af..bf4bdbb3b3 100644 --- a/lib/hipe/doc/src/hipe_app.xml +++ b/lib/hipe/doc/src/hipe_app.xml @@ -37,15 +37,14 @@

The normal way to native-compile an Erlang module using HiPE is to include the atom native - in the Erlang compiler options, as in: - - 1> c(my_module, [native]). - Options to the HiPE compiler are then passed as follows: - - 1> c(my_module, [native,{hipe,Options}]). - For on-line help in the Erlang shell, call hipe:help(). - Details on HiPE compiler options are given by hipe:help_options(). -

+ in the Erlang compiler options, as in:

+
+      1> c(my_module, [native]).
+

Options to the HiPE compiler are then passed as follows:

+
+      1> c(my_module, [native,{hipe,Options}]).
+

For on-line help in the Erlang shell, call hipe:help(). + Details on HiPE compiler options are given by hipe:help_options().

SEE ALSO diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index a463b421a8..e1aec698e4 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -319,22 +319,28 @@

EEP43: New data type - Maps

- With Maps you may for instance: M0 = - #{ a => 1, b => 2}, % create - associations M1 = M0#{ a := 10 }, % - update values M2 = M1#{ "hi" => - "hello"}, % add new associations #{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values

+ With Maps you may for instance:

+ + M0 = #{ a => 1, b => 2}, % create + associations + M1 = M0#{ a := 10 }, % update values + M2 = M1#{ "hi" => + "hello"}, % add new associations + #{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values +

For information on how to use Maps please see Map Expressions in the Reference Manual.

The current implementation is without the following - features: No variable keys - No single value access No map - comprehensions

+ features:

+ + No variable keys + No single value access + No map comprehensions +

Note that Maps is experimental during OTP 17.0.

@@ -602,19 +608,17 @@

Fixed Bugs and Malfunctions -

No warnings for underspecs with remote types

Fix crash in Typer

Fix Dialyzer's warning for its own code

Fix Dialyzer's warnings in HiPE

Add file/line info in a particular Dialyzer crash

Update - inets test results

+ inets test results

Own Id: OTP-9758

-

Correct callback spec in application module

Refine warning about callback specs with extra ranges

Cleanup @@ -625,7 +629,7 @@ analysis

Fix crash in Dialyzer

Variable substitution was not generalizing any unknown variables.

-

+

Own Id: OTP-9776

-- cgit v1.2.3 From 3d86418b496db400d795311ece53f9e632731a94 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:03:23 +0200 Subject: [dialyzer] Correct documentation Fix mistakes found by 'xmllint'. --- lib/dialyzer/doc/src/notes.xml | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index 9b3a7244f1..aa29684697 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -447,22 +447,28 @@

EEP43: New data type - Maps

- With Maps you may for instance: M0 = - #{ a => 1, b => 2}, % create - associations M1 = M0#{ a := 10 }, % - update values M2 = M1#{ "hi" => - "hello"}, % add new associations #{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values

+ With Maps you may for instance:

+ + M0 = #{ a => 1, b => 2}, % create + associations + M1 = M0#{ a := 10 }, % update values + M2 = M1#{ "hi" => + "hello"}, % add new associations + #{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values +

For information on how to use Maps please see Map Expressions in the Reference Manual.

The current implementation is without the following - features: No variable keys - No single value access No map - comprehensions

+ features:

+ + No variable keys + No single value access + No map comprehensions +

Note that Maps is experimental during OTP 17.0.

@@ -776,19 +782,17 @@ Own Id: OTP-9731

-

No warnings for underspecs with remote types

Fix crash in Typer

Fix Dialyzer's warning for its own code

Fix Dialyzer's warnings in HiPE

Add file/line info in a particular Dialyzer crash

Update - inets test results

+ inets test results

Own Id: OTP-9758

-

Correct callback spec in application module

Refine warning about callback specs with extra ranges

Cleanup @@ -799,7 +803,7 @@ analysis

Fix crash in Dialyzer

Variable substitution was not generalizing any unknown variables.

-

+

Own Id: OTP-9776

-- cgit v1.2.3 From 15770ab1b5587e890b7e4f557a4803291a37d2f8 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:03:12 +0200 Subject: [erl_docgen] Correct documentation Fix mistakes found by 'xmllint'. --- lib/erl_docgen/doc/src/erl_docgen_app.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/erl_docgen/doc/src/erl_docgen_app.xml b/lib/erl_docgen/doc/src/erl_docgen_app.xml index c2c65a0592..58c2a24f4b 100644 --- a/lib/erl_docgen/doc/src/erl_docgen_app.xml +++ b/lib/erl_docgen/doc/src/erl_docgen_app.xml @@ -32,7 +32,7 @@

- The application consists of the following parts + The application consists of the following parts:

XSL @@ -59,7 +59,6 @@

-

-- cgit v1.2.3 From b93e9b611056828ac2c82f225960aa29348ebe97 Mon Sep 17 00:00:00 2001 From: Andrew Bennett Date: Wed, 10 Jun 2015 13:48:30 -0600 Subject: stdlib: Add BIF binary:split/2 and binary:split/3 --- lib/stdlib/src/binary.erl | 77 +++++------------------------------------------ 1 file changed, 8 insertions(+), 69 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl index af00410572..fb0c395d70 100644 --- a/lib/stdlib/src/binary.erl +++ b/lib/stdlib/src/binary.erl @@ -20,7 +20,7 @@ -module(binary). %% %% Implemented in this module: --export([split/2,split/3,replace/3,replace/4]). +-export([replace/3,replace/4]). -export_type([cp/0]). @@ -34,7 +34,8 @@ decode_unsigned/2, encode_unsigned/1, encode_unsigned/2, first/1, last/1, list_to_bin/1, longest_common_prefix/1, longest_common_suffix/1, match/2, match/3, matches/2, - matches/3, part/2, part/3, referenced_byte_size/1]). + matches/3, part/2, part/3, referenced_byte_size/1, + split/2, split/3]). -spec at(Subject, Pos) -> byte() when Subject :: binary(), @@ -198,19 +199,13 @@ part(_, _, _) -> referenced_byte_size(_) -> erlang:nif_error(undef). -%%% End of BIFs. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% split -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -spec split(Subject, Pattern) -> Parts when Subject :: binary(), Pattern :: binary() | [binary()] | cp(), Parts :: [binary()]. -split(H,N) -> - split(H,N,[]). +split(_, _) -> + erlang:nif_error(undef). -spec split(Subject, Pattern, Options) -> Parts when Subject :: binary(), @@ -219,53 +214,10 @@ split(H,N) -> Option :: {scope, part()} | trim | global | trim_all, Parts :: [binary()]. -split(Haystack,Needles,Options) -> - try - {Part,Global,Trim,TrimAll} = - get_opts_split(Options,{no,false,false,false}), - Moptlist = case Part of - no -> - []; - {A,B} -> - [{scope,{A,B}}] - end, - MList = if - Global -> - binary:matches(Haystack,Needles,Moptlist); - true -> - case binary:match(Haystack,Needles,Moptlist) of - nomatch -> []; - Match -> [Match] - end - end, - do_split(Haystack,MList,0,Trim,TrimAll) - catch - _:_ -> - erlang:error(badarg) - end. - -do_split(H,[],N,true,_) when N >= byte_size(H) -> - []; -do_split(H,[],N,_,true) when N >= byte_size(H) -> - []; -do_split(H,[],N,_,_) -> - [binary:part(H,{N,byte_size(H)-N})]; -do_split(H,[{A,B}|T],N,Trim,TrimAll) -> - case binary:part(H,{N,A-N}) of - <<>> when TrimAll == true -> - do_split(H,T,A+B,Trim,TrimAll); - <<>> -> - Rest = do_split(H,T,A+B,Trim,TrimAll), - case {Trim, Rest} of - {true,[]} -> - []; - _ -> - [<<>> | Rest] - end; - Oth -> - [Oth | do_split(H,T,A+B,Trim,TrimAll)] - end. +split(_, _, _) -> + erlang:nif_error(undef). +%%% End of BIFs. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% replace @@ -352,19 +304,6 @@ splitat(H,N,[I|T]) -> %% Simple helper functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_opts_split([],{Part,Global,Trim,TrimAll}) -> - {Part,Global,Trim,TrimAll}; -get_opts_split([{scope,{A,B}} | T],{_Part,Global,Trim,TrimAll}) -> - get_opts_split(T,{{A,B},Global,Trim,TrimAll}); -get_opts_split([global | T],{Part,_Global,Trim,TrimAll}) -> - get_opts_split(T,{Part,true,Trim,TrimAll}); -get_opts_split([trim | T],{Part,Global,_Trim,TrimAll}) -> - get_opts_split(T,{Part,Global,true,TrimAll}); -get_opts_split([trim_all | T],{Part,Global,Trim,_TrimAll}) -> - get_opts_split(T,{Part,Global,Trim,true}); -get_opts_split(_,_) -> - throw(badopt). - get_opts_replace([],{Part,Global,Insert}) -> {Part,Global,Insert}; get_opts_replace([{scope,{A,B}} | T],{_Part,Global,Insert}) -> -- cgit v1.2.3 From dc6d89bc1c08e15f8d4cd32f2e0886713cdc2dc2 Mon Sep 17 00:00:00 2001 From: Derek Brown Date: Wed, 4 Nov 2015 16:05:33 +0100 Subject: Fix typos and grammar --- lib/kernel/doc/src/code.xml | 6 +++--- lib/kernel/doc/src/file.xml | 4 ++-- lib/stdlib/doc/src/random.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 4e3be35079..eb0f4b7a06 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -230,7 +230,7 @@ -code_path_choice Choice. If the flag is set to relaxed, the code server will instead choose a suitable directory depending on the actual file structure. If there exists a regular - application ebin directory,situation it will be chosen. But if it does + application ebin directory, it will be chosen. But if it does not exist, the ebin directory in the archive is chosen if it exists. If neither of them exists the original directory will be chosen.

@@ -282,9 +282,9 @@

From the R12B release, functions in this module will generally fail with an exception if they are passed an incorrect type (for instance, an integer or a tuple - where an atom was expected). An error tuple will be returned if type of argument + where an atom was expected). An error tuple will be returned if the type of the argument was correct, but there was some other error (for instance, a non-existing directory - given to set_path/1.

+ was given to set_path/1).

diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 9cd4cfa712..831ef1c22a 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -1194,8 +1194,8 @@ and read_line/1 are the only ways to read from a file opened in raw mode (although they work for normally opened files, too).

-

For files where encoding is set to something else than latin1, one character might be represented by more than one byte on the file. The parameter Number always denotes the number of characters read from the file, why the position in the file might be moved a lot more than this number when reading a Unicode file.

-

Also if encoding is set to something else than latin1, the read/3 call will fail if the data contains characters larger than 255, why the io(3) module is to be preferred when reading such a file.

+

For files where encoding is set to something else than latin1, one character might be represented by more than one byte on the file. The parameter Number always denotes the number of characters read from the file, while the position in the file might be moved much more than this number when reading a Unicode file.

+

Also, if encoding is set to something else than latin1, the read/3 call will fail if the data contains characters larger than 255, which is why the io(3) module is to be preferred when reading such a file.

The function returns:

{ok, Data} diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml index a1bf67d332..d3d7c90c31 100644 --- a/lib/stdlib/doc/src/random.xml +++ b/lib/stdlib/doc/src/random.xml @@ -148,7 +148,7 @@ random:seed(erlang:phash2([node()]),

The implementation changed in R15. Upgrading to R15 will break applications that expect a specific output for a given seed. The output is still deterministic number series, but different compared to releases - older than R15. The seed {0,0,0} will for example no longer + older than R15. The seed {0,0,0} will, for example, no longer produce a flawed series of only zeros.

-- cgit v1.2.3 From bd5666f98d15aa363820465621977ffb60271954 Mon Sep 17 00:00:00 2001 From: Ben Tyler Date: Sun, 1 Nov 2015 02:27:52 +0100 Subject: Fix spelling of ssh 'subsystem' This commit does not change any behaviour, since the spelling was internally consistent. --- lib/ssh/src/ssh_connection.erl | 4 ++-- lib/ssh/src/ssh_connection_handler.erl | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl index 266c64fd4f..a34478732c 100644 --- a/lib/ssh/src/ssh_connection.erl +++ b/lib/ssh/src/ssh_connection.erl @@ -662,7 +662,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId, ReplyMsg = {subsystem, ChannelId, WantReply, binary_to_list(SsName)}, try - {ok, Pid} = start_subsytem(SsName, Connection, Channel0, ReplyMsg), + {ok, Pid} = start_subsystem(SsName, Connection, Channel0, ReplyMsg), erlang:monitor(process, Pid), Channel = Channel0#channel{user = Pid}, ssh_channel:cache_update(Cache, Channel), @@ -1017,7 +1017,7 @@ start_cli(#connection{options = Options, sub_system_supervisor = SubSysSup}, ChannelId) -> start_channel(CbModule, ChannelId, Args, SubSysSup, Exec, Options). -start_subsytem(BinName, #connection{options = Options, +start_subsystem(BinName, #connection{options = Options, sub_system_supervisor = SubSysSup}, #channel{local_id = ChannelId}, _ReplyMsg) -> Name = binary_to_list(BinName), diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 7fb86c1108..099268d521 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1088,7 +1088,7 @@ handle_info(UnexpectedMessage, StateName, #state{opts = Opts, terminate(normal, _, #state{transport_cb = Transport, connection_state = Connection, socket = Socket}) -> - terminate_subsytem(Connection), + terminate_subsystem(Connection), (catch Transport:close(Socket)), ok; @@ -1117,7 +1117,7 @@ terminate({shutdown, _}, StateName, State) -> terminate(Reason, StateName, #state{ssh_params = Ssh0, starter = _Pid, connection_state = Connection} = State) -> - terminate_subsytem(Connection), + terminate_subsystem(Connection), log_error(Reason), DisconnectMsg = #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION, @@ -1128,10 +1128,10 @@ terminate(Reason, StateName, #state{ssh_params = Ssh0, starter = _Pid, terminate(normal, StateName, State#state{ssh_params = Ssh}). -terminate_subsytem(#connection{system_supervisor = SysSup, +terminate_subsystem(#connection{system_supervisor = SysSup, sub_system_supervisor = SubSysSup}) when is_pid(SubSysSup) -> ssh_system_sup:stop_subsystem(SysSup, SubSysSup); -terminate_subsytem(_) -> +terminate_subsystem(_) -> ok. format_status(normal, [_, State]) -> -- cgit v1.2.3 From df622b62f72b6509505b32380fbb88203616868d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 5 Nov 2015 17:39:46 +0100 Subject: ssh, public_key: updates after doc review --- lib/public_key/doc/src/public_key.xml | 22 ++++++++++---------- lib/public_key/priv/generate | 2 +- lib/public_key/src/Makefile | 2 +- lib/ssh/doc/src/ssh.xml | 38 ++++++++++++++++++++++++----------- 4 files changed, 39 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 7f68138497..258e7cd1b9 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -316,17 +316,17 @@

Selects a group for Diffie-Hellman key exchange with the key size in the range MinSize...MaxSize and as close to SuggestedSize as possible. If Groups == undefined a default set will be used, otherwise the group is selected from Groups.

-

First is a size as close as possible to SuggestedSize selected. Then is one group with that key size - randomly selected from the list. If no size within the limits of MinSize and MaxSize is - available, {error,no_group_found} is returned.

-

The default list is in lib/public_key/priv/ssh_moduli. The format is as produced by the openssh tool - ssh-keygen -G followed by ssh-keygen -T. When that list is changed, make should be run in - lib/public_key to make it available for dh_gex_group/4.

- -

If you change the default ssh_moduli file, be sure to run ssh-keygen -T as described - in the ssh-keygen manual. Failure to do so correctly will compromise the security of applications - relying on this function.

-
+

First a size, as close as possible to SuggestedSize, is selected. Then one group with that key size + is randomly selected from the specified set of groups. If no size within the limits of MinSize + and MaxSize is available, {error,no_group_found} is returned.

+

The default set of groups is listed in lib/public_key/priv/moduli. This file may be regenerated like this:

+
+	$> cd $ERL_TOP/lib/public_key/priv/
+	$> generate
+         ---- wait until all background jobs has finished. It may take several days !
+	$> cat moduli-* > moduli
+	$> cd ..; make 
+      
diff --git a/lib/public_key/priv/generate b/lib/public_key/priv/generate index da47e99b91..fd185bfd52 100755 --- a/lib/public_key/priv/generate +++ b/lib/public_key/priv/generate @@ -21,5 +21,5 @@ do done # When all files moduli-* are generated, do: -# cat moduli-* > ssh_moduli +# cat moduli-* > moduli diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile index ca91fd5a4a..786f244f85 100644 --- a/lib/public_key/src/Makefile +++ b/lib/public_key/src/Makefile @@ -88,7 +88,7 @@ debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(HRL_FILES) $(EBIN)/pubkey_ssh.$(EMULATOR): pubkey_moduli.hrl -pubkey_moduli.hrl: ../priv/ssh_moduli +pubkey_moduli.hrl: ../priv/moduli escript ../priv/convert.escript $< $@ clean: diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 06bc39f8fe..43db63e7e6 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -464,27 +464,41 @@ kex is implicit but public_key is set explicitly.

-

Sets the groups that the server may choose among when diffie-hellman-group-exchange is negotiated. - See RFC 4419 for details. +

Defines the groups the server may choose among when diffie-hellman-group-exchange is negotiated. + See RFC 4419 for details. The three variants of this option are:

-

The default list is fetched from the public_key application. -

-

If the parameter is {file,filename()}, the file must exist and have one or more three-tuples terminated by a dot. The interpretation is as if the tuples had been given directly in the option. The file is read when the daemon starts. -

-

If the parameter is {ssh_moduli_file,filename()}, the file must exist and be in ssh-keygen moduli file format. The file is read when the daemon starts. + + {Size=integer(),G=integer(),P=integer()} + The groups are given explicitly in this list. There may be several elements with the same Size. + In such a case, the server will choose one randomly in the negotiated Size. + + {file,filename()} + The file must have one or more three-tuples {Size=integer(),G=integer(),P=integer()} + terminated by a dot. The file is read when the daemon starts. + + {ssh_moduli_file,filename()} + The file must be in + ssh-keygen moduli file format. + The file is read when the daemon starts. + + +

The default list is fetched from the + public_key application.

-

Limits the key Sizes what a client can ask for in diffie-hellman-group-exchange. - The effective value will be - MaxUsed = min(MaxClient,Max), MinUsed = max(MinClient,Min). - The default value is {0,infinity}. +

Limits what a client can ask for in diffie-hellman-group-exchange. + The limits will be + {MaxUsed = min(MaxClient,Max), MinUsed = max(MinClient,Min)} where MaxClient and + MinClient are the values proposed by a connecting client. +

+

The default value is {0,infinity}.

If MaxUsed < MinUsed in a key exchange, it will fail with a disconnect.

-

See RFC 4419 for the function of the Max an Min values.

+

See RFC 4419 for the function of the Max and Min values.

boolean()}]]> -- cgit v1.2.3 From c9437f4fc42769aa4cb7ea3acab9f589f1ded4e0 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 5 Nov 2015 18:00:51 +0100 Subject: public_key: renamed priv/ssh_moduli -> priv/moduli --- lib/public_key/priv/moduli | 193 +++++++++++++++++++++++++++++++++++++++++ lib/public_key/priv/ssh_moduli | 193 ----------------------------------------- 2 files changed, 193 insertions(+), 193 deletions(-) create mode 100644 lib/public_key/priv/moduli delete mode 100644 lib/public_key/priv/ssh_moduli (limited to 'lib') diff --git a/lib/public_key/priv/moduli b/lib/public_key/priv/moduli new file mode 100644 index 0000000000..446f4b8bf4 --- /dev/null +++ b/lib/public_key/priv/moduli @@ -0,0 +1,193 @@ +20151021104105 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D182EB7 +20151021104106 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D27F94F +20151021104107 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D398EB7 +20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4B850F +20151021104108 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4BF35B +20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5031DF +20151021104109 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5A4933 +20151021104110 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D6434BF +20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D70676B +20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D7235E3 +20151021104113 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D963493 +20151021104114 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DAABAA7 +20151021104115 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DC2E333 +20151021104116 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE16A7B +20151021104117 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE2C5D3 +20151021104118 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DFF382F +20151021104119 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E158F13 +20151021104122 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E4D9FEB +20151021104123 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E5C1FDB +20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9BB69B +20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9F62D3 +20151021104127 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EAA1C27 +20151021104128 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EBC3313 +20151021104129 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EC0733B +20151021104130 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EDB7AD3 +20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF56457 +20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF5A9CF +20151021104133 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9F13CBB3 +20151021104218 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BAAFFDF +20151021104222 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BCB6D93 +20151021104225 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE660BB +20151021104226 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE676C3 +20151021104229 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF3E23B +20151021104230 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF95757 +20151021104241 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C59BEA7 +20151021104242 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6231B3 +20151021104244 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6879BF +20151021104250 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C9B678F +20151021104252 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CA66A4B +20151021104253 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CAB5543 +20151021104256 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CB96933 +20151021104300 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CDA8493 +20151021104308 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D18C0C7 +20151021104310 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D1DA5BF +20151021104318 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D4AB15F +20151021104325 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D7DE42F +20151021104329 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DA03D3B +20151021104335 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DD88BFF +20151021104338 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DE82B5F +20151021104342 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E07AF43 +20151021104343 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E091E6F +20151021104346 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E28B90F +20151021104347 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E2A24F3 +20151021104401 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EB074A7 +20151021104403 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EC01B0F +20151021104406 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED2186F +20151021104407 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED55AAB +20151021104411 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EF58773 +20151021104414 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F0B3267 +20151021104423 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F4DF61B +20151021104434 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F9BBB0B +20151021104442 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17FDD6AFB +20151021104350 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE5E381EF +20151021104414 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE641C193 +20151021104422 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE659F523 +20151021104427 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE660E217 +20151021104438 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6842F73 +20151021104441 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE689683B +20151021104455 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6C41E3B +20151021104512 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE71E3BFF +20151021104525 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75C804F +20151021104527 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75DC48B +20151021104535 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE7738983 +20151021104543 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE787027B +20151021104610 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8075A1B +20151021104625 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE84F79B3 +20151021104628 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE859F617 +20151021104641 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8948E2F +20151021104646 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8A571B3 +20151021104659 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8CEA637 +20151021104705 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E590FF +20151021104707 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E7943F +20151021104731 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE95A975F +20151021104741 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE985F923 +20151021104745 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE996E20B +20151021104806 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE9FACFD7 +20151021104827 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA562C43 +20151021104839 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA8F25E3 +20151021104939 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB1DA0B +20151021104941 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB86153 +20151021105002 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC1B8883 +20151021105019 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC71316F +20151021105035 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECB1D113 +20151021105042 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECC3F3AB +20151021105045 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECCC109B +20151021105101 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED16353B +20151021105106 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED24854F +20151021105109 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED2AE4B3 +20151021105116 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED472CF7 +20151021104612 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E360CD0C3 +20151021104628 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3620FBE7 +20151021104701 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E36490F57 +20151021105014 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E377ACADB +20151021105125 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E37E6DE07 +20151021105320 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E38C2387F +20151021105649 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3A61E46B +20151021105815 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B0A6A4B +20151021105848 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B47D2C3 +20151021105948 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BBBB953 +20151021110011 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BE3B83B +20151021110036 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3C0A3F1B +20151021110201 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB1970F +20151021110208 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB70C2B +20151021110235 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CE4E4DF +20151021110424 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3DB68CD7 +20151021110525 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3E290717 +20151021110655 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3ED6DA83 +20151021110731 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F14C563 +20151021110831 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F85477F +20151021111418 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E420DE56B +20151021111430 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E421DBA2F +20151021111624 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E42F39A93 +20151021111916 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E44302363 +20151021112222 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4585795F +20151021112245 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E45A1DAFF +20151021112339 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4601674F +20151021112437 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46691977 +20151021112521 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46AF3AD3 +20151021112532 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46BCAE97 +20151021112708 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E476520D3 +20151021112724 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E477B3317 +20151021105143 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BA7321EB +20151021105537 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BB3AF34B +20151021105816 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BBC51883 +20151021110444 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BD1A86C7 +20151021111341 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BEDB7BBB +20151021111438 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BF0297AB +20151021111935 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BFF381FF +20151021113820 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C433A1BF +20151021113833 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C43B426B +20151021113900 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45007D3 +20151021113921 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45D8C3B +20151021113941 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4685D5F +20151021114203 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4F95D97 +20151021114417 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C57ED2FF +20151021114645 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C612EC33 +20151021114825 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C67219F7 +20151021114922 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C6A942BB +20151021115945 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C91E14DB +20151021120515 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CA5F5DB3 +20151021120715 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CAD0D497 +20151021121027 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CB8F9D6F +20151021121241 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC0F677F +20151021121518 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC9CC647 +20151021121600 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CCC0ADC3 +20151021121734 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD1BC68B +20151021121759 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD2A7DBF +20151021122003 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CDA3D323 +20151021122542 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CED8D107 +20151021122856 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CF8DFEE7 +20151021123548 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D11CAC4F +20151021123633 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D1426BBB +20151021124201 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D2A62F0B +20151021124454 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D353F0FB +20151021124620 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D3AE526F +20151021125224 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D535C4CB +20151021130254 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D7B5CA43 +20151021111833 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239959D5A7 +20151021112931 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239A078C1B +20151021123021 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239EC676DF +20151021131523 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A2B9FC6B +20151021141029 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A7BD762B +20151021143421 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A9C3EFDF +20151021144912 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB1077AF +20151021145200 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB49943B +20151021145825 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ABE06353 +20151021150910 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ACDA0223 +20151021153131 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AE91738F +20151021154038 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF40D013 +20151021154300 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF75AD97 +20151021155008 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B01C9553 +20151021162240 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B319431B +20151021162649 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B35A3D2B +20151021163640 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B439E263 +20151021171004 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B748B983 +20151021172144 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B8609B5B +20151021173002 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B9021E9F +20151021182612 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23BE0C1EDB +20151021190053 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C120FF97 +20151021192934 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C3BEB637 +20151021113847 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE37347869A3 +20151021133636 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373914ECA3 +20151021140108 2 6 100 8191 5 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373A17959F diff --git a/lib/public_key/priv/ssh_moduli b/lib/public_key/priv/ssh_moduli deleted file mode 100644 index 446f4b8bf4..0000000000 --- a/lib/public_key/priv/ssh_moduli +++ /dev/null @@ -1,193 +0,0 @@ -20151021104105 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D182EB7 -20151021104106 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D27F94F -20151021104107 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D398EB7 -20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4B850F -20151021104108 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4BF35B -20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5031DF -20151021104109 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5A4933 -20151021104110 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D6434BF -20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D70676B -20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D7235E3 -20151021104113 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D963493 -20151021104114 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DAABAA7 -20151021104115 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DC2E333 -20151021104116 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE16A7B -20151021104117 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE2C5D3 -20151021104118 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DFF382F -20151021104119 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E158F13 -20151021104122 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E4D9FEB -20151021104123 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E5C1FDB -20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9BB69B -20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9F62D3 -20151021104127 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EAA1C27 -20151021104128 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EBC3313 -20151021104129 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EC0733B -20151021104130 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EDB7AD3 -20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF56457 -20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF5A9CF -20151021104133 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9F13CBB3 -20151021104218 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BAAFFDF -20151021104222 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BCB6D93 -20151021104225 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE660BB -20151021104226 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE676C3 -20151021104229 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF3E23B -20151021104230 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF95757 -20151021104241 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C59BEA7 -20151021104242 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6231B3 -20151021104244 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6879BF -20151021104250 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C9B678F -20151021104252 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CA66A4B -20151021104253 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CAB5543 -20151021104256 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CB96933 -20151021104300 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CDA8493 -20151021104308 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D18C0C7 -20151021104310 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D1DA5BF -20151021104318 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D4AB15F -20151021104325 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D7DE42F -20151021104329 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DA03D3B -20151021104335 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DD88BFF -20151021104338 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DE82B5F -20151021104342 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E07AF43 -20151021104343 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E091E6F -20151021104346 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E28B90F -20151021104347 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E2A24F3 -20151021104401 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EB074A7 -20151021104403 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EC01B0F -20151021104406 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED2186F -20151021104407 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED55AAB -20151021104411 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EF58773 -20151021104414 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F0B3267 -20151021104423 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F4DF61B -20151021104434 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F9BBB0B -20151021104442 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17FDD6AFB -20151021104350 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE5E381EF -20151021104414 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE641C193 -20151021104422 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE659F523 -20151021104427 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE660E217 -20151021104438 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6842F73 -20151021104441 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE689683B -20151021104455 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6C41E3B -20151021104512 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE71E3BFF -20151021104525 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75C804F -20151021104527 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75DC48B -20151021104535 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE7738983 -20151021104543 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE787027B -20151021104610 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8075A1B -20151021104625 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE84F79B3 -20151021104628 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE859F617 -20151021104641 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8948E2F -20151021104646 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8A571B3 -20151021104659 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8CEA637 -20151021104705 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E590FF -20151021104707 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E7943F -20151021104731 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE95A975F -20151021104741 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE985F923 -20151021104745 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE996E20B -20151021104806 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE9FACFD7 -20151021104827 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA562C43 -20151021104839 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA8F25E3 -20151021104939 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB1DA0B -20151021104941 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB86153 -20151021105002 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC1B8883 -20151021105019 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC71316F -20151021105035 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECB1D113 -20151021105042 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECC3F3AB -20151021105045 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECCC109B -20151021105101 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED16353B -20151021105106 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED24854F -20151021105109 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED2AE4B3 -20151021105116 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED472CF7 -20151021104612 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E360CD0C3 -20151021104628 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3620FBE7 -20151021104701 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E36490F57 -20151021105014 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E377ACADB -20151021105125 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E37E6DE07 -20151021105320 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E38C2387F -20151021105649 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3A61E46B -20151021105815 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B0A6A4B -20151021105848 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B47D2C3 -20151021105948 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BBBB953 -20151021110011 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BE3B83B -20151021110036 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3C0A3F1B -20151021110201 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB1970F -20151021110208 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB70C2B -20151021110235 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CE4E4DF -20151021110424 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3DB68CD7 -20151021110525 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3E290717 -20151021110655 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3ED6DA83 -20151021110731 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F14C563 -20151021110831 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F85477F -20151021111418 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E420DE56B -20151021111430 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E421DBA2F -20151021111624 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E42F39A93 -20151021111916 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E44302363 -20151021112222 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4585795F -20151021112245 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E45A1DAFF -20151021112339 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4601674F -20151021112437 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46691977 -20151021112521 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46AF3AD3 -20151021112532 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46BCAE97 -20151021112708 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E476520D3 -20151021112724 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E477B3317 -20151021105143 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BA7321EB -20151021105537 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BB3AF34B -20151021105816 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BBC51883 -20151021110444 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BD1A86C7 -20151021111341 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BEDB7BBB -20151021111438 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BF0297AB -20151021111935 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BFF381FF -20151021113820 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C433A1BF -20151021113833 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C43B426B -20151021113900 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45007D3 -20151021113921 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45D8C3B -20151021113941 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4685D5F -20151021114203 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4F95D97 -20151021114417 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C57ED2FF -20151021114645 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C612EC33 -20151021114825 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C67219F7 -20151021114922 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C6A942BB -20151021115945 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C91E14DB -20151021120515 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CA5F5DB3 -20151021120715 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CAD0D497 -20151021121027 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CB8F9D6F -20151021121241 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC0F677F -20151021121518 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC9CC647 -20151021121600 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CCC0ADC3 -20151021121734 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD1BC68B -20151021121759 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD2A7DBF -20151021122003 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CDA3D323 -20151021122542 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CED8D107 -20151021122856 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CF8DFEE7 -20151021123548 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D11CAC4F -20151021123633 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D1426BBB -20151021124201 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D2A62F0B -20151021124454 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D353F0FB -20151021124620 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D3AE526F -20151021125224 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D535C4CB -20151021130254 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D7B5CA43 -20151021111833 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239959D5A7 -20151021112931 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239A078C1B -20151021123021 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239EC676DF -20151021131523 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A2B9FC6B -20151021141029 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A7BD762B -20151021143421 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A9C3EFDF -20151021144912 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB1077AF -20151021145200 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB49943B -20151021145825 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ABE06353 -20151021150910 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ACDA0223 -20151021153131 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AE91738F -20151021154038 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF40D013 -20151021154300 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF75AD97 -20151021155008 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B01C9553 -20151021162240 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B319431B -20151021162649 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B35A3D2B -20151021163640 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B439E263 -20151021171004 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B748B983 -20151021172144 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B8609B5B -20151021173002 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B9021E9F -20151021182612 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23BE0C1EDB -20151021190053 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C120FF97 -20151021192934 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C3BEB637 -20151021113847 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE37347869A3 -20151021133636 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373914ECA3 -20151021140108 2 6 100 8191 5 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373A17959F -- cgit v1.2.3 From 7adbd6ee24fa7f1bb3c26d5106e7e38446405f16 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 5 Nov 2015 18:27:05 +0100 Subject: ssh: correct a bad doc xref --- lib/ssh/doc/src/ssh.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 43db63e7e6..5c18c48f65 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -478,12 +478,12 @@ kex is implicit but public_key is set explicitly.

{ssh_moduli_file,filename()} The file must be in - ssh-keygen moduli file format. + ssh-keygen moduli file format. The file is read when the daemon starts.

The default list is fetched from the - public_key application. + public_key application.

-- cgit v1.2.3 From cdbe44920678d68a9936e1ab504bc1c8aad65847 Mon Sep 17 00:00:00 2001 From: David Whitlock Date: Thu, 5 Nov 2015 12:47:08 +0700 Subject: Recommend against using crypto:rand_bytes --- lib/crypto/doc/src/crypto.xml | 7 +++++-- lib/ssh/doc/src/using_ssh.xml | 2 +- lib/stdlib/doc/src/rand.xml | 2 +- lib/stdlib/doc/src/random.xml | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 291a5145e4..36ab329ff0 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -601,8 +601,11 @@

Generates N bytes randomly uniform 0..255, and returns the - result in a binary. Uses the crypto library pseudo-random - number generator.

+ result in a binary. Uses the crypto library pseudo-random + number generator.

+

This function is not recommended for cryptographic purposes. + Please use + strong_rand_bytes/1 instead.

diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml index 91185a0f6e..3ed862458c 100644 --- a/lib/ssh/doc/src/using_ssh.xml +++ b/lib/ssh/doc/src/using_ssh.xml @@ -252,7 +252,7 @@ %% First three parameters depending on which crypto type we select: Key = <<"This is a 256 bit key. abcdefghi">>, -Ivec0 = crypto:rand_bytes(16), +Ivec0 = crypto:strong_rand_bytes(16), DataSize = 1024, % DataSize rem 16 = 0 for aes_cbc %% Initialization of the CryptoState, in this case it is the Ivector. diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml index e7d4728ef7..50057259c6 100644 --- a/lib/stdlib/doc/src/rand.xml +++ b/lib/stdlib/doc/src/rand.xml @@ -104,7 +104,7 @@ strong. If a strong cryptographic random number generator is needed, use one of functions in the crypto - module, for example crypto:rand_bytes/1.

+ module, for example crypto:strong_rand_bytes/1.

diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml index 91a4012ce9..f6f9e56966 100644 --- a/lib/stdlib/doc/src/random.xml +++ b/lib/stdlib/doc/src/random.xml @@ -48,7 +48,7 @@ tuple of three integers.

It should be noted that this random number generator is not cryptographically strong. If a strong cryptographic random number generator is needed for - example crypto:rand_bytes/1 could be used instead.

+ example crypto:strong_rand_bytes/1 could be used instead.

The new and improved rand module should be used instead of this module.

-- cgit v1.2.3 From e89a2c4c760a4c92f76fbde6d48ab0d7d08e7ee4 Mon Sep 17 00:00:00 2001 From: Zandra Date: Wed, 9 Sep 2015 14:31:24 +0200 Subject: add a soft upgrade instruction to the snmp appup --- lib/snmp/src/app/snmp.appup.src | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 6632d29457..f2936c0c1d 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -29,6 +29,7 @@ %% {update, snmpa_local_db, soft, soft_purge, soft_purge, []} %% {add_module, snmpm_net_if_mt} [ + {"5.3", [{load_module, snmp_conf, soft_purge, soft_purge, []}]}, {"5.1.2", [ % Only runtime dependencies change ]}, {"5.1.1", [{restart_application, snmp}]}, -- cgit v1.2.3 From 27659d4f0b917a4540dee46af2e0702cfcf56c63 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 6 Nov 2015 14:43:32 +0100 Subject: Make sure priv_dir names don't cause name clashes --- lib/test_server/src/test_server_ctrl.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 0be6e0b4e4..8a46996bc3 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -3711,8 +3711,8 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, RunDir = filename:dirname(MinorName), Ext = if Num == 0 -> - Nr = erlang:unique_integer([positive]), - lists:flatten(io_lib:format(".~w", [Nr])); + Int = erlang:unique_integer([positive,monotonic]), + lists:flatten(io_lib:format(".cfg.~w", [Int])); true -> lists:flatten(io_lib:format(".~w", [Num])) end, -- cgit v1.2.3 From a9f1cb21b0d418df61ffade6c0a4ed1767b9f068 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 9 Nov 2015 15:24:15 +0100 Subject: ssh: use crypto for ecdh point validation --- lib/ssh/src/ssh_transport.erl | 84 ++++++++----------------------------------- 1 file changed, 15 insertions(+), 69 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index d61fc76c0a..0c999b96cc 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -593,10 +593,11 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, Ssh0 = #ssh{algorithms = #alg{kex=Kex}}) -> %% at server Curve = ecdh_curve(Kex), - case ecdh_validate_public_key(PeerPublic, Curve) of - true -> - {MyPublic, MyPrivate} = generate_key(ecdh, Curve), - K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), + {MyPublic, MyPrivate} = generate_key(ecdh, Curve), + try + compute_key(ecdh, PeerPublic, MyPrivate, Curve) + of + K -> MyPrivHostKey = get_host_key(Ssh0), MyPubHostKey = extract_public_key(MyPrivHostKey), H = kex_h(Ssh0, Curve, MyPubHostKey, PeerPublic, MyPublic, K), @@ -609,9 +610,9 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, {ok, SshPacket, Ssh1#ssh{keyex_key = {{MyPublic,MyPrivate},Curve}, shared_secret = K, exchanged_hash = H, - session_id = sid(Ssh1, H)}}; - - false -> + session_id = sid(Ssh1, H)}} + catch + _:_ -> throw({{error,invalid_peer_public_key}, #ssh_msg_disconnect{ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, @@ -626,9 +627,10 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, #ssh{keyex_key = {{MyPublic,MyPrivate}, Curve}} = Ssh0 ) -> %% at client - case ecdh_validate_public_key(PeerPublic, Curve) of - true -> - K = compute_key(ecdh, PeerPublic, MyPrivate, Curve), + try + compute_key(ecdh, PeerPublic, MyPrivate, Curve) + of + K -> H = kex_h(Ssh0, Curve, PeerPubHostKey, MyPublic, PeerPublic, K), case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of ok -> @@ -643,9 +645,9 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, description = "Key exchange failed", language = ""} }) - end; - - false -> + end + catch + _:_ -> throw({{error,invalid_peer_public_key}, #ssh_msg_disconnect{ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, @@ -655,62 +657,6 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, end. -%%%---------------------------------------------------------------- -%%% -%%% Standards for Efficient Cryptography Group, "Elliptic Curve Cryptography", SEC 1 -%%% Section 3.2.2.1 -%%% - -ecdh_validate_public_key(Key, Curve) -> - case key_size(Curve) of - undefined -> - false; - - Sz -> - case dec_key(Key, Sz) of - {ok,Q} -> - case crypto:ec_curve(Curve) of - {{prime_field,P}, {A, B, _Seed}, - _P0Bin, _OrderBin, _CoFactorBin} -> - on_curve(Q, bin2int(A), bin2int(B), bin2int(P)) - end; - - {error,compressed_not_implemented} -> % Be a bit generous... - true; - - _Error -> - false - end - end. - - -on_curve({X,Y}, A, B, P) when 0 =< X,X =< (P-1), - 0 =< Y,Y =< (P-1) -> - %% Section 3.2.2.1, point 2 - (Y*Y) rem P == (X*X*X + A*X + B) rem P; -on_curve(_, _, _, _) -> - false. - - -bin2int(B) -> - Sz = erlang:bit_size(B), - <> = B, - I. - -key_size(secp256r1) -> 256; -key_size(secp384r1) -> 384; -key_size(secp521r1) -> 528; % Round 521 up to closest 8-bits. -key_size(_) -> undefined. - - -dec_key(Key, NBits) -> - Size = 8 + 2*NBits, - case <> of - <<4:8, X:NBits, Y:NBits>> -> {ok,{X,Y}}; - <<4:8, _/binary>> -> {error,bad_format}; - _ -> {error,compressed_not_implemented} - end. - %%%---------------------------------------------------------------- handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> try install_alg(Ssh0) of -- cgit v1.2.3 From e59290283c595efa84c8ac7720eb128dedb98fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 1 Sep 2015 17:37:04 +0200 Subject: io: Make a fast code path for i/o requests Unicode support was introduced in R13. The backward compatible code path in 'io' is unlikely to be used in practice. Therefore, make sure that the common case of an i/o server supporting unicode requests is as fast as possible, making sure to get rid of the mathing and re-building of tuples in the current code. Make the backward compatible code path work with a minimum of code. --- lib/stdlib/src/io.erl | 43 +++++++++++-------------------------------- 1 file changed, 11 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl index 284f2e5a2b..5dc8b4541e 100644 --- a/lib/stdlib/src/io.erl +++ b/lib/stdlib/src/io.erl @@ -631,41 +631,20 @@ io_requests(Pid, [], [Rs|Cont], Tail) -> io_requests(_Pid, [], [], _Tail) -> {false,[]}. - -bc_req(Pid,{Op,Enc,Param},MaybeConvert) -> - case net_kernel:dflag_unicode_io(Pid) of - true -> - {false,{Op,Enc,Param}}; - false -> - {MaybeConvert,{Op,Param}} - end; -bc_req(Pid,{Op,Enc,P,F},MaybeConvert) -> - case net_kernel:dflag_unicode_io(Pid) of - true -> - {false,{Op,Enc,P,F}}; - false -> - {MaybeConvert,{Op,P,F}} - end; -bc_req(Pid, {Op,Enc,M,F,A},MaybeConvert) -> +bc_req(Pid, Req0, MaybeConvert) -> case net_kernel:dflag_unicode_io(Pid) of true -> - {false,{Op,Enc,M,F,A}}; + %% The most common case. A modern i/o server. + {false,Req0}; false -> - {MaybeConvert,{Op,M,F,A}} - end; -bc_req(Pid, {Op,Enc,P,M,F,A},MaybeConvert) -> - case net_kernel:dflag_unicode_io(Pid) of - true -> - {false,{Op,Enc,P,M,F,A}}; - false -> - {MaybeConvert,{Op,P,M,F,A}} - end; -bc_req(Pid,{Op,Enc},MaybeConvert) -> - case net_kernel:dflag_unicode_io(Pid) of - true -> - {false,{Op, Enc}}; - false -> - {MaybeConvert,Op} + %% Backward compatibility only. Unlikely to ever happen. + case tuple_to_list(Req0) of + [Op,_Enc] -> + {MaybeConvert,Op}; + [Op,_Enc|T] -> + Req = list_to_tuple([Op|T]), + {MaybeConvert,Req} + end end. io_request(Pid, {write,Term}) -> -- cgit v1.2.3 From bd60ac17406d0cd4c12cc92944dfc1fdc068a746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Sep 2015 16:38:05 +0200 Subject: sys_pre_expand: Remove unnecessary inclusion of erl_bits.hrl --- lib/compiler/src/sys_pre_expand.erl | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index d9cc4b530c..bd37859bc2 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -32,8 +32,6 @@ -import(ordsets, [from_list/1,union/2]). -import(lists, [member/2,foldl/3,foldr/3]). --include("../include/erl_bits.hrl"). - -type fa() :: {atom(), arity()}. -record(expand, {module=[], %Module name -- cgit v1.2.3 From 765df80e59c6d5397483518f6770c0fd3f9f9412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 06:43:05 +0100 Subject: sys_pre_expand: Remove imports of ordsets functions Importing from_list/1 and union/2 from the 'ordsets', while at the same time making calls explicit calls to the functions with same name in the 'gb_sets' module is confusing. Make all calls to 'ordsets' explicit. --- lib/compiler/src/sys_pre_expand.erl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index bd37859bc2..aa1b04b631 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -29,7 +29,6 @@ %% Main entry point. -export([module/2]). --import(ordsets, [from_list/1,union/2]). -import(lists, [member/2,foldl/3,foldr/3]). -type fa() :: {atom(), arity()}. @@ -127,7 +126,7 @@ module_predef_func_beh_info(#expand{callbacks=Callbacks, PreExp=PreDef, {[gen_beh_info(Callbacks, OptionalCallbacks)], St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), Defined), - exports=union(from_list(PreExp), Exports)}}. + exports=ordsets:union(ordsets:from_list(PreExp), Exports)}}. gen_beh_info(Callbacks, OptionalCallbacks) -> List = make_list(Callbacks), @@ -167,7 +166,8 @@ module_predef_funcs_mod_info(St) -> [{atom,0,St#expand.module},{var,0,'X'}]}]}]}], St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), St#expand.defined), - exports=union(from_list(PreExp), St#expand.exports)}}. + exports=ordsets:union(ordsets:from_list(PreExp), + St#expand.exports)}}. %% forms(Forms, State) -> %% {TransformedForms,State'} @@ -194,7 +194,8 @@ attribute(module, Module, _L, St) -> true = is_atom(Module), St#expand{module=Module}; attribute(export, Es, _L, St) -> - St#expand{exports=union(from_list(Es), St#expand.exports)}; + St#expand{exports=ordsets:union(ordsets:from_list(Es), + St#expand.exports)}; attribute(import, Is, _L, St) -> import(Is, St); attribute(compile, _C, _L, St) -> @@ -652,7 +653,7 @@ string_to_conses(Line, Cs, Tail) -> import({Mod,Fs}, St) -> true = is_atom(Mod), - Mfs = from_list(Fs), + Mfs = ordsets:from_list(Fs), St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}. add_imports(Mod, [F|Fs], Is) -> -- cgit v1.2.3 From e28fdaaad1c367bd073116fa0468ae22303189c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 08:58:09 +0100 Subject: sys_pre_expand: Remove vestiges of variable usage tracking Before the Core Erlang passes were introduced a long time ago, sys_pre_expand used to track used and new variables in order to do lambda lifting (i.e. transform funs into ordinary Erlang functions). Lambda lifting is now done in v3_kernel. Remove the few remaining vestiges of variable tracking in the comments and the code. --- lib/compiler/src/sys_pre_expand.erl | 55 ++++++++----------------------------- 1 file changed, 11 insertions(+), 44 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index aa1b04b631..e0c35d63e4 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -230,8 +230,6 @@ head(As, St) -> pattern_list(As, St). %% {TransformedPattern,State'} %% -pattern({var,_,'_'}=Var, St) -> %Ignore anonymous variable. - {Var,St}; pattern({var,_,_}=Var, St) -> {Var,St}; pattern({char,_,_}=Char, St) -> @@ -384,19 +382,19 @@ expr({block,Line,Es0}, St0) -> {Es,St1} = exprs(Es0, St0), {{block,Line,Es},St1}; expr({'if',Line,Cs0}, St0) -> - {Cs,St1} = icr_clauses(Cs0, St0), + {Cs,St1} = clauses(Cs0, St0), {{'if',Line,Cs},St1}; expr({'case',Line,E0,Cs0}, St0) -> {E,St1} = expr(E0, St0), - {Cs,St2} = icr_clauses(Cs0, St1), + {Cs,St2} = clauses(Cs0, St1), {{'case',Line,E,Cs},St2}; expr({'receive',Line,Cs0}, St0) -> - {Cs,St1} = icr_clauses(Cs0, St0), + {Cs,St1} = clauses(Cs0, St0), {{'receive',Line,Cs},St1}; expr({'receive',Line,Cs0,To0,ToEs0}, St0) -> {To,St1} = expr(To0, St0), {ToEs,St2} = exprs(ToEs0, St1), - {Cs,St3} = icr_clauses(Cs0, St2), + {Cs,St3} = clauses(Cs0, St2), {{'receive',Line,Cs,To,ToEs},St3}; expr({'fun',Line,Body}, St) -> fun_tq(Line, Body, St); @@ -429,12 +427,11 @@ expr({call,Line,F,As0}, St0) -> {{call,Line,Fun1,As1},St1}; expr({'try',Line,Es0,Scs0,Ccs0,As0}, St0) -> {Es1,St1} = exprs(Es0, St0), - {Scs1,St2} = icr_clauses(Scs0, St1), - {Ccs1,St3} = icr_clauses(Ccs0, St2), + {Scs1,St2} = clauses(Scs0, St1), + {Ccs1,St3} = clauses(Ccs0, St2), {As1,St4} = exprs(As0, St3), {{'try',Line,Es1,Scs1,Ccs1,As1},St4}; expr({'catch',Line,E0}, St0) -> - %% Catch exports no new variables. {E,St1} = expr(E0, St0), {{'catch',Line,E},St1}; expr({match,Line,P0,E0}, St0) -> @@ -455,21 +452,6 @@ expr_list([E0|Es0], St0) -> {[E|Es],St2}; expr_list([], St) -> {[],St}. -%% icr_clauses([Clause], State) -> {[TransformedClause],State'} -%% Be very careful here to return the variables that are really used -%% and really new. - -icr_clauses([], St) -> {[],St}; -icr_clauses(Clauses, St) -> icr_clauses2(Clauses, St). - -icr_clauses2([{clause,Line,H0,G0,B0}|Cs0], St0) -> - {H,St1} = head(H0, St0), - {G,St2} = guard(G0, St1), - {B,St3} = exprs(B0, St2), - {Cs,St4} = icr_clauses2(Cs0, St3), - {[{clause,Line,H,G,B}|Cs],St4}; -icr_clauses2([], St) -> {[],St}. - %% lc_tq(Line, Qualifiers, State) -> %% {[TransQual],State'} @@ -485,16 +467,9 @@ lc_tq(Line, [{b_generate,Lg,P0,G0}|Qs0], St0) -> {Qs1,St3} = lc_tq(Line, Qs0, St2), {[{b_generate,Lg,P1,G1}|Qs1],St3}; lc_tq(Line, [F0 | Qs0], St0) -> - case erl_lint:is_guard_test(F0) of - true -> - {F1,St1} = guard_test(F0, St0), - {Qs1,St2} = lc_tq(Line, Qs0, St1), - {[F1|Qs1],St2}; - false -> - {F1,St1} = expr(F0, St0), - {Qs1,St2} = lc_tq(Line, Qs0, St1), - {[F1 | Qs1],St2} - end; + {F1,St1} = expr(F0, St0), + {Qs1,St2} = lc_tq(Line, Qs0, St1), + {[F1|Qs1],St2}; lc_tq(_Line, [], St0) -> {[],St0}. @@ -526,7 +501,7 @@ fun_tq(L, {function,M,F,A}, St) when is_atom(M), is_atom(F), is_integer(A) -> fun_tq(Lf, {function,_,_,_}=ExtFun, St) -> {{'fun',Lf,ExtFun},St}; fun_tq(Lf, {clauses,Cs0}, St0) -> - {Cs1,St1} = fun_clauses(Cs0, St0), + {Cs1,St1} = clauses(Cs0, St0), {Fname,St2} = new_fun_name(St1), %% Set dummy values for Index and Uniq -- the real values will %% be assigned by beam_asm. @@ -534,18 +509,10 @@ fun_tq(Lf, {clauses,Cs0}, St0) -> {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},St2}. fun_tq(Line, Cs0, St0, Name) -> - {Cs1,St1} = fun_clauses(Cs0, St0), + {Cs1,St1} = clauses(Cs0, St0), {Fname,St2} = new_fun_name(St1, Name), {{named_fun,Line,Name,Cs1,{0,0,Fname}},St2}. -fun_clauses([{clause,L,H0,G0,B0}|Cs0], St0) -> - {H,St1} = head(H0, St0), - {G,St2} = guard(G0, St1), - {B,St3} = exprs(B0, St2), - {Cs,St4} = fun_clauses(Cs0, St3), - {[{clause,L,H,G,B}|Cs],St4}; -fun_clauses([], St) -> {[],St}. - %% new_fun_name(State) -> {FunName,State}. new_fun_name(St) -> -- cgit v1.2.3 From f51512fadee8f9ef817bfc0af8ba92a532f8def2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 9 Nov 2015 16:14:16 +0100 Subject: sys_pre_expand: Clean up data structures The handling of non-remote calls is messy, with several lookups to determine whether the call is local or to some imported module. We can simplify the code if we keep a map that immediately gives us the answer. Here is an example of what the map entries look like: {f,1} => local {foldl,3} => {imported,lists} That is, there should be a local call to f/1 and a remote call to lists:foldl/3. Note that there is no longer any need to keep the set of all defined functions in the state record. --- lib/compiler/src/sys_pre_expand.erl | 115 +++++++++++++++--------------------- 1 file changed, 48 insertions(+), 67 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index e0c35d63e4..21961bc020 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -35,21 +35,20 @@ -record(expand, {module=[], %Module name exports=[], %Exports - imports=[], %Imports attributes=[], %Attributes callbacks=[], %Callbacks optional_callbacks=[] :: [fa()], %Optional callbacks - defined, %Defined functions (gb_set) vcount=0, %Variable counter func=[], %Current function arity=[], %Arity for current function - fcount=0 %Local fun count + fcount=0, %Local fun count + ctype %Call type map }). %% module(Forms, CompileOptions) %% {ModuleName,Exports,TransformedForms,CompileOptions'} -%% Expand the forms in one module. N.B.: the lists of predefined -%% exports and imports are really ordsets! +%% Expand the forms in one module. +%% %% CompileOptions is augmented with options from -compile attributes. module(Fs0, Opts0) -> @@ -62,19 +61,28 @@ module(Fs0, Opts0) -> %% Set pre-defined exported functions. PreExp = [{module_info,0},{module_info,1}], + %% Build the set of defined functions and the initial call + %% type map. + Defined = defined_functions(Fs, PreExp), + Ctype = maps:from_list([{K,local} || K <- Defined]), + %% Build initial expand record. St0 = #expand{exports=PreExp, - defined=PreExp + ctype=Ctype }, + %% Expand the functions. - {Tfs,St1} = forms(Fs, define_functions(Fs, St0)), + {Tfs,St1} = forms(Fs, St0), + %% Get the correct list of exported functions. Exports = case member(export_all, Opts) of - true -> gb_sets:to_list(St1#expand.defined); + true -> Defined; false -> St1#expand.exports end, + St2 = St1#expand{exports=Exports,ctype=undefined}, + %% Generate all functions from stored info. - {Ats,St3} = module_attrs(St1#expand{exports = Exports}), + {Ats,St3} = module_attrs(St2), {Mfs,St4} = module_predef_funcs(St3), {St4#expand.module, St4#expand.exports, Ats ++ Tfs ++ Mfs, Opts}. @@ -82,14 +90,14 @@ module(Fs0, Opts0) -> compiler_options(Forms) -> lists:flatten([C || {attribute,_,compile,C} <- Forms]). -%% define_function(Form, State) -> State. +%% defined_function(Forms, Predef) -> Functions. %% Add function to defined if form is a function. -define_functions(Forms, #expand{defined=Predef}=St) -> +defined_functions(Forms, Predef) -> Fs = foldl(fun({function,_,N,A,_Cs}, Acc) -> [{N,A}|Acc]; (_, Acc) -> Acc end, Predef, Forms), - St#expand{defined=gb_sets:from_list(Fs)}. + ordsets:from_list(Fs). module_attrs(#expand{attributes=Attributes}=St) -> Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes], @@ -110,23 +118,21 @@ is_fa_list([{FuncName, Arity}|L]) is_fa_list([]) -> true; is_fa_list(_) -> false. -module_predef_funcs(St) -> - {Mpf1,St1}=module_predef_func_beh_info(St), - {Mpf2,St2}=module_predef_funcs_mod_info(St1), +module_predef_funcs(St0) -> + {Mpf1,St1} = module_predef_func_beh_info(St0), + Mpf2 = module_predef_funcs_mod_info(St1), Mpf = [erl_parse:new_anno(F) || F <- Mpf1++Mpf2], - {Mpf,St2}. + {Mpf,St1}. module_predef_func_beh_info(#expand{callbacks=[]}=St) -> {[], St}; module_predef_func_beh_info(#expand{callbacks=Callbacks, optional_callbacks=OptionalCallbacks, - defined=Defined, exports=Exports}=St) -> - PreDef=[{behaviour_info,1}], - PreExp=PreDef, + PreDef0 = [{behaviour_info,1}], + PreDef = ordsets:from_list(PreDef0), {[gen_beh_info(Callbacks, OptionalCallbacks)], - St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), Defined), - exports=ordsets:union(ordsets:from_list(PreExp), Exports)}}. + St#expand{exports=ordsets:union(PreDef, Exports)}}. gen_beh_info(Callbacks, OptionalCallbacks) -> List = make_list(Callbacks), @@ -153,21 +159,16 @@ make_optional_list([{Name,Arity}|Rest]) -> {integer,0,Arity}]}, make_optional_list(Rest)}. -module_predef_funcs_mod_info(St) -> - PreDef = [{module_info,0},{module_info,1}], - PreExp = PreDef, - {[{function,0,module_info,0, - [{clause,0,[],[], +module_predef_funcs_mod_info(#expand{module=Mod}) -> + ModAtom = {atom,0,Mod}, + [{function,0,module_info,0, + [{clause,0,[],[], [{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}}, - [{atom,0,St#expand.module}]}]}]}, - {function,0,module_info,1, - [{clause,0,[{var,0,'X'}],[], + [ModAtom]}]}]}, + {function,0,module_info,1, + [{clause,0,[{var,0,'X'}],[], [{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}}, - [{atom,0,St#expand.module},{var,0,'X'}]}]}]}], - St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), - St#expand.defined), - exports=ordsets:union(ordsets:from_list(PreExp), - St#expand.exports)}}. + [ModAtom,{var,0,'X'}]}]}]}]. %% forms(Forms, State) -> %% {TransformedForms,State'} @@ -403,21 +404,15 @@ expr({named_fun,Line,Name,Cs}, St) -> expr({call,Line,{atom,La,N}=Atom,As0}, St0) -> {As,St1} = expr_list(As0, St0), Ar = length(As), - case defined(N,Ar,St1) of - true -> + Key = {N,Ar}, + case St1#expand.ctype of + #{Key:=local} -> {{call,Line,Atom,As},St1}; + #{Key:={imported,Mod}} -> + {{call,Line,{remote,La,{atom,La,Mod},Atom},As},St1}; _ -> - case imported(N, Ar, St1) of - {yes,Mod} -> - {{call,Line,{remote,La,{atom,La,Mod},Atom},As},St1}; - no -> - case erl_internal:bif(N, Ar) of - true -> - {{call,Line,{remote,La,{atom,La,erlang},Atom},As},St1}; - false -> %% This should have been handled by erl_lint - {{call,Line,Atom,As},St1} - end - end + true = erl_internal:bif(N, Ar), + {{call,Line,{remote,La,{atom,La,erlang},Atom},As},St1} end; expr({call,Line,{remote,Lr,M0,F},As0}, St0) -> {[M1,F1|As1],St1} = expr_list([M0,F|As0], St0), @@ -613,25 +608,11 @@ string_to_conses(Line, Cs, Tail) -> %% import(Line, Imports, State) -> %% State' -%% imported(Name, Arity, State) -> -%% {yes,Module} | no -%% Handle import declarations and test for imported functions. No need to -%% check when building imports as code is correct. +%% Handle import declarations. -import({Mod,Fs}, St) -> +import({Mod,Fs}, #expand{ctype=Ctype0}=St) -> true = is_atom(Mod), - Mfs = ordsets:from_list(Fs), - St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}. - -add_imports(Mod, [F|Fs], Is) -> - add_imports(Mod, Fs, orddict:store(F, Mod, Is)); -add_imports(_, [], Is) -> Is. - -imported(F, A, St) -> - case orddict:find({F,A}, St#expand.imports) of - {ok,Mod} -> {yes,Mod}; - error -> no - end. - -defined(F, A, St) -> - gb_sets:is_element({F,A}, St#expand.defined). + Ctype = foldl(fun(F, A) -> + A#{F=>{imported,Mod}} + end, Ctype0, Fs), + St#expand{ctype=Ctype}. -- cgit v1.2.3 From 624638e6668dcf51f6b616de5fc7c9ff1aa77bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 12:50:08 +0100 Subject: sys_pre_expand: Remove uncovered clause in pat_bit_size/2 The atom 'all' can never occur in a size field before sys_pre_expand has been run. --- lib/compiler/src/sys_pre_expand.erl | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index 21961bc020..150a453eec 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -532,7 +532,6 @@ pattern_element({bin_element,Line,Expr0,Size0,Type0}, {Es,St0}) -> {[{bin_element,Line,Expr,Size,Type}|Es],St2}. pat_bit_size(default, St) -> {default,St}; -pat_bit_size({atom,_La,all}=All, St) -> {All,St}; pat_bit_size({var,_Lv,_V}=Var, St) -> {Var,St}; pat_bit_size(Size, St) -> Line = element(2, Size), -- cgit v1.2.3 From f1c449d76e4dbe2f12de05ec08809e0a86cc63b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 10:28:15 +0100 Subject: Cover sys_pre_expand:pattern/2 --- lib/compiler/test/match_SUITE.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index 67d668f650..9166726aa2 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -449,7 +449,10 @@ do_map_vars_used(X, Y, Map) -> coverage(Config) when is_list(Config) -> %% Cover beam_dead. ok = coverage_1(x, a), - ok = coverage_1(x, b). + ok = coverage_1(x, b), + + %% Cover sys_pre_expand. + ok = coverage_3("abc"). coverage_1(B, Tag) -> case Tag of @@ -460,4 +463,6 @@ coverage_1(B, Tag) -> coverage_2(1, a, x) -> ok; coverage_2(2, b, x) -> ok. +coverage_3([$a]++[]++"bc") -> ok. + id(I) -> I. -- cgit v1.2.3 From 488862ddb45a8949efe5d71b7eb4a4a5e6406a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 10:46:21 +0100 Subject: Cover code for callbacks in sys_pre_expand --- lib/compiler/test/misc_SUITE.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index b88abaf62d..c7c20fdbf2 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -38,7 +38,11 @@ -compile({no_auto_import,[byte_size/1]}). -import(erlang,[byte_size/1]). - +%% Cover the code for callback handling. +-callback must_define_this_one() -> 'ok'. +-callback do_something_strange(atom()) -> 'ok'. +-optional_callbacks([do_something_strange/1]). +-optional_callbacks([ignore_me]). %Invalid; ignored. %% Include an opaque declaration to cover the stripping of %% opaque types from attributes in v3_kernel. -- cgit v1.2.3 From 7929fd383a90e1fbc47b6d0625cd8d889794a755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 14:49:12 +0100 Subject: sys_pre_expand: Cover coerce_to_float/2 --- lib/compiler/src/sys_pre_expand.erl | 3 +-- lib/compiler/test/bs_match_SUITE.erl | 13 ++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index 150a453eec..7ab4e1845c 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -552,8 +552,7 @@ coerce_to_float({integer,L,I}=E, [float|_]) -> try {float,L,float(I)} catch - error:badarg -> E; - error:badarith -> E + error:badarg -> E end; coerce_to_float(E, _) -> E. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index a19b152bc5..d8bef18a1a 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -116,9 +116,16 @@ fun_shadow_4(L) -> int_float(Config) when is_list(Config) -> %% OTP-5323 - ?line <<103133.0:64/float>> = <<103133:64/float>>, - ?line <<103133:64/float>> = <<103133:64/float>>, - ok. + <<103133.0:64/float>> = <<103133:64/float>>, + <<103133:64/float>> = <<103133:64/float>>, + + %% Coverage of error cases in sys_pre_expand:coerce_to_float/2. + case id(default) of + <<(1 bsl 1024):64/float>> -> + ?t:fail(); + default -> + ok + end. %% Stolen from erl_eval_SUITE and modified. %% OTP-5269. Bugs in the bit syntax. -- cgit v1.2.3 From 80f9c7d0650330d53a3c457d85916447abe17194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 15:25:29 +0100 Subject: sys_core_dsetel: Use a map instead of a dict For large modules, a map is significantly faster than a dict. --- lib/compiler/src/sys_core_dsetel.erl | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_core_dsetel.erl b/lib/compiler/src/sys_core_dsetel.erl index ac32db10fe..c6cfdbae7e 100644 --- a/lib/compiler/src/sys_core_dsetel.erl +++ b/lib/compiler/src/sys_core_dsetel.erl @@ -72,7 +72,7 @@ module(M0, _Options) -> {ok,M}. visit_module(#c_module{defs=Ds0}=R) -> - Env = dict:new(), + Env = #{}, Ds = visit_module_1(Ds0, Env, []), R#c_module{defs=Ds}. @@ -95,9 +95,11 @@ visit(Env, #c_var{name={_,_}}=R) -> {R, Env}; visit(Env0, #c_var{name=X}=R) -> %% There should not be any free variables. If there are, - %% the next line will cause an exception. - {ok, N} = dict:find(X, Env0), - {R, dict:store(X, N+1, Env0)}; + %% the case will fail with an exception. + case Env0 of + #{X:=N} -> + {R, Env0#{X:=N+1}} + end; visit(Env, #c_literal{}=R) -> {R, Env}; visit(Env0, #c_tuple{es=Es0}=R) -> @@ -203,7 +205,7 @@ bind_vars(Vs, Env) -> bind_vars(Vs, Env, []). bind_vars([#c_var{name=X}|Vs], Env0, Xs)-> - bind_vars(Vs, dict:store(X, 0, Env0), [X|Xs]); + bind_vars(Vs, Env0#{X=>0}, [X|Xs]); bind_vars([], Env,Xs) -> {Xs, Env}. @@ -217,7 +219,7 @@ visit_pats([], Env, Vs) -> {Vs, Env}. visit_pat(Env0, #c_var{name=V}, Vs) -> - {[V|Vs], dict:store(V, 0, Env0)}; + {[V|Vs], Env0#{V=>0}}; visit_pat(Env0, #c_tuple{es=Es}, Vs) -> visit_pats(Es, Env0, Vs); visit_pat(Env0, #c_map{es=Es}, Vs) -> @@ -235,23 +237,25 @@ visit_pat(Env0, #c_bitstr{val=Val,size=Sz}, Vs0) -> case Sz of #c_var{name=V} -> %% We don't tolerate free variables. - {ok, N} = dict:find(V, Env0), - {Vs0, dict:store(V, N+1, Env0)}; + case Env0 of + #{V:=N} -> + {Vs0, Env0#{V:=N+1}} + end; _ -> visit_pat(Env0, Sz, Vs0) end, visit_pat(Env1, Val, Vs1); visit_pat(Env0, #c_alias{pat=P,var=#c_var{name=V}}, Vs) -> - visit_pat(dict:store(V, 0, Env0), P, [V|Vs]); + visit_pat(Env0#{V=>0}, P, [V|Vs]); visit_pat(Env, #c_literal{}, Vs) -> {Vs, Env}. restore_vars([V|Vs], Env0, Env1) -> - case dict:find(V, Env0) of - {ok, N} -> - restore_vars(Vs, Env0, dict:store(V, N, Env1)); - error -> - restore_vars(Vs, Env0, dict:erase(V, Env1)) + case Env0 of + #{V:=N} -> + restore_vars(Vs, Env0, Env1#{V=>N}); + _ -> + restore_vars(Vs, Env0, maps:remove(V, Env1)) end; restore_vars([], _, Env1) -> Env1. @@ -349,8 +353,8 @@ is_safe(#c_literal{}) -> true; is_safe(_) -> false. is_single_use(V, Env) -> - case dict:find(V, Env) of - {ok, 1} -> + case Env of + #{V:=1} -> true; _ -> false -- cgit v1.2.3 From 36a8aa107467bd1b5f9464cf1e8f23bf5858d81f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 10 Nov 2015 15:41:35 +0100 Subject: public_key: update vsn.mk --- lib/public_key/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index f762473a58..d5ffe6ca35 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.0.1 +PUBLIC_KEY_VSN = 1.1 -- cgit v1.2.3 From 9106490ce6fa3e21641ae0dc66f20b18f755fec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 15:41:59 +0100 Subject: beam_asm: Speed up assembly for modules with many exports Eliminate searching in the list of exported functions in favor of using a map. For modules with a huge number of exported functions (such as NBAP-PDU-Contents in the asn1 test suite), that will mean a significant speed-up. --- lib/compiler/src/beam_asm.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl index a3201b0f4a..95be471de3 100644 --- a/lib/compiler/src/beam_asm.erl +++ b/lib/compiler/src/beam_asm.erl @@ -30,11 +30,12 @@ module(Code, Abst, SourceFile, Opts) -> {ok,assemble(Code, Abst, SourceFile, Opts)}. -assemble({Mod,Exp,Attr0,Asm0,NumLabels}, Abst, SourceFile, Opts) -> +assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, Abst, SourceFile, Opts) -> {1,Dict0} = beam_dict:atom(Mod, beam_dict:new()), {0,Dict1} = beam_dict:fname(atom_to_list(Mod) ++ ".erl", Dict0), NumFuncs = length(Asm0), {Asm,Attr} = on_load(Asm0, Attr0), + Exp = cerl_sets:from_list(Exp0), {Code,Dict2} = assemble_1(Asm, Exp, Dict1, []), build_file(Code, Attr, Dict2, NumLabels, NumFuncs, Abst, SourceFile, Opts). @@ -61,7 +62,7 @@ insert_on_load_instruction(Is0, Entry) -> Bef ++ [El,on_load|Is]. assemble_1([{function,Name,Arity,Entry,Asm}|T], Exp, Dict0, Acc) -> - Dict1 = case member({Name,Arity}, Exp) of + Dict1 = case cerl_sets:is_element({Name,Arity}, Exp) of true -> beam_dict:export(Name, Arity, Entry, Dict0); false -> -- cgit v1.2.3 From 30b70dbe78b8acc7a5450518cf89d9749ce6730d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 15:49:20 +0100 Subject: beam_dict: Speed up storage of funs For huge modules with many funs (such as NBAP-PDU-Contents in the asn1 test suite), the call to length/1 in beam_dict:lambda/3 will dominate the running time of the beam_asm pass. --- lib/compiler/src/beam_dict.erl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl index 2b5f8c1b7f..654fb47dbd 100644 --- a/lib/compiler/src/beam_dict.erl +++ b/lib/compiler/src/beam_dict.erl @@ -44,7 +44,7 @@ locals = [] :: [{label(), arity(), label()}], imports = gb_trees:empty() :: import_tab(), strings = <<>> :: binary(), %String pool - lambdas = [], %[{...}] + lambdas = {0,[]}, %[{...}] literals = dict:new() :: literal_tab(), fnames = #{} :: fname_tab(), lines = #{} :: line_tab(), @@ -145,15 +145,14 @@ string(Str, Dict) when is_list(Str) -> -spec lambda(label(), non_neg_integer(), bdict()) -> {non_neg_integer(), bdict()}. -lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) -> - OldIndex = length(Lambdas0), +lambda(Lbl, NumFree, #asm{lambdas={OldIndex,Lambdas0}}=Dict) -> %% Set Index the same as OldIndex. Index = OldIndex, %% Initialize OldUniq to 0. It will be set to an unique value %% based on the MD5 checksum of the BEAM code for the module. OldUniq = 0, Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0], - {OldIndex,Dict#asm{lambdas=Lambdas}}. + {OldIndex,Dict#asm{lambdas={OldIndex+1,Lambdas}}}. %% Returns the index for a literal (adding it to the literal table if necessary). %% literal(Literal, Dict) -> {Index,Dict'} @@ -236,13 +235,13 @@ string_table(#asm{strings=Strings,string_offset=Size}) -> -spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}. -lambda_table(#asm{locals=Loc0,lambdas=Lambdas0}) -> +lambda_table(#asm{locals=Loc0,lambdas={NumLambdas,Lambdas0}}) -> Lambdas1 = sofs:relation(Lambdas0), Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]), Lambdas2 = sofs:relative_product1(Lambdas1, Loc), Lambdas = [<> || {{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)], - {length(Lambdas),Lambdas}. + {NumLambdas,Lambdas}. %% Returns the literal table. %% literal_table(Dict) -> {NumLiterals, [<>,TermInExternalFormat]} -- cgit v1.2.3 From f9a3728566668a6ad54067fe347ab9055d351b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 16:27:53 +0100 Subject: v3_kernel: Speed up compilation of modules with many funs Using a map to store the number of free variables for funs instead of an orddict will speed up the v3_kernel pass for modules with a huge number of funs (such as NBAP-PDU-Contents in the asn1 test suite). --- lib/compiler/src/v3_kernel.erl | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index 7ee564683b..011748df3a 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -117,7 +117,7 @@ copy_anno(Kdst, Ksrc) -> fcount=0, %Fun counter ds=cerl_sets:new() :: cerl_sets:set(), %Defined variables funs=[], %Fun functions - free=[], %Free variables + free=#{}, %Free variables ws=[] :: [warning()], %Warnings. guard_refc=0}). %> 0 means in guard @@ -1837,14 +1837,17 @@ handle_reuse_anno_1(V, _St) -> V. %% get_free(Name, Arity, State) -> [Free]. %% store_free(Name, Arity, [Free], State) -> State. -get_free(F, A, St) -> - case orddict:find({F,A}, St#kern.free) of - {ok,Val} -> Val; - error -> [] +get_free(F, A, #kern{free=FreeMap}) -> + Key = {F,A}, + case FreeMap of + #{Key:=Val} -> Val; + _ -> [] end. -store_free(F, A, Free, St) -> - St#kern{free=orddict:store({F,A}, Free, St#kern.free)}. +store_free(F, A, Free, #kern{free=FreeMap0}=St) -> + Key = {F,A}, + FreeMap = FreeMap0#{Key=>Free}, + St#kern{free=FreeMap}. break_rets({break,Rs}) -> Rs; break_rets(return) -> []. -- cgit v1.2.3 From 37e598c1784595f8e10924ac2460d71c0c251c2c Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 10 Nov 2015 16:04:29 +0100 Subject: ssh: add better error handling in ssh_file ssh_file:lookup_user_key_fd and ssh_file:lookup_host_key --- lib/ssh/src/ssh_file.erl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index c087ce14d7..2f16a31cba 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -221,9 +221,11 @@ do_lookup_host_key(KeyToMatch, Host, Alg, Opts) -> {ok, Fd} -> Res = lookup_host_key_fd(Fd, KeyToMatch, Host, Alg), file:close(Fd), - {ok, Res}; - {error, enoent} -> {error, not_found}; - Error -> Error + Res; + {error, enoent} -> + {error, not_found}; + Error -> + Error end. identity_key_filename('ssh-dss' ) -> "id_dsa"; @@ -242,6 +244,9 @@ lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) -> case io:get_line(Fd, '') of eof -> {error, not_found}; + {error,Error} -> + %% Rare... For example NFS errors + {error,Error}; Line -> case ssh_decode_line(Line, known_hosts) of [{Key, Attributes}] -> @@ -262,7 +267,7 @@ handle_host(Fd, KeyToMatch, Host, HostList, Key, KeyType) -> Host1 = host_name(Host), case lists:member(Host1, HostList) andalso key_match(Key, KeyType) of true when KeyToMatch == Key -> - Key; + {ok,Key}; _ -> lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) end. @@ -309,6 +314,9 @@ lookup_user_key_fd(Fd, Key) -> case io:get_line(Fd, '') of eof -> {error, not_found}; + {error,Error} -> + %% Rare... For example NFS errors + {error,Error}; Line -> case ssh_decode_line(Line, auth_keys) of [{AuthKey, _}] -> -- cgit v1.2.3 From 3d719a5bc849e2c3279d71c84285c2da3af9e28d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 10 Nov 2015 12:26:50 +0100 Subject: ssh: document function dependencies in ssh_connection.erl --- lib/ssh/doc/src/ssh_connection.xml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml index 9a7bb09b12..7e7cfad90d 100644 --- a/lib/ssh/doc/src/ssh_connection.xml +++ b/lib/ssh/doc/src/ssh_connection.xml @@ -373,6 +373,9 @@

Is to be called by client- and server-channel processes to send data to each other.

+

The function subsystem/4 and subsequent + calls of send/3,4,5 must be executed in the same process. +

@@ -454,6 +457,9 @@

Is to be called by a client-channel process for requesting to execute a predefined subsystem on the server.

+

The function subsystem/4 and subsequent calls of + send/3,4,5 must be executed in the same process. +

-- cgit v1.2.3 From 13b4186f902ca250b86ffffb11f79a2778b4d167 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 10 Nov 2015 12:29:44 +0100 Subject: ssh: removed pre-historic ssh specs from the doc-dir --- .../standard/draft-ietf-secsh-architecture-15.2.ps | 3315 ------------------ .../standard/draft-ietf-secsh-architecture-15.txt | 1624 --------- .../doc/standard/draft-ietf-secsh-connect-18.2.ps | 2557 -------------- .../doc/standard/draft-ietf-secsh-connect-18.txt | 1232 ------- .../doc/standard/draft-ietf-secsh-filexfer-02.2.ps | 2853 ---------------- .../doc/standard/draft-ietf-secsh-filexfer-02.txt | 1627 --------- .../doc/standard/draft-ietf-secsh-filexfer-03.2.ps | 3511 -------------------- .../doc/standard/draft-ietf-secsh-filexfer-03.txt | 1962 ----------- .../doc/standard/draft-ietf-secsh-filexfer-04.txt | 2130 ------------ .../standard/draft-ietf-secsh-transport-17.2.ps | 3205 ------------------ .../doc/standard/draft-ietf-secsh-transport-17.txt | 1624 --------- .../doc/standard/draft-ietf-secsh-userauth-18.2.ps | 1881 ----------- .../doc/standard/draft-ietf-secsh-userauth-18.txt | 896 ----- 13 files changed, 28417 deletions(-) delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps delete mode 100644 lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt (limited to 'lib') diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps deleted file mode 100644 index d766a933b4..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps +++ /dev/null @@ -1,3315 +0,0 @@ -%!PS-Adobe-3.0 -%%BoundingBox: 75 0 595 747 -%%Title: Enscript Output -%%For: Magnus Thoang -%%Creator: GNU enscript 1.6.1 -%%CreationDate: Fri Oct 31 13:31:26 2003 -%%Orientation: Portrait -%%Pages: 15 0 -%%DocumentMedia: A4 595 842 0 () () -%%DocumentNeededResources: (atend) -%%EndComments -%%BeginProlog -%%BeginProcSet: PStoPS 1 15 -userdict begin -[/showpage/erasepage/copypage]{dup where{pop dup load - type/operatortype eq{1 array cvx dup 0 3 index cvx put - bind def}{pop}ifelse}{pop}ifelse}forall -[/letter/legal/executivepage/a4/a4small/b5/com10envelope - /monarchenvelope/c5envelope/dlenvelope/lettersmall/note - /folio/quarto/a5]{dup where{dup wcheck{exch{}put} - {pop{}def}ifelse}{pop}ifelse}forall -/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put} - {pop def}ifelse}{def}ifelse -/PStoPSmatrix matrix currentmatrix def -/PStoPSxform matrix def/PStoPSclip{clippath}def -/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def -/initmatrix{matrix defaultmatrix setmatrix}bind def -/initclip[{matrix currentmatrix PStoPSmatrix setmatrix - [{currentpoint}stopped{$error/newerror false put{newpath}} - {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse] - {[/newpath cvx{/moveto cvx}{/lineto cvx} - {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop} - stopped{$error/errorname get/invalidaccess eq{cleartomark - $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop - /initclip dup load dup type dup/operatortype eq{pop exch pop} - {dup/arraytype eq exch/packedarraytype eq or - {dup xcheck{exch pop aload pop}{pop cvx}ifelse} - {pop cvx}ifelse}ifelse - {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def -/initgraphics{initmatrix newpath initclip 1 setlinewidth - 0 setlinecap 0 setlinejoin []0 setdash 0 setgray - 10 setmiterlimit}bind def -end -%%EndProcSet -%%BeginResource: procset Enscript-Prolog 1.6 1 -% -% Procedures. -% - -/_S { % save current state - /_s save def -} def -/_R { % restore from saved state - _s restore -} def - -/S { % showpage protecting gstate - gsave - showpage - grestore -} bind def - -/MF { % fontname newfontname -> - make a new encoded font - /newfontname exch def - /fontname exch def - - /fontdict fontname findfont def - /newfont fontdict maxlength dict def - - fontdict { - exch - dup /FID eq { - % skip FID pair - pop pop - } { - % copy to the new font dictionary - exch newfont 3 1 roll put - } ifelse - } forall - - newfont /FontName newfontname put - - % insert only valid encoding vectors - encoding_vector length 256 eq { - newfont /Encoding encoding_vector put - } if - - newfontname newfont definefont pop -} def - -/SF { % fontname width height -> - set a new font - /height exch def - /width exch def - - findfont - [width 0 0 height 0 0] makefont setfont -} def - -/SUF { % fontname width height -> - set a new user font - /height exch def - /width exch def - - /F-gs-user-font MF - /F-gs-user-font width height SF -} def - -/M {moveto} bind def -/s {show} bind def - -/Box { % x y w h -> - define box path - /d_h exch def /d_w exch def /d_y exch def /d_x exch def - d_x d_y moveto - d_w 0 rlineto - 0 d_h rlineto - d_w neg 0 rlineto - closepath -} def - -/bgs { % x y height blskip gray str -> - show string with bg color - /str exch def - /gray exch def - /blskip exch def - /height exch def - /y exch def - /x exch def - - gsave - x y blskip sub str stringwidth pop height Box - gray setgray - fill - grestore - x y M str s -} def - -% Highlight bars. -/highlight_bars { % nlines lineheight output_y_margin gray -> - - gsave - setgray - /ymarg exch def - /lineheight exch def - /nlines exch def - - % This 2 is just a magic number to sync highlight lines to text. - 0 d_header_y ymarg sub 2 sub translate - - /cw d_output_w cols div def - /nrows d_output_h ymarg 2 mul sub lineheight div cvi def - - % for each column - 0 1 cols 1 sub { - cw mul /xp exch def - - % for each rows - 0 1 nrows 1 sub { - /rn exch def - rn lineheight mul neg /yp exch def - rn nlines idiv 2 mod 0 eq { - % Draw highlight bar. 4 is just a magic indentation. - xp 4 add yp cw 8 sub lineheight neg Box fill - } if - } for - } for - - grestore -} def - -% Line highlight bar. -/line_highlight { % x y width height gray -> - - gsave - /gray exch def - Box gray setgray fill - grestore -} def - -% Column separator lines. -/column_lines { - gsave - .1 setlinewidth - 0 d_footer_h translate - /cw d_output_w cols div def - 1 1 cols 1 sub { - cw mul 0 moveto - 0 d_output_h rlineto stroke - } for - grestore -} def - -% Column borders. -/column_borders { - gsave - .1 setlinewidth - 0 d_footer_h moveto - 0 d_output_h rlineto - d_output_w 0 rlineto - 0 d_output_h neg rlineto - closepath stroke - grestore -} def - -% Do the actual underlay drawing -/draw_underlay { - ul_style 0 eq { - ul_str true charpath stroke - } { - ul_str show - } ifelse -} def - -% Underlay -/underlay { % - -> - - gsave - 0 d_page_h translate - d_page_h neg d_page_w atan rotate - - ul_gray setgray - ul_font setfont - /dw d_page_h dup mul d_page_w dup mul add sqrt def - ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto - draw_underlay - grestore -} def - -/user_underlay { % - -> - - gsave - ul_x ul_y translate - ul_angle rotate - ul_gray setgray - ul_font setfont - 0 0 ul_h_ptsize 2 div sub moveto - draw_underlay - grestore -} def - -% Page prefeed -/page_prefeed { % bool -> - - statusdict /prefeed known { - statusdict exch /prefeed exch put - } { - pop - } ifelse -} def - -% Wrapped line markers -/wrapped_line_mark { % x y charwith charheight type -> - - /type exch def - /h exch def - /w exch def - /y exch def - /x exch def - - type 2 eq { - % Black boxes (like TeX does) - gsave - 0 setlinewidth - x w 4 div add y M - 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto - closepath fill - grestore - } { - type 3 eq { - % Small arrows - gsave - .2 setlinewidth - x w 2 div add y h 2 div add M - w 4 div 0 rlineto - x w 4 div add y lineto stroke - - x w 4 div add w 8 div add y h 4 div add M - x w 4 div add y lineto - w 4 div h 8 div rlineto stroke - grestore - } { - % do nothing - } ifelse - } ifelse -} def - -% EPSF import. - -/BeginEPSF { - /b4_Inc_state save def % Save state for cleanup - /dict_count countdictstack def % Count objects on dict stack - /op_count count 1 sub def % Count objects on operand stack - userdict begin - /showpage { } def - 0 setgray 0 setlinecap - 1 setlinewidth 0 setlinejoin - 10 setmiterlimit [ ] 0 setdash newpath - /languagelevel where { - pop languagelevel - 1 ne { - false setstrokeadjust false setoverprint - } if - } if -} bind def - -/EndEPSF { - count op_count sub { pos } repeat % Clean up stacks - countdictstack dict_count sub { end } repeat - b4_Inc_state restore -} bind def - -% Check PostScript language level. -/languagelevel where { - pop /gs_languagelevel languagelevel def -} { - /gs_languagelevel 1 def -} ifelse -%%EndResource -%%BeginResource: procset Enscript-Encoding-88591 1.6 1 -/encoding_vector [ -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclam /quotedbl /numbersign -/dollar /percent /ampersand /quoteright -/parenleft /parenright /asterisk /plus -/comma /hyphen /period /slash -/zero /one /two /three -/four /five /six /seven -/eight /nine /colon /semicolon -/less /equal /greater /question -/at /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 /bracketleft -/backslash /bracketright /asciicircum /underscore -/quoteleft /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 /braceleft -/bar /braceright /tilde /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclamdown /cent /sterling -/currency /yen /brokenbar /section -/dieresis /copyright /ordfeminine /guillemotleft -/logicalnot /hyphen /registered /macron -/degree /plusminus /twosuperior /threesuperior -/acute /mu /paragraph /bullet -/cedilla /onesuperior /ordmasculine /guillemotright -/onequarter /onehalf /threequarters /questiondown -/Agrave /Aacute /Acircumflex /Atilde -/Adieresis /Aring /AE /Ccedilla -/Egrave /Eacute /Ecircumflex /Edieresis -/Igrave /Iacute /Icircumflex /Idieresis -/Eth /Ntilde /Ograve /Oacute -/Ocircumflex /Otilde /Odieresis /multiply -/Oslash /Ugrave /Uacute /Ucircumflex -/Udieresis /Yacute /Thorn /germandbls -/agrave /aacute /acircumflex /atilde -/adieresis /aring /ae /ccedilla -/egrave /eacute /ecircumflex /edieresis -/igrave /iacute /icircumflex /idieresis -/eth /ntilde /ograve /oacute -/ocircumflex /otilde /odieresis /divide -/oslash /ugrave /uacute /ucircumflex -/udieresis /yacute /thorn /ydieresis -] def -%%EndResource -%%EndProlog -%%BeginSetup -%%IncludeResource: font Courier-Bold -%%IncludeResource: font Courier -/HFpt_w 10 def -/HFpt_h 10 def -/Courier-Bold /HF-gs-font MF -/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def -/Courier /F-gs-font MF -/F-gs-font 10 10 SF -/#copies 1 def -/d_page_w 520 def -/d_page_h 747 def -/d_header_x 0 def -/d_header_y 747 def -/d_header_w 520 def -/d_header_h 0 def -/d_footer_x 0 def -/d_footer_y 0 def -/d_footer_w 520 def -/d_footer_h 0 def -/d_output_w 520 def -/d_output_h 747 def -/cols 1 def -userdict/PStoPSxform PStoPSmatrix matrix currentmatrix - matrix invertmatrix matrix concatmatrix - matrix invertmatrix put -%%EndSetup -%%Page: (0,1) 1 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 1 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 701 M -(Network Working Group T. Ylonen) s -5 690 M -(Internet-Draft SSH Communications Security Corp) s -5 679 M -(Expires: March 31, 2004 D. Moffat, Ed.) s -5 668 M -( Sun Microsystems, Inc) s -5 657 M -( Oct 2003) s -5 624 M -( SSH Protocol Architecture) s -5 613 M -( draft-ietf-secsh-architecture-15.txt) s -5 591 M -(Status of this Memo) s -5 569 M -( This document is an Internet-Draft and is in full conformance with) s -5 558 M -( all provisions of Section 10 of RFC2026.) s -5 536 M -( Internet-Drafts are working documents of the Internet Engineering) s -5 525 M -( Task Force \(IETF\), its areas, and its working groups. Note that other) s -5 514 M -( groups may also distribute working documents as Internet-Drafts.) s -5 492 M -( Internet-Drafts are draft documents valid for a maximum of six months) s -5 481 M -( and may be updated, replaced, or obsoleted by other documents at any) s -5 470 M -( time. It is inappropriate to use Internet-Drafts as reference) s -5 459 M -( material or to cite them other than as "work in progress.") s -5 437 M -( The list of current Internet-Drafts can be accessed at http://) s -5 426 M -( www.ietf.org/ietf/1id-abstracts.txt.) s -5 404 M -( The list of Internet-Draft Shadow Directories can be accessed at) s -5 393 M -( http://www.ietf.org/shadow.html.) s -5 371 M -( This Internet-Draft will expire on March 31, 2004.) s -5 349 M -(Copyright Notice) s -5 327 M -( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s -5 305 M -(Abstract) s -5 283 M -( SSH is a protocol for secure remote login and other secure network) s -5 272 M -( services over an insecure network. This document describes the) s -5 261 M -( architecture of the SSH protocol, as well as the notation and) s -5 250 M -( terminology used in SSH protocol documents. It also discusses the SSH) s -5 239 M -( algorithm naming system that allows local extensions. The SSH) s -5 228 M -( protocol consists of three major components: The Transport Layer) s -5 217 M -( Protocol provides server authentication, confidentiality, and) s -5 206 M -( integrity with perfect forward secrecy. The User Authentication) s -5 195 M -( Protocol authenticates the client to the server. The Connection) s -5 184 M -( Protocol multiplexes the encrypted tunnel into several logical) s -5 173 M -( channels. Details of these protocols are described in separate) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 1]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 2 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( documents.) s -5 668 M -(Table of Contents) s -5 646 M -( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 635 M -( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 624 M -( 3. Specification of Requirements . . . . . . . . . . . . . . . 3) s -5 613 M -( 4. Architecture . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 602 M -( 4.1 Host Keys . . . . . . . . . . . . . . . . . . . . . . . . . 4) s -5 591 M -( 4.2 Extensibility . . . . . . . . . . . . . . . . . . . . . . . 5) s -5 580 M -( 4.3 Policy Issues . . . . . . . . . . . . . . . . . . . . . . . 5) s -5 569 M -( 4.4 Security Properties . . . . . . . . . . . . . . . . . . . . 6) s -5 558 M -( 4.5 Packet Size and Overhead . . . . . . . . . . . . . . . . . . 6) s -5 547 M -( 4.6 Localization and Character Set Support . . . . . . . . . . . 7) s -5 536 M -( 5. Data Type Representations Used in the SSH Protocols . . . . 8) s -5 525 M -( 6. Algorithm Naming . . . . . . . . . . . . . . . . . . . . . . 10) s -5 514 M -( 7. Message Numbers . . . . . . . . . . . . . . . . . . . . . . 11) s -5 503 M -( 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . 11) s -5 492 M -( 9. Security Considerations . . . . . . . . . . . . . . . . . . 12) s -5 481 M -( 9.1 Pseudo-Random Number Generation . . . . . . . . . . . . . . 12) s -5 470 M -( 9.2 Transport . . . . . . . . . . . . . . . . . . . . . . . . . 13) s -5 459 M -( 9.2.1 Confidentiality . . . . . . . . . . . . . . . . . . . . . . 13) s -5 448 M -( 9.2.2 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 16) s -5 437 M -( 9.2.3 Replay . . . . . . . . . . . . . . . . . . . . . . . . . . . 16) s -5 426 M -( 9.2.4 Man-in-the-middle . . . . . . . . . . . . . . . . . . . . . 17) s -5 415 M -( 9.2.5 Denial-of-service . . . . . . . . . . . . . . . . . . . . . 19) s -5 404 M -( 9.2.6 Covert Channels . . . . . . . . . . . . . . . . . . . . . . 19) s -5 393 M -( 9.2.7 Forward Secrecy . . . . . . . . . . . . . . . . . . . . . . 20) s -5 382 M -( 9.3 Authentication Protocol . . . . . . . . . . . . . . . . . . 20) s -5 371 M -( 9.3.1 Weak Transport . . . . . . . . . . . . . . . . . . . . . . . 21) s -5 360 M -( 9.3.2 Debug messages . . . . . . . . . . . . . . . . . . . . . . . 21) s -5 349 M -( 9.3.3 Local security policy . . . . . . . . . . . . . . . . . . . 21) s -5 338 M -( 9.3.4 Public key authentication . . . . . . . . . . . . . . . . . 22) s -5 327 M -( 9.3.5 Password authentication . . . . . . . . . . . . . . . . . . 22) s -5 316 M -( 9.3.6 Host based authentication . . . . . . . . . . . . . . . . . 23) s -5 305 M -( 9.4 Connection protocol . . . . . . . . . . . . . . . . . . . . 23) s -5 294 M -( 9.4.1 End point security . . . . . . . . . . . . . . . . . . . . . 23) s -5 283 M -( 9.4.2 Proxy forwarding . . . . . . . . . . . . . . . . . . . . . . 23) s -5 272 M -( 9.4.3 X11 forwarding . . . . . . . . . . . . . . . . . . . . . . . 24) s -5 261 M -( Normative References . . . . . . . . . . . . . . . . . . . . 24) s -5 250 M -( Informative References . . . . . . . . . . . . . . . . . . . 25) s -5 239 M -( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 27) s -5 228 M -( Intellectual Property and Copyright Statements . . . . . . . 28) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 2]) s -_R -S -PStoPSsaved restore -%%Page: (2,3) 2 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 3 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -(1. Contributors) s -5 668 M -( The major original contributors of this document were: Tatu Ylonen,) s -5 657 M -( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s -5 646 M -( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s -5 635 M -( Jyvaskyla\)) s -5 613 M -( The document editor is: Darren.Moffat@Sun.COM. Comments on this) s -5 602 M -( internet draft should be sent to the IETF SECSH working group,) s -5 591 M -( details at: http://ietf.org/html.charters/secsh-charter.html) s -5 569 M -(2. Introduction) s -5 547 M -( SSH is a protocol for secure remote login and other secure network) s -5 536 M -( services over an insecure network. It consists of three major) s -5 525 M -( components:) s -5 514 M -( o The Transport Layer Protocol [SSH-TRANS] provides server) s -5 503 M -( authentication, confidentiality, and integrity. It may optionally) s -5 492 M -( also provide compression. The transport layer will typically be) s -5 481 M -( run over a TCP/IP connection, but might also be used on top of any) s -5 470 M -( other reliable data stream.) s -5 459 M -( o The User Authentication Protocol [SSH-USERAUTH] authenticates the) s -5 448 M -( client-side user to the server. It runs over the transport layer) s -5 437 M -( protocol.) s -5 426 M -( o The Connection Protocol [SSH-CONNECT] multiplexes the encrypted) s -5 415 M -( tunnel into several logical channels. It runs over the user) s -5 404 M -( authentication protocol.) s -5 382 M -( The client sends a service request once a secure transport layer) s -5 371 M -( connection has been established. A second service request is sent) s -5 360 M -( after user authentication is complete. This allows new protocols to) s -5 349 M -( be defined and coexist with the protocols listed above.) s -5 327 M -( The connection protocol provides channels that can be used for a wide) s -5 316 M -( range of purposes. Standard methods are provided for setting up) s -5 305 M -( secure interactive shell sessions and for forwarding \("tunneling"\)) s -5 294 M -( arbitrary TCP/IP ports and X11 connections.) s -5 272 M -(3. Specification of Requirements) s -5 250 M -( All documents related to the SSH protocols shall use the keywords) s -5 239 M -( "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",) s -5 228 M -( "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" to describe) s -5 217 M -( requirements. They are to be interpreted as described in [RFC2119].) s -5 195 M -(4. Architecture) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 3]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 4 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -(4.1 Host Keys) s -5 668 M -( Each server host SHOULD have a host key. Hosts MAY have multiple) s -5 657 M -( host keys using multiple different algorithms. Multiple hosts MAY) s -5 646 M -( share the same host key. If a host has keys at all, it MUST have at) s -5 635 M -( least one key using each REQUIRED public key algorithm \(DSS) s -5 624 M -( [FIPS-186]\).) s -5 602 M -( The server host key is used during key exchange to verify that the) s -5 591 M -( client is really talking to the correct server. For this to be) s -5 580 M -( possible, the client must have a priori knowledge of the server's) s -5 569 M -( public host key.) s -5 547 M -( Two different trust models can be used:) s -5 536 M -( o The client has a local database that associates each host name \(as) s -5 525 M -( typed by the user\) with the corresponding public host key. This) s -5 514 M -( method requires no centrally administered infrastructure, and no) s -5 503 M -( third-party coordination. The downside is that the database of) s -5 492 M -( name-to-key associations may become burdensome to maintain.) s -5 481 M -( o The host name-to-key association is certified by some trusted) s -5 470 M -( certification authority. The client only knows the CA root key,) s -5 459 M -( and can verify the validity of all host keys certified by accepted) s -5 448 M -( CAs.) s -5 426 M -( The second alternative eases the maintenance problem, since) s -5 415 M -( ideally only a single CA key needs to be securely stored on the) s -5 404 M -( client. On the other hand, each host key must be appropriately) s -5 393 M -( certified by a central authority before authorization is possible.) s -5 382 M -( Also, a lot of trust is placed on the central infrastructure.) s -5 360 M -( The protocol provides the option that the server name - host key) s -5 349 M -( association is not checked when connecting to the host for the first) s -5 338 M -( time. This allows communication without prior communication of host) s -5 327 M -( keys or certification. The connection still provides protection) s -5 316 M -( against passive listening; however, it becomes vulnerable to active) s -5 305 M -( man-in-the-middle attacks. Implementations SHOULD NOT normally allow) s -5 294 M -( such connections by default, as they pose a potential security) s -5 283 M -( problem. However, as there is no widely deployed key infrastructure) s -5 272 M -( available on the Internet yet, this option makes the protocol much) s -5 261 M -( more usable during the transition time until such an infrastructure) s -5 250 M -( emerges, while still providing a much higher level of security than) s -5 239 M -( that offered by older solutions \(e.g. telnet [RFC-854] and rlogin) s -5 228 M -( [RFC-1282]\).) s -5 206 M -( Implementations SHOULD try to make the best effort to check host) s -5 195 M -( keys. An example of a possible strategy is to only accept a host key) s -5 184 M -( without checking the first time a host is connected, save the key in) s -5 173 M -( a local database, and compare against that key on all future) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 4]) s -_R -S -PStoPSsaved restore -%%Page: (4,5) 3 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 5 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( connections to that host.) s -5 668 M -( Implementations MAY provide additional methods for verifying the) s -5 657 M -( correctness of host keys, e.g. a hexadecimal fingerprint derived from) s -5 646 M -( the SHA-1 hash of the public key. Such fingerprints can easily be) s -5 635 M -( verified by using telephone or other external communication channels.) s -5 613 M -( All implementations SHOULD provide an option to not accept host keys) s -5 602 M -( that cannot be verified.) s -5 580 M -( We believe that ease of use is critical to end-user acceptance of) s -5 569 M -( security solutions, and no improvement in security is gained if the) s -5 558 M -( new solutions are not used. Thus, providing the option not to check) s -5 547 M -( the server host key is believed to improve the overall security of) s -5 536 M -( the Internet, even though it reduces the security of the protocol in) s -5 525 M -( configurations where it is allowed.) s -5 503 M -(4.2 Extensibility) s -5 481 M -( We believe that the protocol will evolve over time, and some) s -5 470 M -( organizations will want to use their own encryption, authentication) s -5 459 M -( and/or key exchange methods. Central registration of all extensions) s -5 448 M -( is cumbersome, especially for experimental or classified features.) s -5 437 M -( On the other hand, having no central registration leads to conflicts) s -5 426 M -( in method identifiers, making interoperability difficult.) s -5 404 M -( We have chosen to identify algorithms, methods, formats, and) s -5 393 M -( extension protocols with textual names that are of a specific format.) s -5 382 M -( DNS names are used to create local namespaces where experimental or) s -5 371 M -( classified extensions can be defined without fear of conflicts with) s -5 360 M -( other implementations.) s -5 338 M -( One design goal has been to keep the base protocol as simple as) s -5 327 M -( possible, and to require as few algorithms as possible. However, all) s -5 316 M -( implementations MUST support a minimal set of algorithms to ensure) s -5 305 M -( interoperability \(this does not imply that the local policy on all) s -5 294 M -( hosts would necessary allow these algorithms\). The mandatory) s -5 283 M -( algorithms are specified in the relevant protocol documents.) s -5 261 M -( Additional algorithms, methods, formats, and extension protocols can) s -5 250 M -( be defined in separate drafts. See Section Algorithm Naming \(Section) s -5 239 M -( 6\) for more information.) s -5 217 M -(4.3 Policy Issues) s -5 195 M -( The protocol allows full negotiation of encryption, integrity, key) s -5 184 M -( exchange, compression, and public key algorithms and formats.) s -5 173 M -( Encryption, integrity, public key, and compression algorithms can be) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 5]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 6 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( different for each direction.) s -5 668 M -( The following policy issues SHOULD be addressed in the configuration) s -5 657 M -( mechanisms of each implementation:) s -5 646 M -( o Encryption, integrity, and compression algorithms, separately for) s -5 635 M -( each direction. The policy MUST specify which is the preferred) s -5 624 M -( algorithm \(e.g. the first algorithm listed in each category\).) s -5 613 M -( o Public key algorithms and key exchange method to be used for host) s -5 602 M -( authentication. The existence of trusted host keys for different) s -5 591 M -( public key algorithms also affects this choice.) s -5 580 M -( o The authentication methods that are to be required by the server) s -5 569 M -( for each user. The server's policy MAY require multiple) s -5 558 M -( authentication for some or all users. The required algorithms MAY) s -5 547 M -( depend on the location where the user is trying to log in from.) s -5 536 M -( o The operations that the user is allowed to perform using the) s -5 525 M -( connection protocol. Some issues are related to security; for) s -5 514 M -( example, the policy SHOULD NOT allow the server to start sessions) s -5 503 M -( or run commands on the client machine, and MUST NOT allow) s -5 492 M -( connections to the authentication agent unless forwarding such) s -5 481 M -( connections has been requested. Other issues, such as which TCP/) s -5 470 M -( IP ports can be forwarded and by whom, are clearly issues of local) s -5 459 M -( policy. Many of these issues may involve traversing or bypassing) s -5 448 M -( firewalls, and are interrelated with the local security policy.) s -5 426 M -(4.4 Security Properties) s -5 404 M -( The primary goal of the SSH protocol is improved security on the) s -5 393 M -( Internet. It attempts to do this in a way that is easy to deploy,) s -5 382 M -( even at the cost of absolute security.) s -5 371 M -( o All encryption, integrity, and public key algorithms used are) s -5 360 M -( well-known, well-established algorithms.) s -5 349 M -( o All algorithms are used with cryptographically sound key sizes) s -5 338 M -( that are believed to provide protection against even the strongest) s -5 327 M -( cryptanalytic attacks for decades.) s -5 316 M -( o All algorithms are negotiated, and in case some algorithm is) s -5 305 M -( broken, it is easy to switch to some other algorithm without) s -5 294 M -( modifying the base protocol.) s -5 272 M -( Specific concessions were made to make wide-spread fast deployment) s -5 261 M -( easier. The particular case where this comes up is verifying that) s -5 250 M -( the server host key really belongs to the desired host; the protocol) s -5 239 M -( allows the verification to be left out \(but this is NOT RECOMMENDED\).) s -5 228 M -( This is believed to significantly improve usability in the short) s -5 217 M -( term, until widespread Internet public key infrastructures emerge.) s -5 195 M -(4.5 Packet Size and Overhead) s -5 173 M -( Some readers will worry about the increase in packet size due to new) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 6]) s -_R -S -PStoPSsaved restore -%%Page: (6,7) 4 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 7 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( headers, padding, and MAC. The minimum packet size is in the order) s -5 679 M -( of 28 bytes \(depending on negotiated algorithms\). The increase is) s -5 668 M -( negligible for large packets, but very significant for one-byte) s -5 657 M -( packets \(telnet-type sessions\). There are, however, several factors) s -5 646 M -( that make this a non-issue in almost all cases:) s -5 635 M -( o The minimum size of a TCP/IP header is 32 bytes. Thus, the) s -5 624 M -( increase is actually from 33 to 51 bytes \(roughly\).) s -5 613 M -( o The minimum size of the data field of an Ethernet packet is 46) s -5 602 M -( bytes [RFC-894]. Thus, the increase is no more than 5 bytes. When) s -5 591 M -( Ethernet headers are considered, the increase is less than 10) s -5 580 M -( percent.) s -5 569 M -( o The total fraction of telnet-type data in the Internet is) s -5 558 M -( negligible, even with increased packet sizes.) s -5 536 M -( The only environment where the packet size increase is likely to have) s -5 525 M -( a significant effect is PPP [RFC-1134] over slow modem lines \(PPP) s -5 514 M -( compresses the TCP/IP headers, emphasizing the increase in packet) s -5 503 M -( size\). However, with modern modems, the time needed to transfer is in) s -5 492 M -( the order of 2 milliseconds, which is a lot faster than people can) s -5 481 M -( type.) s -5 459 M -( There are also issues related to the maximum packet size. To) s -5 448 M -( minimize delays in screen updates, one does not want excessively) s -5 437 M -( large packets for interactive sessions. The maximum packet size is) s -5 426 M -( negotiated separately for each channel.) s -5 404 M -(4.6 Localization and Character Set Support) s -5 382 M -( For the most part, the SSH protocols do not directly pass text that) s -5 371 M -( would be displayed to the user. However, there are some places where) s -5 360 M -( such data might be passed. When applicable, the character set for the) s -5 349 M -( data MUST be explicitly specified. In most places, ISO 10646 with) s -5 338 M -( UTF-8 encoding is used [RFC-2279]. When applicable, a field is also) s -5 327 M -( provided for a language tag [RFC-3066].) s -5 305 M -( One big issue is the character set of the interactive session. There) s -5 294 M -( is no clear solution, as different applications may display data in) s -5 283 M -( different formats. Different types of terminal emulation may also be) s -5 272 M -( employed in the client, and the character set to be used is) s -5 261 M -( effectively determined by the terminal emulation. Thus, no place is) s -5 250 M -( provided for directly specifying the character set or encoding for) s -5 239 M -( terminal session data. However, the terminal emulation type \(e.g.) s -5 228 M -( "vt100"\) is transmitted to the remote site, and it implicitly) s -5 217 M -( specifies the character set and encoding. Applications typically use) s -5 206 M -( the terminal type to determine what character set they use, or the) s -5 195 M -( character set is determined using some external means. The terminal) s -5 184 M -( emulation may also allow configuring the default character set. In) s -5 173 M -( any case, the character set for the terminal session is considered) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 7]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 8 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( primarily a client local issue.) s -5 668 M -( Internal names used to identify algorithms or protocols are normally) s -5 657 M -( never displayed to users, and must be in US-ASCII.) s -5 635 M -( The client and server user names are inherently constrained by what) s -5 624 M -( the server is prepared to accept. They might, however, occasionally) s -5 613 M -( be displayed in logs, reports, etc. They MUST be encoded using ISO) s -5 602 M -( 10646 UTF-8, but other encodings may be required in some cases. It) s -5 591 M -( is up to the server to decide how to map user names to accepted user) s -5 580 M -( names. Straight bit-wise binary comparison is RECOMMENDED.) s -5 558 M -( For localization purposes, the protocol attempts to minimize the) s -5 547 M -( number of textual messages transmitted. When present, such messages) s -5 536 M -( typically relate to errors, debugging information, or some externally) s -5 525 M -( configured data. For data that is normally displayed, it SHOULD be) s -5 514 M -( possible to fetch a localized message instead of the transmitted) s -5 503 M -( message by using a numerical code. The remaining messages SHOULD be) s -5 492 M -( configurable.) s -5 470 M -(5. Data Type Representations Used in the SSH Protocols) s -5 459 M -( byte) s -5 437 M -( A byte represents an arbitrary 8-bit value \(octet\) [RFC-1700].) s -5 426 M -( Fixed length data is sometimes represented as an array of bytes,) s -5 415 M -( written byte[n], where n is the number of bytes in the array.) s -5 393 M -( boolean) s -5 371 M -( A boolean value is stored as a single byte. The value 0) s -5 360 M -( represents FALSE, and the value 1 represents TRUE. All non-zero) s -5 349 M -( values MUST be interpreted as TRUE; however, applications MUST NOT) s -5 338 M -( store values other than 0 and 1.) s -5 316 M -( uint32) s -5 294 M -( Represents a 32-bit unsigned integer. Stored as four bytes in the) s -5 283 M -( order of decreasing significance \(network byte order\). For) s -5 272 M -( example, the value 699921578 \(0x29b7f4aa\) is stored as 29 b7 f4) s -5 261 M -( aa.) s -5 239 M -( uint64) s -5 217 M -( Represents a 64-bit unsigned integer. Stored as eight bytes in) s -5 206 M -( the order of decreasing significance \(network byte order\).) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 8]) s -_R -S -PStoPSsaved restore -%%Page: (8,9) 5 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 9 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( string) s -5 668 M -( Arbitrary length binary string. Strings are allowed to contain) s -5 657 M -( arbitrary binary data, including null characters and 8-bit) s -5 646 M -( characters. They are stored as a uint32 containing its length) s -5 635 M -( \(number of bytes that follow\) and zero \(= empty string\) or more) s -5 624 M -( bytes that are the value of the string. Terminating null) s -5 613 M -( characters are not used.) s -5 591 M -( Strings are also used to store text. In that case, US-ASCII is) s -5 580 M -( used for internal names, and ISO-10646 UTF-8 for text that might) s -5 569 M -( be displayed to the user. The terminating null character SHOULD) s -5 558 M -( NOT normally be stored in the string.) s -5 536 M -( For example, the US-ASCII string "testing" is represented as 00 00) s -5 525 M -( 00 07 t e s t i n g. The UTF8 mapping does not alter the encoding) s -5 514 M -( of US-ASCII characters.) s -5 492 M -( mpint) s -5 470 M -( Represents multiple precision integers in two's complement format,) s -5 459 M -( stored as a string, 8 bits per byte, MSB first. Negative numbers) s -5 448 M -( have the value 1 as the most significant bit of the first byte of) s -5 437 M -( the data partition. If the most significant bit would be set for a) s -5 426 M -( positive number, the number MUST be preceded by a zero byte.) s -5 415 M -( Unnecessary leading bytes with the value 0 or 255 MUST NOT be) s -5 404 M -( included. The value zero MUST be stored as a string with zero) s -5 393 M -( bytes of data.) s -5 371 M -( By convention, a number that is used in modular computations in) s -5 360 M -( Z_n SHOULD be represented in the range 0 <= x < n.) s -5 338 M -( Examples:) s -5 327 M -( value \(hex\) representation \(hex\)) s -5 316 M -( ---------------------------------------------------------------) s -5 305 M -( 0 00 00 00 00) s -5 294 M -( 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7) s -5 283 M -( 80 00 00 00 02 00 80) s -5 272 M -( -1234 00 00 00 02 ed cc) s -5 261 M -( -deadbeef 00 00 00 05 ff 21 52 41 11) s -5 217 M -( name-list) s -5 195 M -( A string containing a comma separated list of names. A name list) s -5 184 M -( is represented as a uint32 containing its length \(number of bytes) s -5 173 M -( that follow\) followed by a comma-separated list of zero or more) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 9]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 10 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( names. A name MUST be non-zero length, and it MUST NOT contain a) s -5 679 M -( comma \(','\). Context may impose additional restrictions on the) s -5 668 M -( names; for example, the names in a list may have to be valid) s -5 657 M -( algorithm identifier \(see Algorithm Naming below\), or [RFC-3066]) s -5 646 M -( language tags. The order of the names in a list may or may not be) s -5 635 M -( significant, also depending on the context where the list is is) s -5 624 M -( used. Terminating NUL characters are not used, neither for the) s -5 613 M -( individual names, nor for the list as a whole.) s -5 591 M -( Examples:) s -5 580 M -( value representation \(hex\)) s -5 569 M -( ---------------------------------------) s -5 558 M -( \(\), the empty list 00 00 00 00) s -5 547 M -( \("zlib"\) 00 00 00 04 7a 6c 69 62) s -5 536 M -( \("zlib", "none"\) 00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65) s -5 481 M -(6. Algorithm Naming) s -5 459 M -( The SSH protocols refer to particular hash, encryption, integrity,) s -5 448 M -( compression, and key exchange algorithms or protocols by names.) s -5 437 M -( There are some standard algorithms that all implementations MUST) s -5 426 M -( support. There are also algorithms that are defined in the protocol) s -5 415 M -( specification but are OPTIONAL. Furthermore, it is expected that) s -5 404 M -( some organizations will want to use their own algorithms.) s -5 382 M -( In this protocol, all algorithm identifiers MUST be printable) s -5 371 M -( US-ASCII non-empty strings no longer than 64 characters. Names MUST) s -5 360 M -( be case-sensitive.) s -5 338 M -( There are two formats for algorithm names:) s -5 327 M -( o Names that do not contain an at-sign \(@\) are reserved to be) s -5 316 M -( assigned by IETF consensus \(RFCs\). Examples include `3des-cbc',) s -5 305 M -( `sha-1', `hmac-sha1', and `zlib' \(the quotes are not part of the) s -5 294 M -( name\). Names of this format MUST NOT be used without first) s -5 283 M -( registering them. Registered names MUST NOT contain an at-sign) s -5 272 M -( \(@\) or a comma \(,\).) s -5 261 M -( o Anyone can define additional algorithms by using names in the) s -5 250 M -( format name@domainname, e.g. "ourcipher-cbc@example.com". The) s -5 239 M -( format of the part preceding the at sign is not specified; it MUST) s -5 228 M -( consist of US-ASCII characters except at-sign and comma. The part) s -5 217 M -( following the at-sign MUST be a valid fully qualified internet) s -5 206 M -( domain name [RFC-1034] controlled by the person or organization) s -5 195 M -( defining the name. It is up to each domain how it manages its) s -5 184 M -( local namespace.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 10]) s -_R -S -PStoPSsaved restore -%%Page: (10,11) 6 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 11 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -(7. Message Numbers) s -5 668 M -( SSH packets have message numbers in the range 1 to 255. These numbers) s -5 657 M -( have been allocated as follows:) s -5 624 M -( Transport layer protocol:) s -5 602 M -( 1 to 19 Transport layer generic \(e.g. disconnect, ignore, debug,) s -5 591 M -( etc.\)) s -5 580 M -( 20 to 29 Algorithm negotiation) s -5 569 M -( 30 to 49 Key exchange method specific \(numbers can be reused for) s -5 558 M -( different authentication methods\)) s -5 536 M -( User authentication protocol:) s -5 514 M -( 50 to 59 User authentication generic) s -5 503 M -( 60 to 79 User authentication method specific \(numbers can be) s -5 492 M -( reused for different authentication methods\)) s -5 470 M -( Connection protocol:) s -5 448 M -( 80 to 89 Connection protocol generic) s -5 437 M -( 90 to 127 Channel related messages) s -5 415 M -( Reserved for client protocols:) s -5 393 M -( 128 to 191 Reserved) s -5 371 M -( Local extensions:) s -5 349 M -( 192 to 255 Local extensions) s -5 305 M -(8. IANA Considerations) s -5 283 M -( The initial state of the IANA registry is detailed in [SSH-NUMBERS].) s -5 261 M -( Allocation of the following types of names in the SSH protocols is) s -5 250 M -( assigned by IETF consensus:) s -5 239 M -( o SSH encryption algorithm names,) s -5 228 M -( o SSH MAC algorithm names,) s -5 217 M -( o SSH public key algorithm names \(public key algorithm also implies) s -5 206 M -( encoding and signature/encryption capability\),) s -5 195 M -( o SSH key exchange method names, and) s -5 184 M -( o SSH protocol \(service\) names.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 11]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 12 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( These names MUST be printable US-ASCII strings, and MUST NOT contain) s -5 679 M -( the characters at-sign \('@'\), comma \(','\), or whitespace or control) s -5 668 M -( characters \(ASCII codes 32 or less\). Names are case-sensitive, and) s -5 657 M -( MUST NOT be longer than 64 characters.) s -5 635 M -( Names with the at-sign \('@'\) in them are allocated by the owner of) s -5 624 M -( DNS name after the at-sign \(hierarchical allocation in [RFC-2343]\),) s -5 613 M -( otherwise the same restrictions as above.) s -5 591 M -( Each category of names listed above has a separate namespace.) s -5 580 M -( However, using the same name in multiple categories SHOULD be avoided) s -5 569 M -( to minimize confusion.) s -5 547 M -( Message numbers \(see Section Message Numbers \(Section 7\)\) in the) s -5 536 M -( range of 0..191 are allocated via IETF consensus; message numbers in) s -5 525 M -( the 192..255 range \(the "Local extensions" set\) are reserved for) s -5 514 M -( private use.) s -5 492 M -(9. Security Considerations) s -5 470 M -( In order to make the entire body of Security Considerations more) s -5 459 M -( accessible, Security Considerations for the transport,) s -5 448 M -( authentication, and connection documents have been gathered here.) s -5 426 M -( The transport protocol [1] provides a confidential channel over an) s -5 415 M -( insecure network. It performs server host authentication, key) s -5 404 M -( exchange, encryption, and integrity protection. It also derives a) s -5 393 M -( unique session id that may be used by higher-level protocols.) s -5 371 M -( The authentication protocol [2] provides a suite of mechanisms which) s -5 360 M -( can be used to authenticate the client user to the server.) s -5 349 M -( Individual mechanisms specified in the in authentication protocol use) s -5 338 M -( the session id provided by the transport protocol and/or depend on) s -5 327 M -( the security and integrity guarantees of the transport protocol.) s -5 305 M -( The connection protocol [3] specifies a mechanism to multiplex) s -5 294 M -( multiple streams [channels] of data over the confidential and) s -5 283 M -( authenticated transport. It also specifies channels for accessing an) s -5 272 M -( interactive shell, for 'proxy-forwarding' various external protocols) s -5 261 M -( over the secure transport \(including arbitrary TCP/IP protocols\), and) s -5 250 M -( for accessing secure 'subsystems' on the server host.) s -5 228 M -(9.1 Pseudo-Random Number Generation) s -5 206 M -( This protocol binds each session key to the session by including) s -5 195 M -( random, session specific data in the hash used to produce session) s -5 184 M -( keys. Special care should be taken to ensure that all of the random) s -5 173 M -( numbers are of good quality. If the random data here \(e.g., DH) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 12]) s -_R -S -PStoPSsaved restore -%%Page: (12,13) 7 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 13 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( parameters\) are pseudo-random then the pseudo-random number generator) s -5 679 M -( should be cryptographically secure \(i.e., its next output not easily) s -5 668 M -( guessed even when knowing all previous outputs\) and, furthermore,) s -5 657 M -( proper entropy needs to be added to the pseudo-random number) s -5 646 M -( generator. RFC 1750 [1750] offers suggestions for sources of random) s -5 635 M -( numbers and entropy. Implementors should note the importance of) s -5 624 M -( entropy and the well-meant, anecdotal warning about the difficulty in) s -5 613 M -( properly implementing pseudo-random number generating functions.) s -5 591 M -( The amount of entropy available to a given client or server may) s -5 580 M -( sometimes be less than what is required. In this case one must) s -5 569 M -( either resort to pseudo-random number generation regardless of) s -5 558 M -( insufficient entropy or refuse to run the protocol. The latter is) s -5 547 M -( preferable.) s -5 525 M -(9.2 Transport) s -5 503 M -(9.2.1 Confidentiality) s -5 481 M -( It is beyond the scope of this document and the Secure Shell Working) s -5 470 M -( Group to analyze or recommend specific ciphers other than the ones) s -5 459 M -( which have been established and accepted within the industry. At the) s -5 448 M -( time of this writing, ciphers commonly in use include 3DES, ARCFOUR,) s -5 437 M -( twofish, serpent and blowfish. AES has been accepted by The) s -5 426 M -( published as a US Federal Information Processing Standards [FIPS-197]) s -5 415 M -( and the cryptographic community as being acceptable for this purpose) s -5 404 M -( as well has accepted AES. As always, implementors and users should) s -5 393 M -( check current literature to ensure that no recent vulnerabilities) s -5 382 M -( have been found in ciphers used within products. Implementors should) s -5 371 M -( also check to see which ciphers are considered to be relatively) s -5 360 M -( stronger than others and should recommend their use to users over) s -5 349 M -( relatively weaker ciphers. It would be considered good form for an) s -5 338 M -( implementation to politely and unobtrusively notify a user that a) s -5 327 M -( stronger cipher is available and should be used when a weaker one is) s -5 316 M -( actively chosen.) s -5 294 M -( The "none" cipher is provided for debugging and SHOULD NOT be used) s -5 283 M -( except for that purpose. It's cryptographic properties are) s -5 272 M -( sufficiently described in RFC 2410, which will show that its use does) s -5 261 M -( not meet the intent of this protocol.) s -5 239 M -( The relative merits of these and other ciphers may also be found in) s -5 228 M -( current literature. Two references that may provide information on) s -5 217 M -( the subject are [SCHNEIER] and [KAUFMAN,PERLMAN,SPECINER]. Both of) s -5 206 M -( these describe the CBC mode of operation of certain ciphers and the) s -5 195 M -( weakness of this scheme. Essentially, this mode is theoretically) s -5 184 M -( vulnerable to chosen cipher-text attacks because of the high) s -5 173 M -( predictability of the start of packet sequence. However, this attack) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 13]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 14 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( is still deemed difficult and not considered fully practicable) s -5 679 M -( especially if relatively longer block sizes are used.) s -5 657 M -( Additionally, another CBC mode attack may be mitigated through the) s -5 646 M -( insertion of packets containing SSH_MSG_IGNORE. Without this) s -5 635 M -( technique, a specific attack may be successful. For this attack) s -5 624 M -( \(commonly known as the Rogaway attack) s -5 613 M -( [ROGAWAY],[DAI],[BELLARE,KOHNO,NAMPREMPRE]\) to work, the attacker) s -5 602 M -( would need to know the IV of the next block that is going to be) s -5 591 M -( encrypted. In CBC mode that is the output of the encryption of the) s -5 580 M -( previous block. If the attacker does not have any way to see the) s -5 569 M -( packet yet \(i.e it is in the internal buffers of the ssh) s -5 558 M -( implementation or even in the kernel\) then this attack will not work.) s -5 547 M -( If the last packet has been sent out to the network \(i.e the attacker) s -5 536 M -( has access to it\) then he can use the attack.) s -5 514 M -( In the optimal case an implementor would need to add an extra packet) s -5 503 M -( only if the packet has been sent out onto the network and there are) s -5 492 M -( no other packets waiting for transmission. Implementors may wish to) s -5 481 M -( check to see if there are any unsent packets awaiting transmission,) s -5 470 M -( but unfortunately it is not normally easy to obtain this information) s -5 459 M -( from the kernel or buffers. If there are not, then a packet) s -5 448 M -( containing SSH_MSG_IGNORE SHOULD be sent. If a new packet is added) s -5 437 M -( to the stream every time the attacker knows the IV that is supposed) s -5 426 M -( to be used for the next packet, then the attacker will not be able to) s -5 415 M -( guess the correct IV, thus the attack will never be successfull.) s -5 393 M -( As an example, consider the following case:) s -5 360 M -( Client Server) s -5 349 M -( ------ ------) s -5 338 M -( TCP\(seq=x, len=500\) ->) s -5 327 M -( contains Record 1) s -5 305 M -( [500 ms passes, no ACK]) s -5 283 M -( TCP\(seq=x, len=1000\) ->) s -5 272 M -( contains Records 1,2) s -5 250 M -( ACK) s -5 217 M -( 1. The Nagle algorithm + TCP retransmits mean that the two records) s -5 206 M -( get coalesced into a single TCP segment) s -5 195 M -( 2. Record 2 is *not* at the beginning of the TCP segment and never) s -5 184 M -( will be, since it gets ACKed.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 14]) s -_R -S -PStoPSsaved restore -%%Page: (14,15) 8 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 15 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( 3. Yet, the attack is possible because Record 1 has already been) s -5 679 M -( seen.) s -5 657 M -( As this example indicates, it's totally unsafe to use the existence) s -5 646 M -( of unflushed data in the TCP buffers proper as a guide to whether you) s -5 635 M -( need an empty packet, since when you do the second write\(\), the) s -5 624 M -( buffers will contain the un-ACKed Record 1.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 15]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 16 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( On the other hand, it's perfectly safe to have the following) s -5 679 M -( situation:) s -5 646 M -( Client Server) s -5 635 M -( ------ ------) s -5 624 M -( TCP\(seq=x, len=500\) ->) s -5 613 M -( contains SSH_MSG_IGNORE) s -5 591 M -( TCP\(seq=y, len=500\) ->) s -5 580 M -( contains Data) s -5 558 M -( Provided that the IV for second SSH Record is fixed after the data for) s -5 547 M -( the Data packet is determined -i.e. you do:) s -5 536 M -( read from user) s -5 525 M -( encrypt null packet) s -5 514 M -( encrypt data packet) s -5 481 M -(9.2.2 Data Integrity) s -5 459 M -( This protocol does allow the Data Integrity mechanism to be disabled.) s -5 448 M -( Implementors SHOULD be wary of exposing this feature for any purpose) s -5 437 M -( other than debugging. Users and administrators SHOULD be explicitly) s -5 426 M -( warned anytime the "none" MAC is enabled.) s -5 404 M -( So long as the "none" MAC is not used, this protocol provides data) s -5 393 M -( integrity.) s -5 371 M -( Because MACs use a 32 bit sequence number, they might start to leak) s -5 360 M -( information after 2**32 packets have been sent. However, following) s -5 349 M -( the rekeying recommendations should prevent this attack. The) s -5 338 M -( transport protocol [1] recommends rekeying after one gigabyte of) s -5 327 M -( data, and the smallest possible packet is 16 bytes. Therefore,) s -5 316 M -( rekeying SHOULD happen after 2**28 packets at the very most.) s -5 294 M -(9.2.3 Replay) s -5 272 M -( The use of a MAC other than 'none' provides integrity and) s -5 261 M -( authentication. In addition, the transport protocol provides a) s -5 250 M -( unique session identifier \(bound in part to pseudo-random data that) s -5 239 M -( is part of the algorithm and key exchange process\) that can be used) s -5 228 M -( by higher level protocols to bind data to a given session and prevent) s -5 217 M -( replay of data from prior sessions. For example, the authentication) s -5 206 M -( protocol uses this to prevent replay of signatures from previous) s -5 195 M -( sessions. Because public key authentication exchanges are) s -5 184 M -( cryptographically bound to the session \(i.e., to the initial key) s -5 173 M -( exchange\) they cannot be successfully replayed in other sessions.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 16]) s -_R -S -PStoPSsaved restore -%%Page: (16,17) 9 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 17 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( Note that the session ID can be made public without harming the) s -5 679 M -( security of the protocol.) s -5 657 M -( If two session happen to have the same session ID [hash of key) s -5 646 M -( exchanges] then packets from one can be replayed against the other.) s -5 635 M -( It must be stressed that the chances of such an occurrence are,) s -5 624 M -( needless to say, minimal when using modern cryptographic methods.) s -5 613 M -( This is all the more so true when specifying larger hash function) s -5 602 M -( outputs and DH parameters.) s -5 580 M -( Replay detection using monotonically increasing sequence numbers as) s -5 569 M -( input to the MAC, or HMAC in some cases, is described in [RFC2085] />) s -5 558 M -( [RFC2246], [RFC2743], [RFC1964], [RFC2025], and [RFC1510]. The) s -5 547 M -( underlying construct is discussed in [RFC2104]. Essentially a) s -5 536 M -( different sequence number in each packet ensures that at least this) s -5 525 M -( one input to the MAC function will be unique and will provide a) s -5 514 M -( nonrecurring MAC output that is not predictable to an attacker. If) s -5 503 M -( the session stays active long enough, however, this sequence number) s -5 492 M -( will wrap. This event may provide an attacker an opportunity to) s -5 481 M -( replay a previously recorded packet with an identical sequence number) s -5 470 M -( but only if the peers have not rekeyed since the transmission of the) s -5 459 M -( first packet with that sequence number. If the peers have rekeyed,) s -5 448 M -( then the replay will be detected as the MAC check will fail. For) s -5 437 M -( this reason, it must be emphasized that peers MUST rekey before a) s -5 426 M -( wrap of the sequence numbers. Naturally, if an attacker does attempt) s -5 415 M -( to replay a captured packet before the peers have rekeyed, then the) s -5 404 M -( receiver of the duplicate packet will not be able to validate the MAC) s -5 393 M -( and it will be discarded. The reason that the MAC will fail is) s -5 382 M -( because the receiver will formulate a MAC based upon the packet) s -5 371 M -( contents, the shared secret, and the expected sequence number. Since) s -5 360 M -( the replayed packet will not be using that expected sequence number) s -5 349 M -( \(the sequence number of the replayed packet will have already been) s -5 338 M -( passed by the receiver\) then the calculated MAC will not match the) s -5 327 M -( MAC received with the packet.) s -5 305 M -(9.2.4 Man-in-the-middle) s -5 283 M -( This protocol makes no assumptions nor provisions for an) s -5 272 M -( infrastructure or means for distributing the public keys of hosts. It) s -5 261 M -( is expected that this protocol will sometimes be used without first) s -5 250 M -( verifying the association between the server host key and the server) s -5 239 M -( host name. Such usage is vulnerable to man-in-the-middle attacks.) s -5 228 M -( This section describes this and encourages administrators and users) s -5 217 M -( to understand the importance of verifying this association before any) s -5 206 M -( session is initiated.) s -5 184 M -( There are three cases of man-in-the-middle attacks to consider. The) s -5 173 M -( first is where an attacker places a device between the client and the) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 17]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 18 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( server before the session is initiated. In this case, the attack) s -5 679 M -( device is trying to mimic the legitimate server and will offer its) s -5 668 M -( public key to the client when the client initiates a session. If it) s -5 657 M -( were to offer the public key of the server, then it would not be able) s -5 646 M -( to decrypt or sign the transmissions between the legitimate server) s -5 635 M -( and the client unless it also had access to the private-key of the) s -5 624 M -( host. The attack device will also, simultaneously to this, initiate) s -5 613 M -( a session to the legitimate server masquerading itself as the client.) s -5 602 M -( If the public key of the server had been securely distributed to the) s -5 591 M -( client prior to that session initiation, the key offered to the) s -5 580 M -( client by the attack device will not match the key stored on the) s -5 569 M -( client. In that case, the user SHOULD be given a warning that the) s -5 558 M -( offered host key does not match the host key cached on the client.) s -5 547 M -( As described in Section 3.1 of [ARCH], the user may be free to accept) s -5 536 M -( the new key and continue the session. It is RECOMMENDED that the) s -5 525 M -( warning provide sufficient information to the user of the client) s -5 514 M -( device so they may make an informed decision. If the user chooses to) s -5 503 M -( continue the session with the stored public-key of the server \(not) s -5 492 M -( the public-key offered at the start of the session\), then the session) s -5 481 M -( specific data between the attacker and server will be different) s -5 470 M -( between the client-to-attacker session and the attacker-to-server) s -5 459 M -( sessions due to the randomness discussed above. From this, the) s -5 448 M -( attacker will not be able to make this attack work since the attacker) s -5 437 M -( will not be able to correctly sign packets containing this session) s -5 426 M -( specific data from the server since he does not have the private key) s -5 415 M -( of that server.) s -5 393 M -( The second case that should be considered is similar to the first) s -5 382 M -( case in that it also happens at the time of connection but this case) s -5 371 M -( points out the need for the secure distribution of server public) s -5 360 M -( keys. If the server public keys are not securely distributed then) s -5 349 M -( the client cannot know if it is talking to the intended server. An) s -5 338 M -( attacker may use social engineering techniques to pass off server) s -5 327 M -( keys to unsuspecting users and may then place a man-in-the-middle) s -5 316 M -( attack device between the legitimate server and the clients. If this) s -5 305 M -( is allowed to happen then the clients will form client-to-attacker) s -5 294 M -( sessions and the attacker will form attacker-to-server sessions and) s -5 283 M -( will be able to monitor and manipulate all of the traffic between the) s -5 272 M -( clients and the legitimate servers. Server administrators are) s -5 261 M -( encouraged to make host key fingerprints available for checking by) s -5 250 M -( some means whose security does not rely on the integrity of the) s -5 239 M -( actual host keys. Possible mechanisms are discussed in Section 3.1) s -5 228 M -( of [SSH-ARCH] and may also include secured Web pages, physical pieces) s -5 217 M -( of paper, etc. Implementors SHOULD provide recommendations on how) s -5 206 M -( best to do this with their implementation. Because the protocol is) s -5 195 M -( extensible, future extensions to the protocol may provide better) s -5 184 M -( mechanisms for dealing with the need to know the server's host key) s -5 173 M -( before connecting. For example, making the host key fingerprint) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 18]) s -_R -S -PStoPSsaved restore -%%Page: (18,19) 10 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 19 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( available through a secure DNS lookup, or using kerberos over gssapi) s -5 679 M -( during key exchange to authenticate the server are possibilities.) s -5 657 M -( In the third man-in-the-middle case, attackers may attempt to) s -5 646 M -( manipulate packets in transit between peers after the session has) s -5 635 M -( been established. As described in the Replay part of this section, a) s -5 624 M -( successful attack of this nature is very improbable. As in the) s -5 613 M -( Replay section, this reasoning does assume that the MAC is secure and) s -5 602 M -( that it is infeasible to construct inputs to a MAC algorithm to give) s -5 591 M -( a known output. This is discussed in much greater detail in Section) s -5 580 M -( 6 of RFC 2104. If the MAC algorithm has a vulnerability or is weak) s -5 569 M -( enough, then the attacker may be able to specify certain inputs to) s -5 558 M -( yield a known MAC. With that they may be able to alter the contents) s -5 547 M -( of a packet in transit. Alternatively the attacker may be able to) s -5 536 M -( exploit the algorithm vulnerability or weakness to find the shared) s -5 525 M -( secret by reviewing the MACs from captured packets. In either of) s -5 514 M -( those cases, an attacker could construct a packet or packets that) s -5 503 M -( could be inserted into an SSH stream. To prevent that, implementors) s -5 492 M -( are encouraged to utilize commonly accepted MAC algorithms and) s -5 481 M -( administrators are encouraged to watch current literature and) s -5 470 M -( discussions of cryptography to ensure that they are not using a MAC) s -5 459 M -( algorithm that has a recently found vulnerability or weakness.) s -5 437 M -( In summary, the use of this protocol without a reliable association) s -5 426 M -( of the binding between a host and its host keys is inherently) s -5 415 M -( insecure and is NOT RECOMMENDED. It may however be necessary in) s -5 404 M -( non-security critical environments, and will still provide protection) s -5 393 M -( against passive attacks. Implementors of protocols and applications) s -5 382 M -( running on top of this protocol should keep this possibility in mind.) s -5 360 M -(9.2.5 Denial-of-service) s -5 338 M -( This protocol is designed to be used over a reliable transport. If) s -5 327 M -( transmission errors or message manipulation occur, the connection is) s -5 316 M -( closed. The connection SHOULD be re-established if this occurs.) s -5 305 M -( Denial of service attacks of this type \("wire cutter"\) are almost) s -5 294 M -( impossible to avoid.) s -5 272 M -( In addition, this protocol is vulnerable to Denial of Service attacks) s -5 261 M -( because an attacker can force the server to go through the CPU and) s -5 250 M -( memory intensive tasks of connection setup and key exchange without) s -5 239 M -( authenticating. Implementors SHOULD provide features that make this) s -5 228 M -( more difficult. For example, only allowing connections from a subset) s -5 217 M -( of IPs known to have valid users.) s -5 195 M -(9.2.6 Covert Channels) s -5 173 M -( The protocol was not designed to eliminate covert channels. For) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 19]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 20 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( example, the padding, SSH_MSG_IGNORE messages, and several other) s -5 679 M -( places in the protocol can be used to pass covert information, and) s -5 668 M -( the recipient has no reliable way to verify whether such information) s -5 657 M -( is being sent.) s -5 635 M -(9.2.7 Forward Secrecy) s -5 613 M -( It should be noted that the Diffie-Hellman key exchanges may provide) s -5 602 M -( perfect forward secrecy \(PFS\). PFS is essentially defined as the) s -5 591 M -( cryptographic property of a key-establishment protocol in which the) s -5 580 M -( compromise of a session key or long-term private key after a given) s -5 569 M -( session does not cause the compromise of any earlier session. [ANSI) s -5 558 M -( T1.523-2001] SSHv2 sessions resulting from a key exchange using) s -5 547 M -( diffie-hellman-group1-sha1 are secure even if private keying/) s -5 536 M -( authentication material is later revealed, but not if the session) s -5 525 M -( keys are revealed. So, given this definition of PFS, SSHv2 does have) s -5 514 M -( PFS. It is hoped that all other key exchange mechanisms proposed and) s -5 503 M -( used in the future will also provide PFS. This property is not) s -5 492 M -( commuted to any of the applications or protocols using SSH as a) s -5 481 M -( transport however. The transport layer of SSH provides) s -5 470 M -( confidentiality for password authentication and other methods that) s -5 459 M -( rely on secret data.) s -5 437 M -( Of course, if the DH private parameters for the client and server are) s -5 426 M -( revealed then the session key is revealed, but these items can be) s -5 415 M -( thrown away after the key exchange completes. It's worth pointing) s -5 404 M -( out that these items should not be allowed to end up on swap space) s -5 393 M -( and that they should be erased from memory as soon as the key) s -5 382 M -( exchange completes.) s -5 360 M -(9.3 Authentication Protocol) s -5 338 M -( The purpose of this protocol is to perform client user) s -5 327 M -( authentication. It assumes that this run over a secure transport) s -5 316 M -( layer protocol, which has already authenticated the server machine,) s -5 305 M -( established an encrypted communications channel, and computed a) s -5 294 M -( unique session identifier for this session.) s -5 272 M -( Several authentication methods with different security) s -5 261 M -( characteristics are allowed. It is up to the server's local policy) s -5 250 M -( to decide which methods \(or combinations of methods\) it is willing to) s -5 239 M -( accept for each user. Authentication is no stronger than the weakest) s -5 228 M -( combination allowed.) s -5 206 M -( The server may go into a "sleep" period after repeated unsuccessful) s -5 195 M -( authentication attempts to make key search more difficult for) s -5 184 M -( attackers. Care should be taken so that this doesn't become a) s -5 173 M -( self-denial of service vector.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 20]) s -_R -S -PStoPSsaved restore -%%Page: (20,21) 11 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 21 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -(9.3.1 Weak Transport) s -5 668 M -( If the transport layer does not provide confidentiality,) s -5 657 M -( authentication methods that rely on secret data SHOULD be disabled.) s -5 646 M -( If it does not provide strong integrity protection, requests to) s -5 635 M -( change authentication data \(e.g. a password change\) SHOULD be) s -5 624 M -( disabled to prevent an attacker from modifying the ciphertext) s -5 613 M -( without being noticed, or rendering the new authentication data) s -5 602 M -( unusable \(denial of service\).) s -5 580 M -( The assumption as stated above that the Authentication Protocol only) s -5 569 M -( run over a secure transport that has previously authenticated the) s -5 558 M -( server is very important to note. People deploying SSH are reminded) s -5 547 M -( of the consequences of man-in-the-middle attacks if the client does) s -5 536 M -( not have a very strong a priori association of the server with the) s -5 525 M -( host key of that server. Specifically for the case of the) s -5 514 M -( Authentication Protocol the client may form a session to a) s -5 503 M -( man-in-the-middle attack device and divulge user credentials such as) s -5 492 M -( their username and password. Even in the cases of authentication) s -5 481 M -( where no user credentials are divulged, an attacker may still gain) s -5 470 M -( information they shouldn't have by capturing key-strokes in much the) s -5 459 M -( same way that a honeypot works.) s -5 437 M -(9.3.2 Debug messages) s -5 415 M -( Special care should be taken when designing debug messages. These) s -5 404 M -( messages may reveal surprising amounts of information about the host) s -5 393 M -( if not properly designed. Debug messages can be disabled \(during) s -5 382 M -( user authentication phase\) if high security is required.) s -5 371 M -( Administrators of host machines should make all attempts to) s -5 360 M -( compartmentalize all event notification messages and protect them) s -5 349 M -( from unwarranted observation. Developers should be aware of the) s -5 338 M -( sensitive nature of some of the normal event messages and debug) s -5 327 M -( messages and may want to provide guidance to administrators on ways) s -5 316 M -( to keep this information away from unauthorized people. Developers) s -5 305 M -( should consider minimizing the amount of sensitive information) s -5 294 M -( obtainable by users during the authentication phase in accordance) s -5 283 M -( with the local policies. For this reason, it is RECOMMENDED that) s -5 272 M -( debug messages be initially disabled at the time of deployment and) s -5 261 M -( require an active decision by an administrator to allow them to be) s -5 250 M -( enabled. It is also RECOMMENDED that a message expressing this) s -5 239 M -( concern be presented to the administrator of a system when the action) s -5 228 M -( is taken to enable debugging messages.) s -5 206 M -(9.3.3 Local security policy) s -5 184 M -( Implementer MUST ensure that the credentials provided validate the) s -5 173 M -( professed user and also MUST ensure that the local policy of the) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 21]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 22 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( server permits the user the access requested. In particular, because) s -5 679 M -( of the flexible nature of the SSH connection protocol, it may not be) s -5 668 M -( possible to determine the local security policy, if any, that should) s -5 657 M -( apply at the time of authentication because the kind of service being) s -5 646 M -( requested is not clear at that instant. For example, local policy) s -5 635 M -( might allow a user to access files on the server, but not start an) s -5 624 M -( interactive shell. However, during the authentication protocol, it is) s -5 613 M -( not known whether the user will be accessing files or attempting to) s -5 602 M -( use an interactive shell, or even both. In any event, where local) s -5 591 M -( security policy for the server host exists, it MUST be applied and) s -5 580 M -( enforced correctly.) s -5 558 M -( Implementors are encouraged to provide a default local policy and) s -5 547 M -( make its parameters known to administrators and users. At the) s -5 536 M -( discretion of the implementors, this default policy may be along the) s -5 525 M -( lines of 'anything goes' where there are no restrictions placed upon) s -5 514 M -( users, or it may be along the lines of 'excessively restrictive' in) s -5 503 M -( which case the administrators will have to actively make changes to) s -5 492 M -( this policy to meet their needs. Alternatively, it may be some) s -5 481 M -( attempt at providing something practical and immediately useful to) s -5 470 M -( the administrators of the system so they don't have to put in much) s -5 459 M -( effort to get SSH working. Whatever choice is made MUST be applied) s -5 448 M -( and enforced as required above.) s -5 426 M -(9.3.4 Public key authentication) s -5 404 M -( The use of public-key authentication assumes that the client host has) s -5 393 M -( not been compromised. It also assumes that the private-key of the) s -5 382 M -( server host has not been compromised.) s -5 360 M -( This risk can be mitigated by the use of passphrases on private keys;) s -5 349 M -( however, this is not an enforceable policy. The use of smartcards,) s -5 338 M -( or other technology to make passphrases an enforceable policy is) s -5 327 M -( suggested.) s -5 305 M -( The server could require both password and public-key authentication,) s -5 294 M -( however, this requires the client to expose its password to the) s -5 283 M -( server \(see section on password authentication below.\)) s -5 261 M -(9.3.5 Password authentication) s -5 239 M -( The password mechanism as specified in the authentication protocol) s -5 228 M -( assumes that the server has not been compromised. If the server has) s -5 217 M -( been compromised, using password authentication will reveal a valid) s -5 206 M -( username / password combination to the attacker, which may lead to) s -5 195 M -( further compromises.) s -5 173 M -( This vulnerability can be mitigated by using an alternative form of) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 22]) s -_R -S -PStoPSsaved restore -%%Page: (22,23) 12 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 23 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( authentication. For example, public-key authentication makes no) s -5 679 M -( assumptions about security on the server.) s -5 657 M -(9.3.6 Host based authentication) s -5 635 M -( Host based authentication assumes that the client has not been) s -5 624 M -( compromised. There are no mitigating strategies, other than to use) s -5 613 M -( host based authentication in combination with another authentication) s -5 602 M -( method.) s -5 580 M -(9.4 Connection protocol) s -5 558 M -(9.4.1 End point security) s -5 536 M -( End point security is assumed by the connection protocol. If the) s -5 525 M -( server has been compromised, any terminal sessions, port forwarding,) s -5 514 M -( or systems accessed on the host are compromised. There are no) s -5 503 M -( mitigating factors for this.) s -5 481 M -( If the client end point has been compromised, and the server fails to) s -5 470 M -( stop the attacker at the authentication protocol, all services) s -5 459 M -( exposed \(either as subsystems or through forwarding\) will be) s -5 448 M -( vulnerable to attack. Implementors SHOULD provide mechanisms for) s -5 437 M -( administrators to control which services are exposed to limit the) s -5 426 M -( vulnerability of other services.) s -5 404 M -( These controls might include controlling which machines and ports can) s -5 393 M -( be target in 'port-forwarding' operations, which users are allowed to) s -5 382 M -( use interactive shell facilities, or which users are allowed to use) s -5 371 M -( exposed subsystems.) s -5 349 M -(9.4.2 Proxy forwarding) s -5 327 M -( The SSH connection protocol allows for proxy forwarding of other) s -5 316 M -( protocols such as SNMP, POP3, and HTTP. This may be a concern for) s -5 305 M -( network administrators who wish to control the access of certain) s -5 294 M -( applications by users located outside of their physical location.) s -5 283 M -( Essentially, the forwarding of these protocols may violate site) s -5 272 M -( specific security policies as they may be undetectably tunneled) s -5 261 M -( through a firewall. Implementors SHOULD provide an administrative) s -5 250 M -( mechanism to control the proxy forwarding functionality so that site) s -5 239 M -( specific security policies may be upheld.) s -5 217 M -( In addition, a reverse proxy forwarding functionality is available,) s -5 206 M -( which again can be used to bypass firewall controls.) s -5 184 M -( As indicated above, end-point security is assumed during proxy) s -5 173 M -( forwarding operations. Failure of end-point security will compromise) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 23]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 24 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( all data passed over proxy forwarding.) s -5 668 M -(9.4.3 X11 forwarding) s -5 646 M -( Another form of proxy forwarding provided by the ssh connection) s -5 635 M -( protocol is the forwarding of the X11 protocol. If end-point) s -5 624 M -( security has been compromised, X11 forwarding may allow attacks) s -5 613 M -( against the X11 server. Users and administrators should, as a matter) s -5 602 M -( of course, use appropriate X11 security mechanisms to prevent) s -5 591 M -( unauthorized use of the X11 server. Implementors, administrators and) s -5 580 M -( users who wish to further explore the security mechanisms of X11 are) s -5 569 M -( invited to read [SCHEIFLER] and analyze previously reported problems) s -5 558 M -( with the interactions between SSH forwarding and X11 in CERT) s -5 547 M -( vulnerabilities VU#363181 and VU#118892 [CERT].) s -5 525 M -( X11 display forwarding with SSH, by itself, is not sufficient to) s -5 514 M -( correct well known problems with X11 security [VENEMA]. However, X11) s -5 503 M -( display forwarding in SSHv2 \(or other, secure protocols\), combined) s -5 492 M -( with actual and pseudo-displays which accept connections only over) s -5 481 M -( local IPC mechanisms authorized by permissions or ACLs, does correct) s -5 470 M -( many X11 security problems as long as the "none" MAC is not used. It) s -5 459 M -( is RECOMMENDED that X11 display implementations default to allowing) s -5 448 M -( display opens only over local IPC. It is RECOMMENDED that SSHv2) s -5 437 M -( server implementations that support X11 forwarding default to) s -5 426 M -( allowing display opens only over local IPC. On single-user systems) s -5 415 M -( it might be reasonable to default to allowing local display opens) s -5 404 M -( over TCP/IP.) s -5 382 M -( Implementors of the X11 forwarding protocol SHOULD implement the) s -5 371 M -( magic cookie access checking spoofing mechanism as described in) s -5 360 M -( [ssh-connect] as an additional mechanism to prevent unauthorized use) s -5 349 M -( of the proxy.) s -5 327 M -(Normative References) s -5 305 M -( [SSH-ARCH]) s -5 294 M -( Ylonen, T., "SSH Protocol Architecture", I-D) s -5 283 M -( draft-ietf-architecture-15.txt, Oct 2003.) s -5 261 M -( [SSH-TRANS]) s -5 250 M -( Ylonen, T., "SSH Transport Layer Protocol", I-D) s -5 239 M -( draft-ietf-transport-17.txt, Oct 2003.) s -5 217 M -( [SSH-USERAUTH]) s -5 206 M -( Ylonen, T., "SSH Authentication Protocol", I-D) s -5 195 M -( draft-ietf-userauth-18.txt, Oct 2003.) s -5 173 M -( [SSH-CONNECT]) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 24]) s -_R -S -PStoPSsaved restore -%%Page: (24,25) 13 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 25 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( Ylonen, T., "SSH Connection Protocol", I-D) s -5 679 M -( draft-ietf-connect-18.txt, Oct 2003.) s -5 657 M -( [SSH-NUMBERS]) s -5 646 M -( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s -5 635 M -( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s -5 624 M -( 2003.) s -5 602 M -( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s -5 591 M -( Requirement Levels", BCP 14, RFC 2119, March 1997.) s -5 569 M -(Informative References) s -5 547 M -( [FIPS-186]) s -5 536 M -( Federal Information Processing Standards Publication,) s -5 525 M -( "FIPS PUB 186, Digital Signature Standard", May 1994.) s -5 503 M -( [FIPS-197]) s -5 492 M -( National Institue of Standards and Technology, "FIPS 197,) s -5 481 M -( Specification for the Advanced Encryption Standard",) s -5 470 M -( November 2001.) s -5 448 M -( [ANSI T1.523-2001]) s -5 437 M -( American National Standards Insitute, Inc., "Telecom) s -5 426 M -( Glossary 2000", February 2001.) s -5 404 M -( [SCHEIFLER]) s -5 393 M -( Scheifler, R., "X Window System : The Complete Reference) s -5 382 M -( to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital) s -5 371 M -( Press ISBN 1555580882, Feburary 1992.) s -5 349 M -( [RFC0854] Postel, J. and J. Reynolds, "Telnet Protocol) s -5 338 M -( Specification", STD 8, RFC 854, May 1983.) s -5 316 M -( [RFC0894] Hornig, C., "Standard for the transmission of IP datagrams) s -5 305 M -( over Ethernet networks", STD 41, RFC 894, April 1984.) s -5 283 M -( [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",) s -5 272 M -( STD 13, RFC 1034, November 1987.) s -5 250 M -( [RFC1134] Perkins, D., "Point-to-Point Protocol: A proposal for) s -5 239 M -( multi-protocol transmission of datagrams over) s -5 228 M -( Point-to-Point links", RFC 1134, November 1989.) s -5 206 M -( [RFC1282] Kantor, B., "BSD Rlogin", RFC 1282, December 1991.) s -5 184 M -( [RFC1510] Kohl, J. and B. Neuman, "The Kerberos Network) s -5 173 M -( Authentication Service \(V5\)", RFC 1510, September 1993.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 25]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 26 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( [RFC1700] Reynolds, J. and J. Postel, "Assigned Numbers", RFC 1700,) s -5 679 M -( October 1994.) s -5 657 M -( [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness) s -5 646 M -( Recommendations for Security", RFC 1750, December 1994.) s -5 624 M -( [RFC3066] Alvestrand, H., "Tags for the Identification of) s -5 613 M -( Languages", BCP 47, RFC 3066, January 2001.) s -5 591 M -( [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC) s -5 580 M -( 1964, June 1996.) s -5 558 M -( [RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism) s -5 547 M -( \(SPKM\)", RFC 2025, October 1996.) s -5 525 M -( [RFC2085] Oehler, M. and R. Glenn, "HMAC-MD5 IP Authentication with) s -5 514 M -( Replay Prevention", RFC 2085, February 1997.) s -5 492 M -( [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:) s -5 481 M -( Keyed-Hashing for Message Authentication", RFC 2104,) s -5 470 M -( February 1997.) s -5 448 M -( [RFC2246] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A.) s -5 437 M -( and P. Kocher, "The TLS Protocol Version 1.0", RFC 2246,) s -5 426 M -( January 1999.) s -5 404 M -( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s -5 393 M -( 10646", RFC 2279, January 1998.) s -5 371 M -( [RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm and) s -5 360 M -( Its Use With IPsec", RFC 2410, November 1998.) s -5 338 M -( [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an) s -5 327 M -( IANA Considerations Section in RFCs", BCP 26, RFC 2434,) s -5 316 M -( October 1998.) s -5 294 M -( [RFC2743] Linn, J., "Generic Security Service Application Program) s -5 283 M -( Interface Version 2, Update 1", RFC 2743, January 2000.) s -5 261 M -( [SCHNEIER]) s -5 250 M -( Schneier, B., "Applied Cryptography Second Edition:) s -5 239 M -( protocols algorithms and source in code in C", 1996.) s -5 217 M -( [KAUFMAN,PERLMAN,SPECINER]) s -5 206 M -( Kaufman, C., Perlman, R. and M. Speciner, "Network) s -5 195 M -( Security: PRIVATE Communication in a PUBLIC World", 1995.) s -5 173 M -( [CERT] CERT Coordination Center, The., "http://www.cert.org/nav/) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 26]) s -_R -S -PStoPSsaved restore -%%Page: (26,27) 14 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 27 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( index_red.html".) s -5 668 M -( [VENEMA] Venema, W., "Murphy's Law and Computer Security",) s -5 657 M -( Proceedings of 6th USENIX Security Symposium, San Jose CA) s -5 646 M -( http://www.usenix.org/publications/library/proceedings/) s -5 635 M -( sec96/venema.html, July 1996.) s -5 613 M -( [ROGAWAY] Rogaway, P., "Problems with Proposed IP Cryptography",) s -5 602 M -( Unpublished paper http://www.cs.ucdavis.edu/~rogaway/) s -5 591 M -( papers/draft-rogaway-ipsec-comments-00.txt, 1996.) s -5 569 M -( [DAI] Dai, W., "An attack against SSH2 protocol", Email to the) s -5 558 M -( SECSH Working Group ietf-ssh@netbsd.org ftp://) s -5 547 M -( ftp.ietf.org/ietf-mail-archive/secsh/2002-02.mail, Feb) s -5 536 M -( 2002.) s -5 514 M -( [BELLARE,KOHNO,NAMPREMPRE]) s -5 503 M -( Bellaire, M., Kohno, T. and C. Namprempre, "Authenticated) s -5 492 M -( Encryption in SSH: Fixing the SSH Binary Packet Protocol",) s -5 481 M -( , Sept 2002.) s -5 448 M -(Authors' Addresses) s -5 426 M -( Tatu Ylonen) s -5 415 M -( SSH Communications Security Corp) s -5 404 M -( Fredrikinkatu 42) s -5 393 M -( HELSINKI FIN-00100) s -5 382 M -( Finland) s -5 360 M -( EMail: ylo@ssh.com) s -5 327 M -( Darren J. Moffat \(editor\)) s -5 316 M -( Sun Microsystems, Inc) s -5 305 M -( 17 Network Circle) s -5 294 M -( Menlo Park CA 94025) s -5 283 M -( USA) s -5 261 M -( EMail: Darren.Moffat@Sun.COM) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 27]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 28 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -(Intellectual Property Statement) s -5 668 M -( The IETF takes no position regarding the validity or scope of any) s -5 657 M -( intellectual property or other rights that might be claimed to) s -5 646 M -( pertain to the implementation or use of the technology described in) s -5 635 M -( this document or the extent to which any license under such rights) s -5 624 M -( might or might not be available; neither does it represent that it) s -5 613 M -( has made any effort to identify any such rights. Information on the) s -5 602 M -( IETF's procedures with respect to rights in standards-track and) s -5 591 M -( standards-related documentation can be found in BCP-11. Copies of) s -5 580 M -( claims of rights made available for publication and any assurances of) s -5 569 M -( licenses to be made available, or the result of an attempt made to) s -5 558 M -( obtain a general license or permission for the use of such) s -5 547 M -( proprietary rights by implementors or users of this specification can) s -5 536 M -( be obtained from the IETF Secretariat.) s -5 514 M -( The IETF invites any interested party to bring to its attention any) s -5 503 M -( copyrights, patents or patent applications, or other proprietary) s -5 492 M -( rights which may cover technology that may be required to practice) s -5 481 M -( this standard. Please address the information to the IETF Executive) s -5 470 M -( Director.) s -5 448 M -( The IETF has been notified of intellectual property rights claimed in) s -5 437 M -( regard to some or all of the specification contained in this) s -5 426 M -( document. For more information consult the online list of claimed) s -5 415 M -( rights.) s -5 382 M -(Full Copyright Statement) s -5 360 M -( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s -5 338 M -( This document and translations of it may be copied and furnished to) s -5 327 M -( others, and derivative works that comment on or otherwise explain it) s -5 316 M -( or assist in its implementation may be prepared, copied, published) s -5 305 M -( and distributed, in whole or in part, without restriction of any) s -5 294 M -( kind, provided that the above copyright notice and this paragraph are) s -5 283 M -( included on all such copies and derivative works. However, this) s -5 272 M -( document itself may not be modified in any way, such as by removing) s -5 261 M -( the copyright notice or references to the Internet Society or other) s -5 250 M -( Internet organizations, except as needed for the purpose of) s -5 239 M -( developing Internet standards in which case the procedures for) s -5 228 M -( copyrights defined in the Internet Standards process must be) s -5 217 M -( followed, or as required to translate it into languages other than) s -5 206 M -( English.) s -5 184 M -( The limited permissions granted above are perpetual and will not be) s -5 173 M -( revoked by the Internet Society or its successors or assignees.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 28]) s -_R -S -PStoPSsaved restore -%%Page: (28,29) 15 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 29 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Protocol Architecture Oct 2003) s -5 690 M -( This document and the information contained herein is provided on an) s -5 679 M -( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s -5 668 M -( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s -5 657 M -( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s -5 646 M -( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s -5 635 M -( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s -5 602 M -(Acknowledgment) s -5 580 M -( Funding for the RFC Editor function is currently provided by the) s -5 569 M -( Internet Society.) s -5 129 M -(Ylonen & Moffat Expires March 31, 2004 [Page 29]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -showpage -PStoPSsaved restore -%%Trailer -%%Pages: 29 -%%DocumentNeededResources: font Courier-Bold Courier -%%EOF diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt deleted file mode 100644 index 18070e8485..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt +++ /dev/null @@ -1,1624 +0,0 @@ - - - -Network Working Group T. Ylonen -Internet-Draft SSH Communications Security Corp -Expires: March 31, 2004 D. Moffat, Ed. - Sun Microsystems, Inc - Oct 2003 - - - SSH Protocol Architecture - draft-ietf-secsh-architecture-15.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on March 31, 2004. - -Copyright Notice - - Copyright (C) The Internet Society (2003). All Rights Reserved. - -Abstract - - SSH is a protocol for secure remote login and other secure network - services over an insecure network. This document describes the - architecture of the SSH protocol, as well as the notation and - terminology used in SSH protocol documents. It also discusses the SSH - algorithm naming system that allows local extensions. The SSH - protocol consists of three major components: The Transport Layer - Protocol provides server authentication, confidentiality, and - integrity with perfect forward secrecy. The User Authentication - Protocol authenticates the client to the server. The Connection - Protocol multiplexes the encrypted tunnel into several logical - channels. Details of these protocols are described in separate - - - -Ylonen & Moffat Expires March 31, 2004 [Page 1] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - documents. - -Table of Contents - - 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 - 3. Specification of Requirements . . . . . . . . . . . . . . . 3 - 4. Architecture . . . . . . . . . . . . . . . . . . . . . . . . 3 - 4.1 Host Keys . . . . . . . . . . . . . . . . . . . . . . . . . 4 - 4.2 Extensibility . . . . . . . . . . . . . . . . . . . . . . . 5 - 4.3 Policy Issues . . . . . . . . . . . . . . . . . . . . . . . 5 - 4.4 Security Properties . . . . . . . . . . . . . . . . . . . . 6 - 4.5 Packet Size and Overhead . . . . . . . . . . . . . . . . . . 6 - 4.6 Localization and Character Set Support . . . . . . . . . . . 7 - 5. Data Type Representations Used in the SSH Protocols . . . . 8 - 6. Algorithm Naming . . . . . . . . . . . . . . . . . . . . . . 10 - 7. Message Numbers . . . . . . . . . . . . . . . . . . . . . . 11 - 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . 11 - 9. Security Considerations . . . . . . . . . . . . . . . . . . 12 - 9.1 Pseudo-Random Number Generation . . . . . . . . . . . . . . 12 - 9.2 Transport . . . . . . . . . . . . . . . . . . . . . . . . . 13 - 9.2.1 Confidentiality . . . . . . . . . . . . . . . . . . . . . . 13 - 9.2.2 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 16 - 9.2.3 Replay . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 - 9.2.4 Man-in-the-middle . . . . . . . . . . . . . . . . . . . . . 17 - 9.2.5 Denial-of-service . . . . . . . . . . . . . . . . . . . . . 19 - 9.2.6 Covert Channels . . . . . . . . . . . . . . . . . . . . . . 19 - 9.2.7 Forward Secrecy . . . . . . . . . . . . . . . . . . . . . . 20 - 9.3 Authentication Protocol . . . . . . . . . . . . . . . . . . 20 - 9.3.1 Weak Transport . . . . . . . . . . . . . . . . . . . . . . . 21 - 9.3.2 Debug messages . . . . . . . . . . . . . . . . . . . . . . . 21 - 9.3.3 Local security policy . . . . . . . . . . . . . . . . . . . 21 - 9.3.4 Public key authentication . . . . . . . . . . . . . . . . . 22 - 9.3.5 Password authentication . . . . . . . . . . . . . . . . . . 22 - 9.3.6 Host based authentication . . . . . . . . . . . . . . . . . 23 - 9.4 Connection protocol . . . . . . . . . . . . . . . . . . . . 23 - 9.4.1 End point security . . . . . . . . . . . . . . . . . . . . . 23 - 9.4.2 Proxy forwarding . . . . . . . . . . . . . . . . . . . . . . 23 - 9.4.3 X11 forwarding . . . . . . . . . . . . . . . . . . . . . . . 24 - Normative References . . . . . . . . . . . . . . . . . . . . 24 - Informative References . . . . . . . . . . . . . . . . . . . 25 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 27 - Intellectual Property and Copyright Statements . . . . . . . 28 - - - - - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 2] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - -1. Contributors - - The major original contributors of this document were: Tatu Ylonen, - Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications - Security Corp), and Markku-Juhani O. Saarinen (University of - Jyvaskyla) - - The document editor is: Darren.Moffat@Sun.COM. Comments on this - internet draft should be sent to the IETF SECSH working group, - details at: http://ietf.org/html.charters/secsh-charter.html - -2. Introduction - - SSH is a protocol for secure remote login and other secure network - services over an insecure network. It consists of three major - components: - o The Transport Layer Protocol [SSH-TRANS] provides server - authentication, confidentiality, and integrity. It may optionally - also provide compression. The transport layer will typically be - run over a TCP/IP connection, but might also be used on top of any - other reliable data stream. - o The User Authentication Protocol [SSH-USERAUTH] authenticates the - client-side user to the server. It runs over the transport layer - protocol. - o The Connection Protocol [SSH-CONNECT] multiplexes the encrypted - tunnel into several logical channels. It runs over the user - authentication protocol. - - The client sends a service request once a secure transport layer - connection has been established. A second service request is sent - after user authentication is complete. This allows new protocols to - be defined and coexist with the protocols listed above. - - The connection protocol provides channels that can be used for a wide - range of purposes. Standard methods are provided for setting up - secure interactive shell sessions and for forwarding ("tunneling") - arbitrary TCP/IP ports and X11 connections. - -3. Specification of Requirements - - All documents related to the SSH protocols shall use the keywords - "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", - "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" to describe - requirements. They are to be interpreted as described in [RFC2119]. - -4. Architecture - - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 3] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - -4.1 Host Keys - - Each server host SHOULD have a host key. Hosts MAY have multiple - host keys using multiple different algorithms. Multiple hosts MAY - share the same host key. If a host has keys at all, it MUST have at - least one key using each REQUIRED public key algorithm (DSS - [FIPS-186]). - - The server host key is used during key exchange to verify that the - client is really talking to the correct server. For this to be - possible, the client must have a priori knowledge of the server's - public host key. - - Two different trust models can be used: - o The client has a local database that associates each host name (as - typed by the user) with the corresponding public host key. This - method requires no centrally administered infrastructure, and no - third-party coordination. The downside is that the database of - name-to-key associations may become burdensome to maintain. - o The host name-to-key association is certified by some trusted - certification authority. The client only knows the CA root key, - and can verify the validity of all host keys certified by accepted - CAs. - - The second alternative eases the maintenance problem, since - ideally only a single CA key needs to be securely stored on the - client. On the other hand, each host key must be appropriately - certified by a central authority before authorization is possible. - Also, a lot of trust is placed on the central infrastructure. - - The protocol provides the option that the server name - host key - association is not checked when connecting to the host for the first - time. This allows communication without prior communication of host - keys or certification. The connection still provides protection - against passive listening; however, it becomes vulnerable to active - man-in-the-middle attacks. Implementations SHOULD NOT normally allow - such connections by default, as they pose a potential security - problem. However, as there is no widely deployed key infrastructure - available on the Internet yet, this option makes the protocol much - more usable during the transition time until such an infrastructure - emerges, while still providing a much higher level of security than - that offered by older solutions (e.g. telnet [RFC-854] and rlogin - [RFC-1282]). - - Implementations SHOULD try to make the best effort to check host - keys. An example of a possible strategy is to only accept a host key - without checking the first time a host is connected, save the key in - a local database, and compare against that key on all future - - - -Ylonen & Moffat Expires March 31, 2004 [Page 4] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - connections to that host. - - Implementations MAY provide additional methods for verifying the - correctness of host keys, e.g. a hexadecimal fingerprint derived from - the SHA-1 hash of the public key. Such fingerprints can easily be - verified by using telephone or other external communication channels. - - All implementations SHOULD provide an option to not accept host keys - that cannot be verified. - - We believe that ease of use is critical to end-user acceptance of - security solutions, and no improvement in security is gained if the - new solutions are not used. Thus, providing the option not to check - the server host key is believed to improve the overall security of - the Internet, even though it reduces the security of the protocol in - configurations where it is allowed. - -4.2 Extensibility - - We believe that the protocol will evolve over time, and some - organizations will want to use their own encryption, authentication - and/or key exchange methods. Central registration of all extensions - is cumbersome, especially for experimental or classified features. - On the other hand, having no central registration leads to conflicts - in method identifiers, making interoperability difficult. - - We have chosen to identify algorithms, methods, formats, and - extension protocols with textual names that are of a specific format. - DNS names are used to create local namespaces where experimental or - classified extensions can be defined without fear of conflicts with - other implementations. - - One design goal has been to keep the base protocol as simple as - possible, and to require as few algorithms as possible. However, all - implementations MUST support a minimal set of algorithms to ensure - interoperability (this does not imply that the local policy on all - hosts would necessary allow these algorithms). The mandatory - algorithms are specified in the relevant protocol documents. - - Additional algorithms, methods, formats, and extension protocols can - be defined in separate drafts. See Section Algorithm Naming (Section - 6) for more information. - -4.3 Policy Issues - - The protocol allows full negotiation of encryption, integrity, key - exchange, compression, and public key algorithms and formats. - Encryption, integrity, public key, and compression algorithms can be - - - -Ylonen & Moffat Expires March 31, 2004 [Page 5] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - different for each direction. - - The following policy issues SHOULD be addressed in the configuration - mechanisms of each implementation: - o Encryption, integrity, and compression algorithms, separately for - each direction. The policy MUST specify which is the preferred - algorithm (e.g. the first algorithm listed in each category). - o Public key algorithms and key exchange method to be used for host - authentication. The existence of trusted host keys for different - public key algorithms also affects this choice. - o The authentication methods that are to be required by the server - for each user. The server's policy MAY require multiple - authentication for some or all users. The required algorithms MAY - depend on the location where the user is trying to log in from. - o The operations that the user is allowed to perform using the - connection protocol. Some issues are related to security; for - example, the policy SHOULD NOT allow the server to start sessions - or run commands on the client machine, and MUST NOT allow - connections to the authentication agent unless forwarding such - connections has been requested. Other issues, such as which TCP/ - IP ports can be forwarded and by whom, are clearly issues of local - policy. Many of these issues may involve traversing or bypassing - firewalls, and are interrelated with the local security policy. - -4.4 Security Properties - - The primary goal of the SSH protocol is improved security on the - Internet. It attempts to do this in a way that is easy to deploy, - even at the cost of absolute security. - o All encryption, integrity, and public key algorithms used are - well-known, well-established algorithms. - o All algorithms are used with cryptographically sound key sizes - that are believed to provide protection against even the strongest - cryptanalytic attacks for decades. - o All algorithms are negotiated, and in case some algorithm is - broken, it is easy to switch to some other algorithm without - modifying the base protocol. - - Specific concessions were made to make wide-spread fast deployment - easier. The particular case where this comes up is verifying that - the server host key really belongs to the desired host; the protocol - allows the verification to be left out (but this is NOT RECOMMENDED). - This is believed to significantly improve usability in the short - term, until widespread Internet public key infrastructures emerge. - -4.5 Packet Size and Overhead - - Some readers will worry about the increase in packet size due to new - - - -Ylonen & Moffat Expires March 31, 2004 [Page 6] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - headers, padding, and MAC. The minimum packet size is in the order - of 28 bytes (depending on negotiated algorithms). The increase is - negligible for large packets, but very significant for one-byte - packets (telnet-type sessions). There are, however, several factors - that make this a non-issue in almost all cases: - o The minimum size of a TCP/IP header is 32 bytes. Thus, the - increase is actually from 33 to 51 bytes (roughly). - o The minimum size of the data field of an Ethernet packet is 46 - bytes [RFC-894]. Thus, the increase is no more than 5 bytes. When - Ethernet headers are considered, the increase is less than 10 - percent. - o The total fraction of telnet-type data in the Internet is - negligible, even with increased packet sizes. - - The only environment where the packet size increase is likely to have - a significant effect is PPP [RFC-1134] over slow modem lines (PPP - compresses the TCP/IP headers, emphasizing the increase in packet - size). However, with modern modems, the time needed to transfer is in - the order of 2 milliseconds, which is a lot faster than people can - type. - - There are also issues related to the maximum packet size. To - minimize delays in screen updates, one does not want excessively - large packets for interactive sessions. The maximum packet size is - negotiated separately for each channel. - -4.6 Localization and Character Set Support - - For the most part, the SSH protocols do not directly pass text that - would be displayed to the user. However, there are some places where - such data might be passed. When applicable, the character set for the - data MUST be explicitly specified. In most places, ISO 10646 with - UTF-8 encoding is used [RFC-2279]. When applicable, a field is also - provided for a language tag [RFC-3066]. - - One big issue is the character set of the interactive session. There - is no clear solution, as different applications may display data in - different formats. Different types of terminal emulation may also be - employed in the client, and the character set to be used is - effectively determined by the terminal emulation. Thus, no place is - provided for directly specifying the character set or encoding for - terminal session data. However, the terminal emulation type (e.g. - "vt100") is transmitted to the remote site, and it implicitly - specifies the character set and encoding. Applications typically use - the terminal type to determine what character set they use, or the - character set is determined using some external means. The terminal - emulation may also allow configuring the default character set. In - any case, the character set for the terminal session is considered - - - -Ylonen & Moffat Expires March 31, 2004 [Page 7] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - primarily a client local issue. - - Internal names used to identify algorithms or protocols are normally - never displayed to users, and must be in US-ASCII. - - The client and server user names are inherently constrained by what - the server is prepared to accept. They might, however, occasionally - be displayed in logs, reports, etc. They MUST be encoded using ISO - 10646 UTF-8, but other encodings may be required in some cases. It - is up to the server to decide how to map user names to accepted user - names. Straight bit-wise binary comparison is RECOMMENDED. - - For localization purposes, the protocol attempts to minimize the - number of textual messages transmitted. When present, such messages - typically relate to errors, debugging information, or some externally - configured data. For data that is normally displayed, it SHOULD be - possible to fetch a localized message instead of the transmitted - message by using a numerical code. The remaining messages SHOULD be - configurable. - -5. Data Type Representations Used in the SSH Protocols - byte - - A byte represents an arbitrary 8-bit value (octet) [RFC-1700]. - Fixed length data is sometimes represented as an array of bytes, - written byte[n], where n is the number of bytes in the array. - - boolean - - A boolean value is stored as a single byte. The value 0 - represents FALSE, and the value 1 represents TRUE. All non-zero - values MUST be interpreted as TRUE; however, applications MUST NOT - store values other than 0 and 1. - - uint32 - - Represents a 32-bit unsigned integer. Stored as four bytes in the - order of decreasing significance (network byte order). For - example, the value 699921578 (0x29b7f4aa) is stored as 29 b7 f4 - aa. - - uint64 - - Represents a 64-bit unsigned integer. Stored as eight bytes in - the order of decreasing significance (network byte order). - - - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 8] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - string - - Arbitrary length binary string. Strings are allowed to contain - arbitrary binary data, including null characters and 8-bit - characters. They are stored as a uint32 containing its length - (number of bytes that follow) and zero (= empty string) or more - bytes that are the value of the string. Terminating null - characters are not used. - - Strings are also used to store text. In that case, US-ASCII is - used for internal names, and ISO-10646 UTF-8 for text that might - be displayed to the user. The terminating null character SHOULD - NOT normally be stored in the string. - - For example, the US-ASCII string "testing" is represented as 00 00 - 00 07 t e s t i n g. The UTF8 mapping does not alter the encoding - of US-ASCII characters. - - mpint - - Represents multiple precision integers in two's complement format, - stored as a string, 8 bits per byte, MSB first. Negative numbers - have the value 1 as the most significant bit of the first byte of - the data partition. If the most significant bit would be set for a - positive number, the number MUST be preceded by a zero byte. - Unnecessary leading bytes with the value 0 or 255 MUST NOT be - included. The value zero MUST be stored as a string with zero - bytes of data. - - By convention, a number that is used in modular computations in - Z_n SHOULD be represented in the range 0 <= x < n. - - Examples: - value (hex) representation (hex) - --------------------------------------------------------------- - 0 00 00 00 00 - 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7 - 80 00 00 00 02 00 80 - -1234 00 00 00 02 ed cc - -deadbeef 00 00 00 05 ff 21 52 41 11 - - - - name-list - - A string containing a comma separated list of names. A name list - is represented as a uint32 containing its length (number of bytes - that follow) followed by a comma-separated list of zero or more - - - -Ylonen & Moffat Expires March 31, 2004 [Page 9] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - names. A name MUST be non-zero length, and it MUST NOT contain a - comma (','). Context may impose additional restrictions on the - names; for example, the names in a list may have to be valid - algorithm identifier (see Algorithm Naming below), or [RFC-3066] - language tags. The order of the names in a list may or may not be - significant, also depending on the context where the list is is - used. Terminating NUL characters are not used, neither for the - individual names, nor for the list as a whole. - - Examples: - value representation (hex) - --------------------------------------- - (), the empty list 00 00 00 00 - ("zlib") 00 00 00 04 7a 6c 69 62 - ("zlib", "none") 00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65 - - - - -6. Algorithm Naming - - The SSH protocols refer to particular hash, encryption, integrity, - compression, and key exchange algorithms or protocols by names. - There are some standard algorithms that all implementations MUST - support. There are also algorithms that are defined in the protocol - specification but are OPTIONAL. Furthermore, it is expected that - some organizations will want to use their own algorithms. - - In this protocol, all algorithm identifiers MUST be printable - US-ASCII non-empty strings no longer than 64 characters. Names MUST - be case-sensitive. - - There are two formats for algorithm names: - o Names that do not contain an at-sign (@) are reserved to be - assigned by IETF consensus (RFCs). Examples include `3des-cbc', - `sha-1', `hmac-sha1', and `zlib' (the quotes are not part of the - name). Names of this format MUST NOT be used without first - registering them. Registered names MUST NOT contain an at-sign - (@) or a comma (,). - o Anyone can define additional algorithms by using names in the - format name@domainname, e.g. "ourcipher-cbc@example.com". The - format of the part preceding the at sign is not specified; it MUST - consist of US-ASCII characters except at-sign and comma. The part - following the at-sign MUST be a valid fully qualified internet - domain name [RFC-1034] controlled by the person or organization - defining the name. It is up to each domain how it manages its - local namespace. - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 10] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - -7. Message Numbers - - SSH packets have message numbers in the range 1 to 255. These numbers - have been allocated as follows: - - - Transport layer protocol: - - 1 to 19 Transport layer generic (e.g. disconnect, ignore, debug, - etc.) - 20 to 29 Algorithm negotiation - 30 to 49 Key exchange method specific (numbers can be reused for - different authentication methods) - - User authentication protocol: - - 50 to 59 User authentication generic - 60 to 79 User authentication method specific (numbers can be - reused for different authentication methods) - - Connection protocol: - - 80 to 89 Connection protocol generic - 90 to 127 Channel related messages - - Reserved for client protocols: - - 128 to 191 Reserved - - Local extensions: - - 192 to 255 Local extensions - - - -8. IANA Considerations - - The initial state of the IANA registry is detailed in [SSH-NUMBERS]. - - Allocation of the following types of names in the SSH protocols is - assigned by IETF consensus: - o SSH encryption algorithm names, - o SSH MAC algorithm names, - o SSH public key algorithm names (public key algorithm also implies - encoding and signature/encryption capability), - o SSH key exchange method names, and - o SSH protocol (service) names. - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 11] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - These names MUST be printable US-ASCII strings, and MUST NOT contain - the characters at-sign ('@'), comma (','), or whitespace or control - characters (ASCII codes 32 or less). Names are case-sensitive, and - MUST NOT be longer than 64 characters. - - Names with the at-sign ('@') in them are allocated by the owner of - DNS name after the at-sign (hierarchical allocation in [RFC-2343]), - otherwise the same restrictions as above. - - Each category of names listed above has a separate namespace. - However, using the same name in multiple categories SHOULD be avoided - to minimize confusion. - - Message numbers (see Section Message Numbers (Section 7)) in the - range of 0..191 are allocated via IETF consensus; message numbers in - the 192..255 range (the "Local extensions" set) are reserved for - private use. - -9. Security Considerations - - In order to make the entire body of Security Considerations more - accessible, Security Considerations for the transport, - authentication, and connection documents have been gathered here. - - The transport protocol [1] provides a confidential channel over an - insecure network. It performs server host authentication, key - exchange, encryption, and integrity protection. It also derives a - unique session id that may be used by higher-level protocols. - - The authentication protocol [2] provides a suite of mechanisms which - can be used to authenticate the client user to the server. - Individual mechanisms specified in the in authentication protocol use - the session id provided by the transport protocol and/or depend on - the security and integrity guarantees of the transport protocol. - - The connection protocol [3] specifies a mechanism to multiplex - multiple streams [channels] of data over the confidential and - authenticated transport. It also specifies channels for accessing an - interactive shell, for 'proxy-forwarding' various external protocols - over the secure transport (including arbitrary TCP/IP protocols), and - for accessing secure 'subsystems' on the server host. - -9.1 Pseudo-Random Number Generation - - This protocol binds each session key to the session by including - random, session specific data in the hash used to produce session - keys. Special care should be taken to ensure that all of the random - numbers are of good quality. If the random data here (e.g., DH - - - -Ylonen & Moffat Expires March 31, 2004 [Page 12] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - parameters) are pseudo-random then the pseudo-random number generator - should be cryptographically secure (i.e., its next output not easily - guessed even when knowing all previous outputs) and, furthermore, - proper entropy needs to be added to the pseudo-random number - generator. RFC 1750 [1750] offers suggestions for sources of random - numbers and entropy. Implementors should note the importance of - entropy and the well-meant, anecdotal warning about the difficulty in - properly implementing pseudo-random number generating functions. - - The amount of entropy available to a given client or server may - sometimes be less than what is required. In this case one must - either resort to pseudo-random number generation regardless of - insufficient entropy or refuse to run the protocol. The latter is - preferable. - -9.2 Transport - -9.2.1 Confidentiality - - It is beyond the scope of this document and the Secure Shell Working - Group to analyze or recommend specific ciphers other than the ones - which have been established and accepted within the industry. At the - time of this writing, ciphers commonly in use include 3DES, ARCFOUR, - twofish, serpent and blowfish. AES has been accepted by The - published as a US Federal Information Processing Standards [FIPS-197] - and the cryptographic community as being acceptable for this purpose - as well has accepted AES. As always, implementors and users should - check current literature to ensure that no recent vulnerabilities - have been found in ciphers used within products. Implementors should - also check to see which ciphers are considered to be relatively - stronger than others and should recommend their use to users over - relatively weaker ciphers. It would be considered good form for an - implementation to politely and unobtrusively notify a user that a - stronger cipher is available and should be used when a weaker one is - actively chosen. - - The "none" cipher is provided for debugging and SHOULD NOT be used - except for that purpose. It's cryptographic properties are - sufficiently described in RFC 2410, which will show that its use does - not meet the intent of this protocol. - - The relative merits of these and other ciphers may also be found in - current literature. Two references that may provide information on - the subject are [SCHNEIER] and [KAUFMAN,PERLMAN,SPECINER]. Both of - these describe the CBC mode of operation of certain ciphers and the - weakness of this scheme. Essentially, this mode is theoretically - vulnerable to chosen cipher-text attacks because of the high - predictability of the start of packet sequence. However, this attack - - - -Ylonen & Moffat Expires March 31, 2004 [Page 13] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - is still deemed difficult and not considered fully practicable - especially if relatively longer block sizes are used. - - Additionally, another CBC mode attack may be mitigated through the - insertion of packets containing SSH_MSG_IGNORE. Without this - technique, a specific attack may be successful. For this attack - (commonly known as the Rogaway attack - [ROGAWAY],[DAI],[BELLARE,KOHNO,NAMPREMPRE]) to work, the attacker - would need to know the IV of the next block that is going to be - encrypted. In CBC mode that is the output of the encryption of the - previous block. If the attacker does not have any way to see the - packet yet (i.e it is in the internal buffers of the ssh - implementation or even in the kernel) then this attack will not work. - If the last packet has been sent out to the network (i.e the attacker - has access to it) then he can use the attack. - - In the optimal case an implementor would need to add an extra packet - only if the packet has been sent out onto the network and there are - no other packets waiting for transmission. Implementors may wish to - check to see if there are any unsent packets awaiting transmission, - but unfortunately it is not normally easy to obtain this information - from the kernel or buffers. If there are not, then a packet - containing SSH_MSG_IGNORE SHOULD be sent. If a new packet is added - to the stream every time the attacker knows the IV that is supposed - to be used for the next packet, then the attacker will not be able to - guess the correct IV, thus the attack will never be successfull. - - As an example, consider the following case: - - - Client Server - ------ ------ - TCP(seq=x, len=500) -> - contains Record 1 - - [500 ms passes, no ACK] - - TCP(seq=x, len=1000) -> - contains Records 1,2 - - ACK - - - 1. The Nagle algorithm + TCP retransmits mean that the two records - get coalesced into a single TCP segment - 2. Record 2 is *not* at the beginning of the TCP segment and never - will be, since it gets ACKed. - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 14] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - 3. Yet, the attack is possible because Record 1 has already been - seen. - - As this example indicates, it's totally unsafe to use the existence - of unflushed data in the TCP buffers proper as a guide to whether you - need an empty packet, since when you do the second write(), the - buffers will contain the un-ACKed Record 1. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 15] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - On the other hand, it's perfectly safe to have the following - situation: - - - Client Server - ------ ------ - TCP(seq=x, len=500) -> - contains SSH_MSG_IGNORE - - TCP(seq=y, len=500) -> - contains Data - - Provided that the IV for second SSH Record is fixed after the data for - the Data packet is determined -i.e. you do: - read from user - encrypt null packet - encrypt data packet - - -9.2.2 Data Integrity - - This protocol does allow the Data Integrity mechanism to be disabled. - Implementors SHOULD be wary of exposing this feature for any purpose - other than debugging. Users and administrators SHOULD be explicitly - warned anytime the "none" MAC is enabled. - - So long as the "none" MAC is not used, this protocol provides data - integrity. - - Because MACs use a 32 bit sequence number, they might start to leak - information after 2**32 packets have been sent. However, following - the rekeying recommendations should prevent this attack. The - transport protocol [1] recommends rekeying after one gigabyte of - data, and the smallest possible packet is 16 bytes. Therefore, - rekeying SHOULD happen after 2**28 packets at the very most. - -9.2.3 Replay - - The use of a MAC other than 'none' provides integrity and - authentication. In addition, the transport protocol provides a - unique session identifier (bound in part to pseudo-random data that - is part of the algorithm and key exchange process) that can be used - by higher level protocols to bind data to a given session and prevent - replay of data from prior sessions. For example, the authentication - protocol uses this to prevent replay of signatures from previous - sessions. Because public key authentication exchanges are - cryptographically bound to the session (i.e., to the initial key - exchange) they cannot be successfully replayed in other sessions. - - - -Ylonen & Moffat Expires March 31, 2004 [Page 16] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - Note that the session ID can be made public without harming the - security of the protocol. - - If two session happen to have the same session ID [hash of key - exchanges] then packets from one can be replayed against the other. - It must be stressed that the chances of such an occurrence are, - needless to say, minimal when using modern cryptographic methods. - This is all the more so true when specifying larger hash function - outputs and DH parameters. - - Replay detection using monotonically increasing sequence numbers as - input to the MAC, or HMAC in some cases, is described in [RFC2085] /> - [RFC2246], [RFC2743], [RFC1964], [RFC2025], and [RFC1510]. The - underlying construct is discussed in [RFC2104]. Essentially a - different sequence number in each packet ensures that at least this - one input to the MAC function will be unique and will provide a - nonrecurring MAC output that is not predictable to an attacker. If - the session stays active long enough, however, this sequence number - will wrap. This event may provide an attacker an opportunity to - replay a previously recorded packet with an identical sequence number - but only if the peers have not rekeyed since the transmission of the - first packet with that sequence number. If the peers have rekeyed, - then the replay will be detected as the MAC check will fail. For - this reason, it must be emphasized that peers MUST rekey before a - wrap of the sequence numbers. Naturally, if an attacker does attempt - to replay a captured packet before the peers have rekeyed, then the - receiver of the duplicate packet will not be able to validate the MAC - and it will be discarded. The reason that the MAC will fail is - because the receiver will formulate a MAC based upon the packet - contents, the shared secret, and the expected sequence number. Since - the replayed packet will not be using that expected sequence number - (the sequence number of the replayed packet will have already been - passed by the receiver) then the calculated MAC will not match the - MAC received with the packet. - -9.2.4 Man-in-the-middle - - This protocol makes no assumptions nor provisions for an - infrastructure or means for distributing the public keys of hosts. It - is expected that this protocol will sometimes be used without first - verifying the association between the server host key and the server - host name. Such usage is vulnerable to man-in-the-middle attacks. - This section describes this and encourages administrators and users - to understand the importance of verifying this association before any - session is initiated. - - There are three cases of man-in-the-middle attacks to consider. The - first is where an attacker places a device between the client and the - - - -Ylonen & Moffat Expires March 31, 2004 [Page 17] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - server before the session is initiated. In this case, the attack - device is trying to mimic the legitimate server and will offer its - public key to the client when the client initiates a session. If it - were to offer the public key of the server, then it would not be able - to decrypt or sign the transmissions between the legitimate server - and the client unless it also had access to the private-key of the - host. The attack device will also, simultaneously to this, initiate - a session to the legitimate server masquerading itself as the client. - If the public key of the server had been securely distributed to the - client prior to that session initiation, the key offered to the - client by the attack device will not match the key stored on the - client. In that case, the user SHOULD be given a warning that the - offered host key does not match the host key cached on the client. - As described in Section 3.1 of [ARCH], the user may be free to accept - the new key and continue the session. It is RECOMMENDED that the - warning provide sufficient information to the user of the client - device so they may make an informed decision. If the user chooses to - continue the session with the stored public-key of the server (not - the public-key offered at the start of the session), then the session - specific data between the attacker and server will be different - between the client-to-attacker session and the attacker-to-server - sessions due to the randomness discussed above. From this, the - attacker will not be able to make this attack work since the attacker - will not be able to correctly sign packets containing this session - specific data from the server since he does not have the private key - of that server. - - The second case that should be considered is similar to the first - case in that it also happens at the time of connection but this case - points out the need for the secure distribution of server public - keys. If the server public keys are not securely distributed then - the client cannot know if it is talking to the intended server. An - attacker may use social engineering techniques to pass off server - keys to unsuspecting users and may then place a man-in-the-middle - attack device between the legitimate server and the clients. If this - is allowed to happen then the clients will form client-to-attacker - sessions and the attacker will form attacker-to-server sessions and - will be able to monitor and manipulate all of the traffic between the - clients and the legitimate servers. Server administrators are - encouraged to make host key fingerprints available for checking by - some means whose security does not rely on the integrity of the - actual host keys. Possible mechanisms are discussed in Section 3.1 - of [SSH-ARCH] and may also include secured Web pages, physical pieces - of paper, etc. Implementors SHOULD provide recommendations on how - best to do this with their implementation. Because the protocol is - extensible, future extensions to the protocol may provide better - mechanisms for dealing with the need to know the server's host key - before connecting. For example, making the host key fingerprint - - - -Ylonen & Moffat Expires March 31, 2004 [Page 18] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - available through a secure DNS lookup, or using kerberos over gssapi - during key exchange to authenticate the server are possibilities. - - In the third man-in-the-middle case, attackers may attempt to - manipulate packets in transit between peers after the session has - been established. As described in the Replay part of this section, a - successful attack of this nature is very improbable. As in the - Replay section, this reasoning does assume that the MAC is secure and - that it is infeasible to construct inputs to a MAC algorithm to give - a known output. This is discussed in much greater detail in Section - 6 of RFC 2104. If the MAC algorithm has a vulnerability or is weak - enough, then the attacker may be able to specify certain inputs to - yield a known MAC. With that they may be able to alter the contents - of a packet in transit. Alternatively the attacker may be able to - exploit the algorithm vulnerability or weakness to find the shared - secret by reviewing the MACs from captured packets. In either of - those cases, an attacker could construct a packet or packets that - could be inserted into an SSH stream. To prevent that, implementors - are encouraged to utilize commonly accepted MAC algorithms and - administrators are encouraged to watch current literature and - discussions of cryptography to ensure that they are not using a MAC - algorithm that has a recently found vulnerability or weakness. - - In summary, the use of this protocol without a reliable association - of the binding between a host and its host keys is inherently - insecure and is NOT RECOMMENDED. It may however be necessary in - non-security critical environments, and will still provide protection - against passive attacks. Implementors of protocols and applications - running on top of this protocol should keep this possibility in mind. - -9.2.5 Denial-of-service - - This protocol is designed to be used over a reliable transport. If - transmission errors or message manipulation occur, the connection is - closed. The connection SHOULD be re-established if this occurs. - Denial of service attacks of this type ("wire cutter") are almost - impossible to avoid. - - In addition, this protocol is vulnerable to Denial of Service attacks - because an attacker can force the server to go through the CPU and - memory intensive tasks of connection setup and key exchange without - authenticating. Implementors SHOULD provide features that make this - more difficult. For example, only allowing connections from a subset - of IPs known to have valid users. - -9.2.6 Covert Channels - - The protocol was not designed to eliminate covert channels. For - - - -Ylonen & Moffat Expires March 31, 2004 [Page 19] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - example, the padding, SSH_MSG_IGNORE messages, and several other - places in the protocol can be used to pass covert information, and - the recipient has no reliable way to verify whether such information - is being sent. - -9.2.7 Forward Secrecy - - It should be noted that the Diffie-Hellman key exchanges may provide - perfect forward secrecy (PFS). PFS is essentially defined as the - cryptographic property of a key-establishment protocol in which the - compromise of a session key or long-term private key after a given - session does not cause the compromise of any earlier session. [ANSI - T1.523-2001] SSHv2 sessions resulting from a key exchange using - diffie-hellman-group1-sha1 are secure even if private keying/ - authentication material is later revealed, but not if the session - keys are revealed. So, given this definition of PFS, SSHv2 does have - PFS. It is hoped that all other key exchange mechanisms proposed and - used in the future will also provide PFS. This property is not - commuted to any of the applications or protocols using SSH as a - transport however. The transport layer of SSH provides - confidentiality for password authentication and other methods that - rely on secret data. - - Of course, if the DH private parameters for the client and server are - revealed then the session key is revealed, but these items can be - thrown away after the key exchange completes. It's worth pointing - out that these items should not be allowed to end up on swap space - and that they should be erased from memory as soon as the key - exchange completes. - -9.3 Authentication Protocol - - The purpose of this protocol is to perform client user - authentication. It assumes that this run over a secure transport - layer protocol, which has already authenticated the server machine, - established an encrypted communications channel, and computed a - unique session identifier for this session. - - Several authentication methods with different security - characteristics are allowed. It is up to the server's local policy - to decide which methods (or combinations of methods) it is willing to - accept for each user. Authentication is no stronger than the weakest - combination allowed. - - The server may go into a "sleep" period after repeated unsuccessful - authentication attempts to make key search more difficult for - attackers. Care should be taken so that this doesn't become a - self-denial of service vector. - - - -Ylonen & Moffat Expires March 31, 2004 [Page 20] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - -9.3.1 Weak Transport - - If the transport layer does not provide confidentiality, - authentication methods that rely on secret data SHOULD be disabled. - If it does not provide strong integrity protection, requests to - change authentication data (e.g. a password change) SHOULD be - disabled to prevent an attacker from modifying the ciphertext - without being noticed, or rendering the new authentication data - unusable (denial of service). - - The assumption as stated above that the Authentication Protocol only - run over a secure transport that has previously authenticated the - server is very important to note. People deploying SSH are reminded - of the consequences of man-in-the-middle attacks if the client does - not have a very strong a priori association of the server with the - host key of that server. Specifically for the case of the - Authentication Protocol the client may form a session to a - man-in-the-middle attack device and divulge user credentials such as - their username and password. Even in the cases of authentication - where no user credentials are divulged, an attacker may still gain - information they shouldn't have by capturing key-strokes in much the - same way that a honeypot works. - -9.3.2 Debug messages - - Special care should be taken when designing debug messages. These - messages may reveal surprising amounts of information about the host - if not properly designed. Debug messages can be disabled (during - user authentication phase) if high security is required. - Administrators of host machines should make all attempts to - compartmentalize all event notification messages and protect them - from unwarranted observation. Developers should be aware of the - sensitive nature of some of the normal event messages and debug - messages and may want to provide guidance to administrators on ways - to keep this information away from unauthorized people. Developers - should consider minimizing the amount of sensitive information - obtainable by users during the authentication phase in accordance - with the local policies. For this reason, it is RECOMMENDED that - debug messages be initially disabled at the time of deployment and - require an active decision by an administrator to allow them to be - enabled. It is also RECOMMENDED that a message expressing this - concern be presented to the administrator of a system when the action - is taken to enable debugging messages. - -9.3.3 Local security policy - - Implementer MUST ensure that the credentials provided validate the - professed user and also MUST ensure that the local policy of the - - - -Ylonen & Moffat Expires March 31, 2004 [Page 21] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - server permits the user the access requested. In particular, because - of the flexible nature of the SSH connection protocol, it may not be - possible to determine the local security policy, if any, that should - apply at the time of authentication because the kind of service being - requested is not clear at that instant. For example, local policy - might allow a user to access files on the server, but not start an - interactive shell. However, during the authentication protocol, it is - not known whether the user will be accessing files or attempting to - use an interactive shell, or even both. In any event, where local - security policy for the server host exists, it MUST be applied and - enforced correctly. - - Implementors are encouraged to provide a default local policy and - make its parameters known to administrators and users. At the - discretion of the implementors, this default policy may be along the - lines of 'anything goes' where there are no restrictions placed upon - users, or it may be along the lines of 'excessively restrictive' in - which case the administrators will have to actively make changes to - this policy to meet their needs. Alternatively, it may be some - attempt at providing something practical and immediately useful to - the administrators of the system so they don't have to put in much - effort to get SSH working. Whatever choice is made MUST be applied - and enforced as required above. - -9.3.4 Public key authentication - - The use of public-key authentication assumes that the client host has - not been compromised. It also assumes that the private-key of the - server host has not been compromised. - - This risk can be mitigated by the use of passphrases on private keys; - however, this is not an enforceable policy. The use of smartcards, - or other technology to make passphrases an enforceable policy is - suggested. - - The server could require both password and public-key authentication, - however, this requires the client to expose its password to the - server (see section on password authentication below.) - -9.3.5 Password authentication - - The password mechanism as specified in the authentication protocol - assumes that the server has not been compromised. If the server has - been compromised, using password authentication will reveal a valid - username / password combination to the attacker, which may lead to - further compromises. - - This vulnerability can be mitigated by using an alternative form of - - - -Ylonen & Moffat Expires March 31, 2004 [Page 22] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - authentication. For example, public-key authentication makes no - assumptions about security on the server. - -9.3.6 Host based authentication - - Host based authentication assumes that the client has not been - compromised. There are no mitigating strategies, other than to use - host based authentication in combination with another authentication - method. - -9.4 Connection protocol - -9.4.1 End point security - - End point security is assumed by the connection protocol. If the - server has been compromised, any terminal sessions, port forwarding, - or systems accessed on the host are compromised. There are no - mitigating factors for this. - - If the client end point has been compromised, and the server fails to - stop the attacker at the authentication protocol, all services - exposed (either as subsystems or through forwarding) will be - vulnerable to attack. Implementors SHOULD provide mechanisms for - administrators to control which services are exposed to limit the - vulnerability of other services. - - These controls might include controlling which machines and ports can - be target in 'port-forwarding' operations, which users are allowed to - use interactive shell facilities, or which users are allowed to use - exposed subsystems. - -9.4.2 Proxy forwarding - - The SSH connection protocol allows for proxy forwarding of other - protocols such as SNMP, POP3, and HTTP. This may be a concern for - network administrators who wish to control the access of certain - applications by users located outside of their physical location. - Essentially, the forwarding of these protocols may violate site - specific security policies as they may be undetectably tunneled - through a firewall. Implementors SHOULD provide an administrative - mechanism to control the proxy forwarding functionality so that site - specific security policies may be upheld. - - In addition, a reverse proxy forwarding functionality is available, - which again can be used to bypass firewall controls. - - As indicated above, end-point security is assumed during proxy - forwarding operations. Failure of end-point security will compromise - - - -Ylonen & Moffat Expires March 31, 2004 [Page 23] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - all data passed over proxy forwarding. - -9.4.3 X11 forwarding - - Another form of proxy forwarding provided by the ssh connection - protocol is the forwarding of the X11 protocol. If end-point - security has been compromised, X11 forwarding may allow attacks - against the X11 server. Users and administrators should, as a matter - of course, use appropriate X11 security mechanisms to prevent - unauthorized use of the X11 server. Implementors, administrators and - users who wish to further explore the security mechanisms of X11 are - invited to read [SCHEIFLER] and analyze previously reported problems - with the interactions between SSH forwarding and X11 in CERT - vulnerabilities VU#363181 and VU#118892 [CERT]. - - X11 display forwarding with SSH, by itself, is not sufficient to - correct well known problems with X11 security [VENEMA]. However, X11 - display forwarding in SSHv2 (or other, secure protocols), combined - with actual and pseudo-displays which accept connections only over - local IPC mechanisms authorized by permissions or ACLs, does correct - many X11 security problems as long as the "none" MAC is not used. It - is RECOMMENDED that X11 display implementations default to allowing - display opens only over local IPC. It is RECOMMENDED that SSHv2 - server implementations that support X11 forwarding default to - allowing display opens only over local IPC. On single-user systems - it might be reasonable to default to allowing local display opens - over TCP/IP. - - Implementors of the X11 forwarding protocol SHOULD implement the - magic cookie access checking spoofing mechanism as described in - [ssh-connect] as an additional mechanism to prevent unauthorized use - of the proxy. - -Normative References - - [SSH-ARCH] - Ylonen, T., "SSH Protocol Architecture", I-D - draft-ietf-architecture-15.txt, Oct 2003. - - [SSH-TRANS] - Ylonen, T., "SSH Transport Layer Protocol", I-D - draft-ietf-transport-17.txt, Oct 2003. - - [SSH-USERAUTH] - Ylonen, T., "SSH Authentication Protocol", I-D - draft-ietf-userauth-18.txt, Oct 2003. - - [SSH-CONNECT] - - - -Ylonen & Moffat Expires March 31, 2004 [Page 24] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - Ylonen, T., "SSH Connection Protocol", I-D - draft-ietf-connect-18.txt, Oct 2003. - - [SSH-NUMBERS] - Lehtinen, S. and D. Moffat, "SSH Protocol Assigned - Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct - 2003. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - -Informative References - - [FIPS-186] - Federal Information Processing Standards Publication, - "FIPS PUB 186, Digital Signature Standard", May 1994. - - [FIPS-197] - National Institue of Standards and Technology, "FIPS 197, - Specification for the Advanced Encryption Standard", - November 2001. - - [ANSI T1.523-2001] - American National Standards Insitute, Inc., "Telecom - Glossary 2000", February 2001. - - [SCHEIFLER] - Scheifler, R., "X Window System : The Complete Reference - to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital - Press ISBN 1555580882, Feburary 1992. - - [RFC0854] Postel, J. and J. Reynolds, "Telnet Protocol - Specification", STD 8, RFC 854, May 1983. - - [RFC0894] Hornig, C., "Standard for the transmission of IP datagrams - over Ethernet networks", STD 41, RFC 894, April 1984. - - [RFC1034] Mockapetris, P., "Domain names - concepts and facilities", - STD 13, RFC 1034, November 1987. - - [RFC1134] Perkins, D., "Point-to-Point Protocol: A proposal for - multi-protocol transmission of datagrams over - Point-to-Point links", RFC 1134, November 1989. - - [RFC1282] Kantor, B., "BSD Rlogin", RFC 1282, December 1991. - - [RFC1510] Kohl, J. and B. Neuman, "The Kerberos Network - Authentication Service (V5)", RFC 1510, September 1993. - - - -Ylonen & Moffat Expires March 31, 2004 [Page 25] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - [RFC1700] Reynolds, J. and J. Postel, "Assigned Numbers", RFC 1700, - October 1994. - - [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness - Recommendations for Security", RFC 1750, December 1994. - - [RFC3066] Alvestrand, H., "Tags for the Identification of - Languages", BCP 47, RFC 3066, January 2001. - - [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC - 1964, June 1996. - - [RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism - (SPKM)", RFC 2025, October 1996. - - [RFC2085] Oehler, M. and R. Glenn, "HMAC-MD5 IP Authentication with - Replay Prevention", RFC 2085, February 1997. - - [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: - Keyed-Hashing for Message Authentication", RFC 2104, - February 1997. - - [RFC2246] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. - and P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, - January 1999. - - [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - - [RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm and - Its Use With IPsec", RFC 2410, November 1998. - - [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an - IANA Considerations Section in RFCs", BCP 26, RFC 2434, - October 1998. - - [RFC2743] Linn, J., "Generic Security Service Application Program - Interface Version 2, Update 1", RFC 2743, January 2000. - - [SCHNEIER] - Schneier, B., "Applied Cryptography Second Edition: - protocols algorithms and source in code in C", 1996. - - [KAUFMAN,PERLMAN,SPECINER] - Kaufman, C., Perlman, R. and M. Speciner, "Network - Security: PRIVATE Communication in a PUBLIC World", 1995. - - [CERT] CERT Coordination Center, The., "http://www.cert.org/nav/ - - - -Ylonen & Moffat Expires March 31, 2004 [Page 26] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - index_red.html". - - [VENEMA] Venema, W., "Murphy's Law and Computer Security", - Proceedings of 6th USENIX Security Symposium, San Jose CA - http://www.usenix.org/publications/library/proceedings/ - sec96/venema.html, July 1996. - - [ROGAWAY] Rogaway, P., "Problems with Proposed IP Cryptography", - Unpublished paper http://www.cs.ucdavis.edu/~rogaway/ - papers/draft-rogaway-ipsec-comments-00.txt, 1996. - - [DAI] Dai, W., "An attack against SSH2 protocol", Email to the - SECSH Working Group ietf-ssh@netbsd.org ftp:// - ftp.ietf.org/ietf-mail-archive/secsh/2002-02.mail, Feb - 2002. - - [BELLARE,KOHNO,NAMPREMPRE] - Bellaire, M., Kohno, T. and C. Namprempre, "Authenticated - Encryption in SSH: Fixing the SSH Binary Packet Protocol", - , Sept 2002. - - -Authors' Addresses - - Tatu Ylonen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: ylo@ssh.com - - - Darren J. Moffat (editor) - Sun Microsystems, Inc - 17 Network Circle - Menlo Park CA 94025 - USA - - EMail: Darren.Moffat@Sun.COM - - - - - - - - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 27] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - -Intellectual Property Statement - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementors or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - The IETF has been notified of intellectual property rights claimed in - regard to some or all of the specification contained in this - document. For more information consult the online list of claimed - rights. - - -Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assignees. - - - -Ylonen & Moffat Expires March 31, 2004 [Page 28] - -Internet-Draft SSH Protocol Architecture Oct 2003 - - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - -Acknowledgment - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat Expires March 31, 2004 [Page 29] \ No newline at end of file diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps deleted file mode 100644 index 7a386724c2..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps +++ /dev/null @@ -1,2557 +0,0 @@ -%!PS-Adobe-3.0 -%%BoundingBox: 75 0 595 747 -%%Title: Enscript Output -%%For: Magnus Thoang -%%Creator: GNU enscript 1.6.1 -%%CreationDate: Fri Oct 31 13:33:02 2003 -%%Orientation: Portrait -%%Pages: 11 0 -%%DocumentMedia: A4 595 842 0 () () -%%DocumentNeededResources: (atend) -%%EndComments -%%BeginProlog -%%BeginProcSet: PStoPS 1 15 -userdict begin -[/showpage/erasepage/copypage]{dup where{pop dup load - type/operatortype eq{1 array cvx dup 0 3 index cvx put - bind def}{pop}ifelse}{pop}ifelse}forall -[/letter/legal/executivepage/a4/a4small/b5/com10envelope - /monarchenvelope/c5envelope/dlenvelope/lettersmall/note - /folio/quarto/a5]{dup where{dup wcheck{exch{}put} - {pop{}def}ifelse}{pop}ifelse}forall -/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put} - {pop def}ifelse}{def}ifelse -/PStoPSmatrix matrix currentmatrix def -/PStoPSxform matrix def/PStoPSclip{clippath}def -/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def -/initmatrix{matrix defaultmatrix setmatrix}bind def -/initclip[{matrix currentmatrix PStoPSmatrix setmatrix - [{currentpoint}stopped{$error/newerror false put{newpath}} - {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse] - {[/newpath cvx{/moveto cvx}{/lineto cvx} - {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop} - stopped{$error/errorname get/invalidaccess eq{cleartomark - $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop - /initclip dup load dup type dup/operatortype eq{pop exch pop} - {dup/arraytype eq exch/packedarraytype eq or - {dup xcheck{exch pop aload pop}{pop cvx}ifelse} - {pop cvx}ifelse}ifelse - {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def -/initgraphics{initmatrix newpath initclip 1 setlinewidth - 0 setlinecap 0 setlinejoin []0 setdash 0 setgray - 10 setmiterlimit}bind def -end -%%EndProcSet -%%BeginResource: procset Enscript-Prolog 1.6 1 -% -% Procedures. -% - -/_S { % save current state - /_s save def -} def -/_R { % restore from saved state - _s restore -} def - -/S { % showpage protecting gstate - gsave - showpage - grestore -} bind def - -/MF { % fontname newfontname -> - make a new encoded font - /newfontname exch def - /fontname exch def - - /fontdict fontname findfont def - /newfont fontdict maxlength dict def - - fontdict { - exch - dup /FID eq { - % skip FID pair - pop pop - } { - % copy to the new font dictionary - exch newfont 3 1 roll put - } ifelse - } forall - - newfont /FontName newfontname put - - % insert only valid encoding vectors - encoding_vector length 256 eq { - newfont /Encoding encoding_vector put - } if - - newfontname newfont definefont pop -} def - -/SF { % fontname width height -> - set a new font - /height exch def - /width exch def - - findfont - [width 0 0 height 0 0] makefont setfont -} def - -/SUF { % fontname width height -> - set a new user font - /height exch def - /width exch def - - /F-gs-user-font MF - /F-gs-user-font width height SF -} def - -/M {moveto} bind def -/s {show} bind def - -/Box { % x y w h -> - define box path - /d_h exch def /d_w exch def /d_y exch def /d_x exch def - d_x d_y moveto - d_w 0 rlineto - 0 d_h rlineto - d_w neg 0 rlineto - closepath -} def - -/bgs { % x y height blskip gray str -> - show string with bg color - /str exch def - /gray exch def - /blskip exch def - /height exch def - /y exch def - /x exch def - - gsave - x y blskip sub str stringwidth pop height Box - gray setgray - fill - grestore - x y M str s -} def - -% Highlight bars. -/highlight_bars { % nlines lineheight output_y_margin gray -> - - gsave - setgray - /ymarg exch def - /lineheight exch def - /nlines exch def - - % This 2 is just a magic number to sync highlight lines to text. - 0 d_header_y ymarg sub 2 sub translate - - /cw d_output_w cols div def - /nrows d_output_h ymarg 2 mul sub lineheight div cvi def - - % for each column - 0 1 cols 1 sub { - cw mul /xp exch def - - % for each rows - 0 1 nrows 1 sub { - /rn exch def - rn lineheight mul neg /yp exch def - rn nlines idiv 2 mod 0 eq { - % Draw highlight bar. 4 is just a magic indentation. - xp 4 add yp cw 8 sub lineheight neg Box fill - } if - } for - } for - - grestore -} def - -% Line highlight bar. -/line_highlight { % x y width height gray -> - - gsave - /gray exch def - Box gray setgray fill - grestore -} def - -% Column separator lines. -/column_lines { - gsave - .1 setlinewidth - 0 d_footer_h translate - /cw d_output_w cols div def - 1 1 cols 1 sub { - cw mul 0 moveto - 0 d_output_h rlineto stroke - } for - grestore -} def - -% Column borders. -/column_borders { - gsave - .1 setlinewidth - 0 d_footer_h moveto - 0 d_output_h rlineto - d_output_w 0 rlineto - 0 d_output_h neg rlineto - closepath stroke - grestore -} def - -% Do the actual underlay drawing -/draw_underlay { - ul_style 0 eq { - ul_str true charpath stroke - } { - ul_str show - } ifelse -} def - -% Underlay -/underlay { % - -> - - gsave - 0 d_page_h translate - d_page_h neg d_page_w atan rotate - - ul_gray setgray - ul_font setfont - /dw d_page_h dup mul d_page_w dup mul add sqrt def - ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto - draw_underlay - grestore -} def - -/user_underlay { % - -> - - gsave - ul_x ul_y translate - ul_angle rotate - ul_gray setgray - ul_font setfont - 0 0 ul_h_ptsize 2 div sub moveto - draw_underlay - grestore -} def - -% Page prefeed -/page_prefeed { % bool -> - - statusdict /prefeed known { - statusdict exch /prefeed exch put - } { - pop - } ifelse -} def - -% Wrapped line markers -/wrapped_line_mark { % x y charwith charheight type -> - - /type exch def - /h exch def - /w exch def - /y exch def - /x exch def - - type 2 eq { - % Black boxes (like TeX does) - gsave - 0 setlinewidth - x w 4 div add y M - 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto - closepath fill - grestore - } { - type 3 eq { - % Small arrows - gsave - .2 setlinewidth - x w 2 div add y h 2 div add M - w 4 div 0 rlineto - x w 4 div add y lineto stroke - - x w 4 div add w 8 div add y h 4 div add M - x w 4 div add y lineto - w 4 div h 8 div rlineto stroke - grestore - } { - % do nothing - } ifelse - } ifelse -} def - -% EPSF import. - -/BeginEPSF { - /b4_Inc_state save def % Save state for cleanup - /dict_count countdictstack def % Count objects on dict stack - /op_count count 1 sub def % Count objects on operand stack - userdict begin - /showpage { } def - 0 setgray 0 setlinecap - 1 setlinewidth 0 setlinejoin - 10 setmiterlimit [ ] 0 setdash newpath - /languagelevel where { - pop languagelevel - 1 ne { - false setstrokeadjust false setoverprint - } if - } if -} bind def - -/EndEPSF { - count op_count sub { pos } repeat % Clean up stacks - countdictstack dict_count sub { end } repeat - b4_Inc_state restore -} bind def - -% Check PostScript language level. -/languagelevel where { - pop /gs_languagelevel languagelevel def -} { - /gs_languagelevel 1 def -} ifelse -%%EndResource -%%BeginResource: procset Enscript-Encoding-88591 1.6 1 -/encoding_vector [ -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclam /quotedbl /numbersign -/dollar /percent /ampersand /quoteright -/parenleft /parenright /asterisk /plus -/comma /hyphen /period /slash -/zero /one /two /three -/four /five /six /seven -/eight /nine /colon /semicolon -/less /equal /greater /question -/at /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 /bracketleft -/backslash /bracketright /asciicircum /underscore -/quoteleft /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 /braceleft -/bar /braceright /tilde /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclamdown /cent /sterling -/currency /yen /brokenbar /section -/dieresis /copyright /ordfeminine /guillemotleft -/logicalnot /hyphen /registered /macron -/degree /plusminus /twosuperior /threesuperior -/acute /mu /paragraph /bullet -/cedilla /onesuperior /ordmasculine /guillemotright -/onequarter /onehalf /threequarters /questiondown -/Agrave /Aacute /Acircumflex /Atilde -/Adieresis /Aring /AE /Ccedilla -/Egrave /Eacute /Ecircumflex /Edieresis -/Igrave /Iacute /Icircumflex /Idieresis -/Eth /Ntilde /Ograve /Oacute -/Ocircumflex /Otilde /Odieresis /multiply -/Oslash /Ugrave /Uacute /Ucircumflex -/Udieresis /Yacute /Thorn /germandbls -/agrave /aacute /acircumflex /atilde -/adieresis /aring /ae /ccedilla -/egrave /eacute /ecircumflex /edieresis -/igrave /iacute /icircumflex /idieresis -/eth /ntilde /ograve /oacute -/ocircumflex /otilde /odieresis /divide -/oslash /ugrave /uacute /ucircumflex -/udieresis /yacute /thorn /ydieresis -] def -%%EndResource -%%EndProlog -%%BeginSetup -%%IncludeResource: font Courier-Bold -%%IncludeResource: font Courier -/HFpt_w 10 def -/HFpt_h 10 def -/Courier-Bold /HF-gs-font MF -/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def -/Courier /F-gs-font MF -/F-gs-font 10 10 SF -/#copies 1 def -/d_page_w 520 def -/d_page_h 747 def -/d_header_x 0 def -/d_header_y 747 def -/d_header_w 520 def -/d_header_h 0 def -/d_footer_x 0 def -/d_footer_y 0 def -/d_footer_w 520 def -/d_footer_h 0 def -/d_output_w 520 def -/d_output_h 747 def -/cols 1 def -userdict/PStoPSxform PStoPSmatrix matrix currentmatrix - matrix invertmatrix matrix concatmatrix - matrix invertmatrix put -%%EndSetup -%%Page: (0,1) 1 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 1 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 701 M -(Network Working Group T. Ylonen) s -5 690 M -(Internet-Draft SSH Communications Security Corp) s -5 679 M -(Expires: March 31, 2004 D. Moffat, Editor, Ed.) s -5 668 M -( Sun Microsystems, Inc) s -5 657 M -( Oct 2003) s -5 624 M -( SSH Connection Protocol) s -5 613 M -( draft-ietf-secsh-connect-18.txt) s -5 591 M -(Status of this Memo) s -5 569 M -( This document is an Internet-Draft and is in full conformance with) s -5 558 M -( all provisions of Section 10 of RFC2026.) s -5 536 M -( Internet-Drafts are working documents of the Internet Engineering) s -5 525 M -( Task Force \(IETF\), its areas, and its working groups. Note that other) s -5 514 M -( groups may also distribute working documents as Internet-Drafts.) s -5 492 M -( Internet-Drafts are draft documents valid for a maximum of six months) s -5 481 M -( and may be updated, replaced, or obsoleted by other documents at any) s -5 470 M -( time. It is inappropriate to use Internet-Drafts as reference) s -5 459 M -( material or to cite them other than as "work in progress.") s -5 437 M -( The list of current Internet-Drafts can be accessed at http://) s -5 426 M -( www.ietf.org/ietf/1id-abstracts.txt.) s -5 404 M -( The list of Internet-Draft Shadow Directories can be accessed at) s -5 393 M -( http://www.ietf.org/shadow.html.) s -5 371 M -( This Internet-Draft will expire on March 31, 2004.) s -5 349 M -(Copyright Notice) s -5 327 M -( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s -5 305 M -(Abstract) s -5 283 M -( SSH is a protocol for secure remote login and other secure network) s -5 272 M -( services over an insecure network.) s -5 250 M -( This document describes the SSH Connection Protocol. It provides) s -5 239 M -( interactive login sessions, remote execution of commands, forwarded) s -5 228 M -( TCP/IP connections, and forwarded X11 connections. All of these) s -5 217 M -( channels are multiplexed into a single encrypted tunnel.) s -5 195 M -( The SSH Connection Protocol has been designed to run on top of the) s -5 184 M -( SSH transport layer and user authentication protocols.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 2 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -(Table of Contents) s -5 668 M -( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 657 M -( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 646 M -( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s -5 635 M -( 4. Global Requests . . . . . . . . . . . . . . . . . . . . . . 3) s -5 624 M -( 5. Channel Mechanism . . . . . . . . . . . . . . . . . . . . . 4) s -5 613 M -( 5.1 Opening a Channel . . . . . . . . . . . . . . . . . . . . . 4) s -5 602 M -( 5.2 Data Transfer . . . . . . . . . . . . . . . . . . . . . . . 5) s -5 591 M -( 5.3 Closing a Channel . . . . . . . . . . . . . . . . . . . . . 6) s -5 580 M -( 5.4 Channel-Specific Requests . . . . . . . . . . . . . . . . . 7) s -5 569 M -( 6. Interactive Sessions . . . . . . . . . . . . . . . . . . . . 8) s -5 558 M -( 6.1 Opening a Session . . . . . . . . . . . . . . . . . . . . . 8) s -5 547 M -( 6.2 Requesting a Pseudo-Terminal . . . . . . . . . . . . . . . . 8) s -5 536 M -( 6.3 X11 Forwarding . . . . . . . . . . . . . . . . . . . . . . . 9) s -5 525 M -( 6.3.1 Requesting X11 Forwarding . . . . . . . . . . . . . . . . . 9) s -5 514 M -( 6.3.2 X11 Channels . . . . . . . . . . . . . . . . . . . . . . . . 10) s -5 503 M -( 6.4 Environment Variable Passing . . . . . . . . . . . . . . . . 10) s -5 492 M -( 6.5 Starting a Shell or a Command . . . . . . . . . . . . . . . 10) s -5 481 M -( 6.6 Session Data Transfer . . . . . . . . . . . . . . . . . . . 11) s -5 470 M -( 6.7 Window Dimension Change Message . . . . . . . . . . . . . . 12) s -5 459 M -( 6.8 Local Flow Control . . . . . . . . . . . . . . . . . . . . . 12) s -5 448 M -( 6.9 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 12) s -5 437 M -( 6.10 Returning Exit Status . . . . . . . . . . . . . . . . . . . 13) s -5 426 M -( 7. TCP/IP Port Forwarding . . . . . . . . . . . . . . . . . . . 14) s -5 415 M -( 7.1 Requesting Port Forwarding . . . . . . . . . . . . . . . . . 14) s -5 404 M -( 7.2 TCP/IP Forwarding Channels . . . . . . . . . . . . . . . . . 15) s -5 393 M -( 8. Encoding of Terminal Modes . . . . . . . . . . . . . . . . . 16) s -5 382 M -( 9. Summary of Message Numbers . . . . . . . . . . . . . . . . . 18) s -5 371 M -( 10. Security Considerations . . . . . . . . . . . . . . . . . . 18) s -5 360 M -( 11. iana cONSiderations . . . . . . . . . . . . . . . . . . . . 19) s -5 349 M -( 12. Intellectual Property . . . . . . . . . . . . . . . . . . . 19) s -5 338 M -( Normative References . . . . . . . . . . . . . . . . . . . . 19) s -5 327 M -( Informative References . . . . . . . . . . . . . . . . . . . 20) s -5 316 M -( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 20) s -5 305 M -( Intellectual Property and Copyright Statements . . . . . . . 21) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]) s -_R -S -PStoPSsaved restore -%%Page: (2,3) 2 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 3 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -(1. Contributors) s -5 668 M -( The major original contributors of this document were: Tatu Ylonen,) s -5 657 M -( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s -5 646 M -( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s -5 635 M -( Jyvaskyla\)) s -5 613 M -( The document editor is: Darren.Moffat@Sun.COM. Comments on this) s -5 602 M -( internet draft should be sent to the IETF SECSH working group,) s -5 591 M -( details at: http://ietf.org/html.charters/secsh-charter.html) s -5 569 M -(2. Introduction) s -5 547 M -( The SSH Connection Protocol has been designed to run on top of the) s -5 536 M -( SSH transport layer and user authentication protocols. It provides) s -5 525 M -( interactive login sessions, remote execution of commands, forwarded) s -5 514 M -( TCP/IP connections, and forwarded X11 connections. The service name) s -5 503 M -( for this protocol is "ssh-connection".) s -5 481 M -( This document should be read only after reading the SSH architecture) s -5 470 M -( document [SSH-ARCH]. This document freely uses terminology and) s -5 459 M -( notation from the architecture document without reference or further) s -5 448 M -( explanation.) s -5 426 M -(3. Conventions Used in This Document) s -5 404 M -( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s -5 393 M -( and "MAY" that appear in this document are to be interpreted as) s -5 382 M -( described in [RFC2119].) s -5 360 M -( The used data types and terminology are specified in the architecture) s -5 349 M -( document [SSH-ARCH].) s -5 327 M -( The architecture document also discusses the algorithm naming) s -5 316 M -( conventions that MUST be used with the SSH protocols.) s -5 294 M -(4. Global Requests) s -5 272 M -( There are several kinds of requests that affect the state of the) s -5 261 M -( remote end "globally", independent of any channels. An example is a) s -5 250 M -( request to start TCP/IP forwarding for a specific port. All such) s -5 239 M -( requests use the following format.) s -5 217 M -( byte SSH_MSG_GLOBAL_REQUEST) s -5 206 M -( string request name \(restricted to US-ASCII\)) s -5 195 M -( boolean want reply) s -5 184 M -( ... request-specific data follows) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 4 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( Request names follow the DNS extensibility naming convention outlined) s -5 679 M -( in [SSH-ARCH].) s -5 657 M -( The recipient will respond to this message with) s -5 646 M -( SSH_MSG_REQUEST_SUCCESS or SSH_MSG_REQUEST_FAILURE if `want reply' is) s -5 635 M -( TRUE.) s -5 613 M -( byte SSH_MSG_REQUEST_SUCCESS) s -5 602 M -( ..... response specific data) s -5 580 M -( Usually the response specific data is non-existent.) s -5 558 M -( If the recipient does not recognize or support the request, it simply) s -5 547 M -( responds with SSH_MSG_REQUEST_FAILURE.) s -5 525 M -( byte SSH_MSG_REQUEST_FAILURE) s -5 492 M -(5. Channel Mechanism) s -5 470 M -( All terminal sessions, forwarded connections, etc. are channels.) s -5 459 M -( Either side may open a channel. Multiple channels are multiplexed) s -5 448 M -( into a single connection.) s -5 426 M -( Channels are identified by numbers at each end. The number referring) s -5 415 M -( to a channel may be different on each side. Requests to open a) s -5 404 M -( channel contain the sender's channel number. Any other) s -5 393 M -( channel-related messages contain the recipient's channel number for) s -5 382 M -( the channel.) s -5 360 M -( Channels are flow-controlled. No data may be sent to a channel until) s -5 349 M -( a message is received to indicate that window space is available.) s -5 327 M -(5.1 Opening a Channel) s -5 305 M -( When either side wishes to open a new channel, it allocates a local) s -5 294 M -( number for the channel. It then sends the following message to the) s -5 283 M -( other side, and includes the local channel number and initial window) s -5 272 M -( size in the message.) s -5 250 M -( byte SSH_MSG_CHANNEL_OPEN) s -5 239 M -( string channel type \(restricted to US-ASCII\)) s -5 228 M -( uint32 sender channel) s -5 217 M -( uint32 initial window size) s -5 206 M -( uint32 maximum packet size) s -5 195 M -( ... channel type specific data follows) s -5 173 M -( The channel type is a name as described in the SSH architecture) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]) s -_R -S -PStoPSsaved restore -%%Page: (4,5) 3 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 5 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( document, with similar extension mechanisms. `sender channel' is a) s -5 679 M -( local identifier for the channel used by the sender of this message.) s -5 668 M -( `initial window size' specifies how many bytes of channel data can be) s -5 657 M -( sent to the sender of this message without adjusting the window.) s -5 646 M -( `Maximum packet size' specifies the maximum size of an individual) s -5 635 M -( data packet that can be sent to the sender \(for example, one might) s -5 624 M -( want to use smaller packets for interactive connections to get better) s -5 613 M -( interactive response on slow links\).) s -5 591 M -( The remote side then decides whether it can open the channel, and) s -5 580 M -( responds with either) s -5 558 M -( byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION) s -5 547 M -( uint32 recipient channel) s -5 536 M -( uint32 sender channel) s -5 525 M -( uint32 initial window size) s -5 514 M -( uint32 maximum packet size) s -5 503 M -( ... channel type specific data follows) s -5 481 M -( where `recipient channel' is the channel number given in the original) s -5 470 M -( open request, and `sender channel' is the channel number allocated by) s -5 459 M -( the other side, or) s -5 437 M -( byte SSH_MSG_CHANNEL_OPEN_FAILURE) s -5 426 M -( uint32 recipient channel) s -5 415 M -( uint32 reason code) s -5 404 M -( string additional textual information \(ISO-10646 UTF-8 [RFC2279]\)) s -5 393 M -( string language tag \(as defined in [RFC3066]\)) s -5 371 M -( If the recipient of the SSH_MSG_CHANNEL_OPEN message does not support) s -5 360 M -( the specified channel type, it simply responds with) s -5 349 M -( SSH_MSG_CHANNEL_OPEN_FAILURE. The client MAY show the additional) s -5 338 M -( information to the user. If this is done, the client software should) s -5 327 M -( take the precautions discussed in [SSH-ARCH].) s -5 305 M -( The following reason codes are defined:) s -5 283 M -( #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1) s -5 272 M -( #define SSH_OPEN_CONNECT_FAILED 2) s -5 261 M -( #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3) s -5 250 M -( #define SSH_OPEN_RESOURCE_SHORTAGE 4) s -5 217 M -(5.2 Data Transfer) s -5 195 M -( The window size specifies how many bytes the other party can send) s -5 184 M -( before it must wait for the window to be adjusted. Both parties use) s -5 173 M -( the following message to adjust the window.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 6 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( byte SSH_MSG_CHANNEL_WINDOW_ADJUST) s -5 679 M -( uint32 recipient channel) s -5 668 M -( uint32 bytes to add) s -5 646 M -( After receiving this message, the recipient MAY send the given number) s -5 635 M -( of bytes more than it was previously allowed to send; the window size) s -5 624 M -( is incremented.) s -5 602 M -( Data transfer is done with messages of the following type.) s -5 580 M -( byte SSH_MSG_CHANNEL_DATA) s -5 569 M -( uint32 recipient channel) s -5 558 M -( string data) s -5 536 M -( The maximum amount of data allowed is the current window size. The) s -5 525 M -( window size is decremented by the amount of data sent. Both parties) s -5 514 M -( MAY ignore all extra data sent after the allowed window is empty.) s -5 492 M -( Additionally, some channels can transfer several types of data. An) s -5 481 M -( example of this is stderr data from interactive sessions. Such data) s -5 470 M -( can be passed with SSH_MSG_CHANNEL_EXTENDED_DATA messages, where a) s -5 459 M -( separate integer specifies the type of the data. The available types) s -5 448 M -( and their interpretation depend on the type of the channel.) s -5 426 M -( byte SSH_MSG_CHANNEL_EXTENDED_DATA) s -5 415 M -( uint32 recipient_channel) s -5 404 M -( uint32 data_type_code) s -5 393 M -( string data) s -5 371 M -( Data sent with these messages consumes the same window as ordinary) s -5 360 M -( data.) s -5 338 M -( Currently, only the following type is defined.) s -5 316 M -( #define SSH_EXTENDED_DATA_STDERR 1) s -5 283 M -(5.3 Closing a Channel) s -5 261 M -( When a party will no longer send more data to a channel, it SHOULD) s -5 250 M -( send SSH_MSG_CHANNEL_EOF.) s -5 228 M -( byte SSH_MSG_CHANNEL_EOF) s -5 217 M -( uint32 recipient_channel) s -5 195 M -( No explicit response is sent to this message; however, the) s -5 184 M -( application may send EOF to whatever is at the other end of the) s -5 173 M -( channel. Note that the channel remains open after this message, and) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]) s -_R -S -PStoPSsaved restore -%%Page: (6,7) 4 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 7 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( more data may still be sent in the other direction. This message) s -5 679 M -( does not consume window space and can be sent even if no window space) s -5 668 M -( is available.) s -5 646 M -( When either party wishes to terminate the channel, it sends) s -5 635 M -( SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST) s -5 624 M -( send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this) s -5 613 M -( message for the channel. The channel is considered closed for a) s -5 602 M -( party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and) s -5 591 M -( the party may then reuse the channel number. A party MAY send) s -5 580 M -( SSH_MSG_CHANNEL_CLOSE without having sent or received) s -5 569 M -( SSH_MSG_CHANNEL_EOF.) s -5 547 M -( byte SSH_MSG_CHANNEL_CLOSE) s -5 536 M -( uint32 recipient_channel) s -5 514 M -( This message does not consume window space and can be sent even if no) s -5 503 M -( window space is available.) s -5 481 M -( It is recommended that any data sent before this message is delivered) s -5 470 M -( to the actual destination, if possible.) s -5 448 M -(5.4 Channel-Specific Requests) s -5 426 M -( Many channel types have extensions that are specific to that) s -5 415 M -( particular channel type. An example is requesting a pty \(pseudo) s -5 404 M -( terminal\) for an interactive session.) s -5 382 M -( All channel-specific requests use the following format.) s -5 360 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 349 M -( uint32 recipient channel) s -5 338 M -( string request type \(restricted to US-ASCII\)) s -5 327 M -( boolean want reply) s -5 316 M -( ... type-specific data) s -5 294 M -( If want reply is FALSE, no response will be sent to the request.) s -5 283 M -( Otherwise, the recipient responds with either SSH_MSG_CHANNEL_SUCCESS) s -5 272 M -( or SSH_MSG_CHANNEL_FAILURE, or request-specific continuation) s -5 261 M -( messages. If the request is not recognized or is not supported for) s -5 250 M -( the channel, SSH_MSG_CHANNEL_FAILURE is returned.) s -5 228 M -( This message does not consume window space and can be sent even if no) s -5 217 M -( window space is available. Request types are local to each channel) s -5 206 M -( type.) s -5 184 M -( The client is allowed to send further messages without waiting for) s -5 173 M -( the response to the request.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 8 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( request type names follow the DNS extensibility naming convention) s -5 679 M -( outlined in [SSH-ARCH]) s -5 657 M -( byte SSH_MSG_CHANNEL_SUCCESS) s -5 646 M -( uint32 recipient_channel) s -5 613 M -( byte SSH_MSG_CHANNEL_FAILURE) s -5 602 M -( uint32 recipient_channel) s -5 580 M -( These messages do not consume window space and can be sent even if no) s -5 569 M -( window space is available.) s -5 547 M -(6. Interactive Sessions) s -5 525 M -( A session is a remote execution of a program. The program may be a) s -5 514 M -( shell, an application, a system command, or some built-in subsystem.) s -5 503 M -( It may or may not have a tty, and may or may not involve X11) s -5 492 M -( forwarding. Multiple sessions can be active simultaneously.) s -5 470 M -(6.1 Opening a Session) s -5 448 M -( A session is started by sending the following message.) s -5 426 M -( byte SSH_MSG_CHANNEL_OPEN) s -5 415 M -( string "session") s -5 404 M -( uint32 sender channel) s -5 393 M -( uint32 initial window size) s -5 382 M -( uint32 maximum packet size) s -5 360 M -( Client implementations SHOULD reject any session channel open) s -5 349 M -( requests to make it more difficult for a corrupt server to attack the) s -5 338 M -( client.) s -5 316 M -(6.2 Requesting a Pseudo-Terminal) s -5 294 M -( A pseudo-terminal can be allocated for the session by sending the) s -5 283 M -( following message.) s -5 261 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 250 M -( uint32 recipient_channel) s -5 239 M -( string "pty-req") s -5 228 M -( boolean want_reply) s -5 217 M -( string TERM environment variable value \(e.g., vt100\)) s -5 206 M -( uint32 terminal width, characters \(e.g., 80\)) s -5 195 M -( uint32 terminal height, rows \(e.g., 24\)) s -5 184 M -( uint32 terminal width, pixels \(e.g., 640\)) s -5 173 M -( uint32 terminal height, pixels \(e.g., 480\)) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]) s -_R -S -PStoPSsaved restore -%%Page: (8,9) 5 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 9 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( string encoded terminal modes) s -5 668 M -( The encoding of terminal modes is described in Section Encoding of) s -5 657 M -( Terminal Modes \(Section 8\). Zero dimension parameters MUST be) s -5 646 M -( ignored. The character/row dimensions override the pixel dimensions) s -5 635 M -( \(when nonzero\). Pixel dimensions refer to the drawable area of the) s -5 624 M -( window.) s -5 602 M -( The dimension parameters are only informational.) s -5 580 M -( The client SHOULD ignore pty requests.) s -5 558 M -(6.3 X11 Forwarding) s -5 536 M -(6.3.1 Requesting X11 Forwarding) s -5 514 M -( X11 forwarding may be requested for a session by sending) s -5 492 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 481 M -( uint32 recipient channel) s -5 470 M -( string "x11-req") s -5 459 M -( boolean want reply) s -5 448 M -( boolean single connection) s -5 437 M -( string x11 authentication protocol) s -5 426 M -( string x11 authentication cookie) s -5 415 M -( uint32 x11 screen number) s -5 393 M -( It is recommended that the authentication cookie that is sent be a) s -5 382 M -( fake, random cookie, and that the cookie is checked and replaced by) s -5 371 M -( the real cookie when a connection request is received.) s -5 349 M -( X11 connection forwarding should stop when the session channel is) s -5 338 M -( closed; however, already opened forwardings should not be) s -5 327 M -( automatically closed when the session channel is closed.) s -5 305 M -( If `single connection' is TRUE, only a single connection should be) s -5 294 M -( forwarded. No more connections will be forwarded after the first, or) s -5 283 M -( after the session channel has been closed.) s -5 261 M -( The "x11 authentication protocol" is the name of the X11) s -5 250 M -( authentication method used, e.g. "MIT-MAGIC-COOKIE-1".) s -5 228 M -( The x11 authentication cookie MUST be hexadecimal encoded.) s -5 206 M -( X Protocol is documented in [SCHEIFLER].) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 10 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -(6.3.2 X11 Channels) s -5 668 M -( X11 channels are opened with a channel open request. The resulting) s -5 657 M -( channels are independent of the session, and closing the session) s -5 646 M -( channel does not close the forwarded X11 channels.) s -5 624 M -( byte SSH_MSG_CHANNEL_OPEN) s -5 613 M -( string "x11") s -5 602 M -( uint32 sender channel) s -5 591 M -( uint32 initial window size) s -5 580 M -( uint32 maximum packet size) s -5 569 M -( string originator address \(e.g. "192.168.7.38"\)) s -5 558 M -( uint32 originator port) s -5 536 M -( The recipient should respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION) s -5 525 M -( or SSH_MSG_CHANNEL_OPEN_FAILURE.) s -5 503 M -( Implementations MUST reject any X11 channel open requests if they) s -5 492 M -( have not requested X11 forwarding.) s -5 470 M -(6.4 Environment Variable Passing) s -5 448 M -( Environment variables may be passed to the shell/command to be) s -5 437 M -( started later. Uncontrolled setting of environment variables in a) s -5 426 M -( privileged process can be a security hazard. It is recommended that) s -5 415 M -( implementations either maintain a list of allowable variable names or) s -5 404 M -( only set environment variables after the server process has dropped) s -5 393 M -( sufficient privileges.) s -5 371 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 360 M -( uint32 recipient channel) s -5 349 M -( string "env") s -5 338 M -( boolean want reply) s -5 327 M -( string variable name) s -5 316 M -( string variable value) s -5 283 M -(6.5 Starting a Shell or a Command) s -5 261 M -( Once the session has been set up, a program is started at the remote) s -5 250 M -( end. The program can be a shell, an application program or a) s -5 239 M -( subsystem with a host-independent name. Only one of these requests) s -5 228 M -( can succeed per channel.) s -5 206 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 195 M -( uint32 recipient channel) s -5 184 M -( string "shell") s -5 173 M -( boolean want reply) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]) s -_R -S -PStoPSsaved restore -%%Page: (10,11) 6 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 11 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( This message will request the user's default shell \(typically defined) s -5 679 M -( in /etc/passwd in UNIX systems\) to be started at the other end.) s -5 657 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 646 M -( uint32 recipient channel) s -5 635 M -( string "exec") s -5 624 M -( boolean want reply) s -5 613 M -( string command) s -5 591 M -( This message will request the server to start the execution of the) s -5 580 M -( given command. The command string may contain a path. Normal) s -5 569 M -( precautions MUST be taken to prevent the execution of unauthorized) s -5 558 M -( commands.) s -5 536 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 525 M -( uint32 recipient channel) s -5 514 M -( string "subsystem") s -5 503 M -( boolean want reply) s -5 492 M -( string subsystem name) s -5 470 M -( This last form executes a predefined subsystem. It is expected that) s -5 459 M -( these will include a general file transfer mechanism, and possibly) s -5 448 M -( other features. Implementations may also allow configuring more such) s -5 437 M -( mechanisms. As the user's shell is usually used to execute the) s -5 426 M -( subsystem, it is advisable for the subsystem protocol to have a) s -5 415 M -( "magic cookie" at the beginning of the protocol transaction to) s -5 404 M -( distinguish it from arbitrary output generated by shell) s -5 393 M -( initialization scripts etc. This spurious output from the shell may) s -5 382 M -( be filtered out either at the server or at the client.) s -5 360 M -( The server SHOULD not halt the execution of the protocol stack when) s -5 349 M -( starting a shell or a program. All input and output from these SHOULD) s -5 338 M -( be redirected to the channel or to the encrypted tunnel.) s -5 316 M -( It is RECOMMENDED to request and check the reply for these messages.) s -5 305 M -( The client SHOULD ignore these messages.) s -5 283 M -( Subsystem names follow the DNS extensibility naming convention) s -5 272 M -( outlined in [SSH-ARCH].) s -5 250 M -(6.6 Session Data Transfer) s -5 228 M -( Data transfer for a session is done using SSH_MSG_CHANNEL_DATA and) s -5 217 M -( SSH_MSG_CHANNEL_EXTENDED_DATA packets and the window mechanism. The) s -5 206 M -( extended data type SSH_EXTENDED_DATA_STDERR has been defined for) s -5 195 M -( stderr data.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 12 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -(6.7 Window Dimension Change Message) s -5 668 M -( When the window \(terminal\) size changes on the client side, it MAY) s -5 657 M -( send a message to the other side to inform it of the new dimensions.) s -5 635 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 624 M -( uint32 recipient_channel) s -5 613 M -( string "window-change") s -5 602 M -( boolean FALSE) s -5 591 M -( uint32 terminal width, columns) s -5 580 M -( uint32 terminal height, rows) s -5 569 M -( uint32 terminal width, pixels) s -5 558 M -( uint32 terminal height, pixels) s -5 536 M -( No response SHOULD be sent to this message.) s -5 514 M -(6.8 Local Flow Control) s -5 492 M -( On many systems, it is possible to determine if a pseudo-terminal is) s -5 481 M -( using control-S/control-Q flow control. When flow control is) s -5 470 M -( allowed, it is often desirable to do the flow control at the client) s -5 459 M -( end to speed up responses to user requests. This is facilitated by) s -5 448 M -( the following notification. Initially, the server is responsible for) s -5 437 M -( flow control. \(Here, again, client means the side originating the) s -5 426 M -( session, and server means the other side.\)) s -5 404 M -( The message below is used by the server to inform the client when it) s -5 393 M -( can or cannot perform flow control \(control-S/control-Q processing\).) s -5 382 M -( If `client can do' is TRUE, the client is allowed to do flow control) s -5 371 M -( using control-S and control-Q. The client MAY ignore this message.) s -5 349 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 338 M -( uint32 recipient channel) s -5 327 M -( string "xon-xoff") s -5 316 M -( boolean FALSE) s -5 305 M -( boolean client can do) s -5 283 M -( No response is sent to this message.) s -5 261 M -(6.9 Signals) s -5 239 M -( A signal can be delivered to the remote process/service using the) s -5 228 M -( following message. Some systems may not implement signals, in which) s -5 217 M -( case they SHOULD ignore this message.) s -5 195 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 184 M -( uint32 recipient channel) s -5 173 M -( string "signal") s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]) s -_R -S -PStoPSsaved restore -%%Page: (12,13) 7 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 13 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( boolean FALSE) s -5 679 M -( string signal name without the "SIG" prefix.) s -5 657 M -( Signal names will be encoded as discussed in the "exit-signal") s -5 646 M -( SSH_MSG_CHANNEL_REQUEST.) s -5 624 M -(6.10 Returning Exit Status) s -5 602 M -( When the command running at the other end terminates, the following) s -5 591 M -( message can be sent to return the exit status of the command.) s -5 580 M -( Returning the status is RECOMMENDED. No acknowledgment is sent for) s -5 569 M -( this message. The channel needs to be closed with) s -5 558 M -( SSH_MSG_CHANNEL_CLOSE after this message.) s -5 536 M -( The client MAY ignore these messages.) s -5 514 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 503 M -( uint32 recipient_channel) s -5 492 M -( string "exit-status") s -5 481 M -( boolean FALSE) s -5 470 M -( uint32 exit_status) s -5 448 M -( The remote command may also terminate violently due to a signal.) s -5 437 M -( Such a condition can be indicated by the following message. A zero) s -5 426 M -( exit_status usually means that the command terminated successfully.) s -5 404 M -( byte SSH_MSG_CHANNEL_REQUEST) s -5 393 M -( uint32 recipient channel) s -5 382 M -( string "exit-signal") s -5 371 M -( boolean FALSE) s -5 360 M -( string signal name without the "SIG" prefix.) s -5 349 M -( boolean core dumped) s -5 338 M -( string error message \(ISO-10646 UTF-8\)) s -5 327 M -( string language tag \(as defined in [RFC3066]\)) s -5 305 M -( The signal name is one of the following \(these are from [POSIX]\)) s -5 283 M -( ABRT) s -5 272 M -( ALRM) s -5 261 M -( FPE) s -5 250 M -( HUP) s -5 239 M -( ILL) s -5 228 M -( INT) s -5 217 M -( KILL) s -5 206 M -( PIPE) s -5 195 M -( QUIT) s -5 184 M -( SEGV) s -5 173 M -( TERM) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 14 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( USR1) s -5 679 M -( USR2) s -5 657 M -( Additional signal names MAY be sent in the format "sig-name@xyz",) s -5 646 M -( where `sig-name' and `xyz' may be anything a particular implementor) s -5 635 M -( wants \(except the `@' sign\). However, it is suggested that if a) s -5 624 M -( `configure' script is used, the non-standard signal names it finds be) s -5 613 M -( encoded as "SIG@xyz.config.guess", where `SIG' is the signal name) s -5 602 M -( without the "SIG" prefix, and `xyz' be the host type, as determined) s -5 591 M -( by `config.guess'.) s -5 569 M -( The `error message' contains an additional explanation of the error) s -5 558 M -( message. The message may consist of multiple lines. The client) s -5 547 M -( software MAY display this message to the user. If this is done, the) s -5 536 M -( client software should take the precautions discussed in [SSH-ARCH].) s -5 514 M -(7. TCP/IP Port Forwarding) s -5 492 M -(7.1 Requesting Port Forwarding) s -5 470 M -( A party need not explicitly request forwardings from its own end to) s -5 459 M -( the other direction. However, if it wishes that connections to a) s -5 448 M -( port on the other side be forwarded to the local side, it must) s -5 437 M -( explicitly request this.) s -5 404 M -( byte SSH_MSG_GLOBAL_REQUEST) s -5 393 M -( string "tcpip-forward") s -5 382 M -( boolean want reply) s -5 371 M -( string address to bind \(e.g. "0.0.0.0"\)) s -5 360 M -( uint32 port number to bind) s -5 338 M -( `Address to bind' and `port number to bind' specify the IP address) s -5 327 M -( and port to which the socket to be listened is bound. The address) s -5 316 M -( should be "0.0.0.0" if connections are allowed from anywhere. \(Note) s -5 305 M -( that the client can still filter connections based on information) s -5 294 M -( passed in the open request.\)) s -5 272 M -( Implementations should only allow forwarding privileged ports if the) s -5 261 M -( user has been authenticated as a privileged user.) s -5 239 M -( Client implementations SHOULD reject these messages; they are) s -5 228 M -( normally only sent by the client.) s -5 195 M -( If a client passes 0 as port number to bind and has want reply TRUE) s -5 184 M -( then the server allocates the next available unprivileged port number) s -5 173 M -( and replies with the following message, otherwise there is no) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]) s -_R -S -PStoPSsaved restore -%%Page: (14,15) 8 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 15 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( response specific data.) s -5 657 M -( byte SSH_MSG_GLOBAL_REQUEST_SUCCESS) s -5 646 M -( uint32 port that was bound on the server) s -5 624 M -( A port forwarding can be cancelled with the following message. Note) s -5 613 M -( that channel open requests may be received until a reply to this) s -5 602 M -( message is received.) s -5 580 M -( byte SSH_MSG_GLOBAL_REQUEST) s -5 569 M -( string "cancel-tcpip-forward") s -5 558 M -( boolean want reply) s -5 547 M -( string address_to_bind \(e.g. "127.0.0.1"\)) s -5 536 M -( uint32 port number to bind) s -5 514 M -( Client implementations SHOULD reject these messages; they are) s -5 503 M -( normally only sent by the client.) s -5 481 M -(7.2 TCP/IP Forwarding Channels) s -5 459 M -( When a connection comes to a port for which remote forwarding has) s -5 448 M -( been requested, a channel is opened to forward the port to the other) s -5 437 M -( side.) s -5 415 M -( byte SSH_MSG_CHANNEL_OPEN) s -5 404 M -( string "forwarded-tcpip") s -5 393 M -( uint32 sender channel) s -5 382 M -( uint32 initial window size) s -5 371 M -( uint32 maximum packet size) s -5 360 M -( string address that was connected) s -5 349 M -( uint32 port that was connected) s -5 338 M -( string originator IP address) s -5 327 M -( uint32 originator port) s -5 305 M -( Implementations MUST reject these messages unless they have) s -5 294 M -( previously requested a remote TCP/IP port forwarding with the given) s -5 283 M -( port number.) s -5 261 M -( When a connection comes to a locally forwarded TCP/IP port, the) s -5 250 M -( following packet is sent to the other side. Note that these messages) s -5 239 M -( MAY be sent also for ports for which no forwarding has been) s -5 228 M -( explicitly requested. The receiving side must decide whether to) s -5 217 M -( allow the forwarding.) s -5 195 M -( byte SSH_MSG_CHANNEL_OPEN) s -5 184 M -( string "direct-tcpip") s -5 173 M -( uint32 sender channel) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 16 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( uint32 initial window size) s -5 679 M -( uint32 maximum packet size) s -5 668 M -( string host to connect) s -5 657 M -( uint32 port to connect) s -5 646 M -( string originator IP address) s -5 635 M -( uint32 originator port) s -5 613 M -( `Host to connect' and `port to connect' specify the TCP/IP host and) s -5 602 M -( port where the recipient should connect the channel. `Host to) s -5 591 M -( connect' may be either a domain name or a numeric IP address.) s -5 569 M -( `Originator IP address' is the numeric IP address of the machine) s -5 558 M -( where the connection request comes from, and `originator port' is the) s -5 547 M -( port on the originator host from where the connection came from.) s -5 525 M -( Forwarded TCP/IP channels are independent of any sessions, and) s -5 514 M -( closing a session channel does not in any way imply that forwarded) s -5 503 M -( connections should be closed.) s -5 481 M -( Client implementations SHOULD reject direct TCP/IP open requests for) s -5 470 M -( security reasons.) s -5 448 M -(8. Encoding of Terminal Modes) s -5 426 M -( Terminal modes \(as passed in a pty request\) are encoded into a byte) s -5 415 M -( stream. It is intended that the coding be portable across different) s -5 404 M -( environments.) s -5 382 M -( The tty mode description is a stream of bytes. The stream consists) s -5 371 M -( of opcode-argument pairs. It is terminated by opcode TTY_OP_END \(0\).) s -5 360 M -( Opcodes 1 to 159 have a single uint32 argument. Opcodes 160 to 255) s -5 349 M -( are not yet defined, and cause parsing to stop \(they should only be) s -5 338 M -( used after any other data\).) s -5 316 M -( The client SHOULD put in the stream any modes it knows about, and the) s -5 305 M -( server MAY ignore any modes it does not know about. This allows some) s -5 294 M -( degree of machine-independence, at least between systems that use a) s -5 283 M -( POSIX-like tty interface. The protocol can support other systems as) s -5 272 M -( well, but the client may need to fill reasonable values for a number) s -5 261 M -( of parameters so the server pty gets set to a reasonable mode \(the) s -5 250 M -( server leaves all unspecified mode bits in their default values, and) s -5 239 M -( only some combinations make sense\).) s -5 217 M -( The following opcodes have been defined. The naming of opcodes) s -5 206 M -( mostly follows the POSIX terminal mode flags.) s -5 184 M -( 0 TTY_OP_END Indicates end of options.) s -5 173 M -( 1 VINTR Interrupt character; 255 if none. Similarly for the) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]) s -_R -S -PStoPSsaved restore -%%Page: (16,17) 9 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 17 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( other characters. Not all of these characters are) s -5 679 M -( supported on all systems.) s -5 668 M -( 2 VQUIT The quit character \(sends SIGQUIT signal on POSIX) s -5 657 M -( systems\).) s -5 646 M -( 3 VERASE Erase the character to left of the cursor.) s -5 635 M -( 4 VKILL Kill the current input line.) s -5 624 M -( 5 VEOF End-of-file character \(sends EOF from the terminal\).) s -5 613 M -( 6 VEOL End-of-line character in addition to carriage return) s -5 602 M -( and/or linefeed.) s -5 591 M -( 7 VEOL2 Additional end-of-line character.) s -5 580 M -( 8 VSTART Continues paused output \(normally control-Q\).) s -5 569 M -( 9 VSTOP Pauses output \(normally control-S\).) s -5 558 M -( 10 VSUSP Suspends the current program.) s -5 547 M -( 11 VDSUSP Another suspend character.) s -5 536 M -( 12 VREPRINT Reprints the current input line.) s -5 525 M -( 13 VWERASE Erases a word left of cursor.) s -5 514 M -( 14 VLNEXT Enter the next character typed literally, even if it) s -5 503 M -( is a special character) s -5 492 M -( 15 VFLUSH Character to flush output.) s -5 481 M -( 16 VSWTCH Switch to a different shell layer.) s -5 470 M -( 17 VSTATUS Prints system status line \(load, command, pid etc\).) s -5 459 M -( 18 VDISCARD Toggles the flushing of terminal output.) s -5 448 M -( 30 IGNPAR The ignore parity flag. The parameter SHOULD be 0 if) s -5 437 M -( this flag is FALSE set, and 1 if it is TRUE.) s -5 426 M -( 31 PARMRK Mark parity and framing errors.) s -5 415 M -( 32 INPCK Enable checking of parity errors.) s -5 404 M -( 33 ISTRIP Strip 8th bit off characters.) s -5 393 M -( 34 INLCR Map NL into CR on input.) s -5 382 M -( 35 IGNCR Ignore CR on input.) s -5 371 M -( 36 ICRNL Map CR to NL on input.) s -5 360 M -( 37 IUCLC Translate uppercase characters to lowercase.) s -5 349 M -( 38 IXON Enable output flow control.) s -5 338 M -( 39 IXANY Any char will restart after stop.) s -5 327 M -( 40 IXOFF Enable input flow control.) s -5 316 M -( 41 IMAXBEL Ring bell on input queue full.) s -5 305 M -( 50 ISIG Enable signals INTR, QUIT, [D]SUSP.) s -5 294 M -( 51 ICANON Canonicalize input lines.) s -5 283 M -( 52 XCASE Enable input and output of uppercase characters by) s -5 272 M -( preceding their lowercase equivalents with `\\'.) s -5 261 M -( 53 ECHO Enable echoing.) s -5 250 M -( 54 ECHOE Visually erase chars.) s -5 239 M -( 55 ECHOK Kill character discards current line.) s -5 228 M -( 56 ECHONL Echo NL even if ECHO is off.) s -5 217 M -( 57 NOFLSH Don't flush after interrupt.) s -5 206 M -( 58 TOSTOP Stop background jobs from output.) s -5 195 M -( 59 IEXTEN Enable extensions.) s -5 184 M -( 60 ECHOCTL Echo control characters as ^\(Char\).) s -5 173 M -( 61 ECHOKE Visual erase for line kill.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 18 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( 62 PENDIN Retype pending input.) s -5 679 M -( 70 OPOST Enable output processing.) s -5 668 M -( 71 OLCUC Convert lowercase to uppercase.) s -5 657 M -( 72 ONLCR Map NL to CR-NL.) s -5 646 M -( 73 OCRNL Translate carriage return to newline \(output\).) s -5 635 M -( 74 ONOCR Translate newline to carriage return-newline) s -5 624 M -( \(output\).) s -5 613 M -( 75 ONLRET Newline performs a carriage return \(output\).) s -5 602 M -( 90 CS7 7 bit mode.) s -5 591 M -( 91 CS8 8 bit mode.) s -5 580 M -( 92 PARENB Parity enable.) s -5 569 M -( 93 PARODD Odd parity, else even.) s -5 547 M -( 128 TTY_OP_ISPEED Specifies the input baud rate in bits per second.) s -5 536 M -( 129 TTY_OP_OSPEED Specifies the output baud rate in bits per second.) s -5 503 M -(9. Summary of Message Numbers) s -5 481 M -( #define SSH_MSG_GLOBAL_REQUEST 80) s -5 470 M -( #define SSH_MSG_REQUEST_SUCCESS 81) s -5 459 M -( #define SSH_MSG_REQUEST_FAILURE 82) s -5 448 M -( #define SSH_MSG_CHANNEL_OPEN 90) s -5 437 M -( #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91) s -5 426 M -( #define SSH_MSG_CHANNEL_OPEN_FAILURE 92) s -5 415 M -( #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93) s -5 404 M -( #define SSH_MSG_CHANNEL_DATA 94) s -5 393 M -( #define SSH_MSG_CHANNEL_EXTENDED_DATA 95) s -5 382 M -( #define SSH_MSG_CHANNEL_EOF 96) s -5 371 M -( #define SSH_MSG_CHANNEL_CLOSE 97) s -5 360 M -( #define SSH_MSG_CHANNEL_REQUEST 98) s -5 349 M -( #define SSH_MSG_CHANNEL_SUCCESS 99) s -5 338 M -( #define SSH_MSG_CHANNEL_FAILURE 100) s -5 305 M -(10. Security Considerations) s -5 283 M -( This protocol is assumed to run on top of a secure, authenticated) s -5 272 M -( transport. User authentication and protection against network-level) s -5 261 M -( attacks are assumed to be provided by the underlying protocols.) s -5 239 M -( It is RECOMMENDED that implementations disable all the potentially) s -5 228 M -( dangerous features \(e.g. agent forwarding, X11 forwarding, and TCP/IP) s -5 217 M -( forwarding\) if the host key has changed.) s -5 195 M -( Full security considerations for this protocol are provided in) s -5 184 M -( Section 8 of [SSH-ARCH]) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]) s -_R -S -PStoPSsaved restore -%%Page: (18,19) 10 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 19 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -(11. iana cONSiderations) s -5 668 M -( This document is part of a set, the IANA considerations for the SSH) s -5 657 M -( protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],) s -5 646 M -( [SSH-CONNECT] are detailed in [SSH-NUMBERS].) s -5 624 M -(12. Intellectual Property) s -5 602 M -( The IETF takes no position regarding the validity or scope of any) s -5 591 M -( intellectual property or other rights that might be claimed to) s -5 580 M -( pertain to the implementation or use of the technology described in) s -5 569 M -( this document or the extent to which any license under such rights) s -5 558 M -( might or might not be available; neither does it represent that it) s -5 547 M -( has made any effort to identify any such rights. Information on the) s -5 536 M -( IETF's procedures with respect to rights in standards-track and) s -5 525 M -( standards-related documentation can be found in BCP-11. Copies of) s -5 514 M -( claims of rights made available for publication and any assurances of) s -5 503 M -( licenses to be made available, or the result of an attempt made to) s -5 492 M -( obtain a general license or permission for the use of such) s -5 481 M -( proprietary rights by implementers or users of this specification can) s -5 470 M -( be obtained from the IETF Secretariat.) s -5 448 M -( The IETF has been notified of intellectual property rights claimed in) s -5 437 M -( regard to some or all of the specification contained in this) s -5 426 M -( document. For more information consult the online list of claimed) s -5 415 M -( rights.) s -5 393 M -(Normative References) s -5 371 M -( [SSH-ARCH]) s -5 360 M -( Ylonen, T., "SSH Protocol Architecture", I-D) s -5 349 M -( draft-ietf-architecture-15.txt, Oct 2003.) s -5 327 M -( [SSH-TRANS]) s -5 316 M -( Ylonen, T., "SSH Transport Layer Protocol", I-D) s -5 305 M -( draft-ietf-transport-17.txt, Oct 2003.) s -5 283 M -( [SSH-USERAUTH]) s -5 272 M -( Ylonen, T., "SSH Authentication Protocol", I-D) s -5 261 M -( draft-ietf-userauth-18.txt, Oct 2003.) s -5 239 M -( [SSH-CONNECT]) s -5 228 M -( Ylonen, T., "SSH Connection Protocol", I-D) s -5 217 M -( draft-ietf-connect-18.txt, Oct 2003.) s -5 195 M -( [SSH-NUMBERS]) s -5 184 M -( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s -5 173 M -( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 20 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( 2003.) s -5 668 M -( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s -5 657 M -( Requirement Levels", BCP 14, RFC 2119, March 1997.) s -5 635 M -(Informative References) s -5 613 M -( [RFC3066] Alvestrand, H., "Tags for the Identification of) s -5 602 M -( Languages", BCP 47, RFC 3066, January 2001.) s -5 580 M -( [RFC1884] Hinden, R. and S. Deering, "IP Version 6 Addressing) s -5 569 M -( Architecture", RFC 1884, December 1995.) s -5 547 M -( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s -5 536 M -( 10646", RFC 2279, January 1998.) s -5 514 M -( [SCHEIFLER]) s -5 503 M -( Scheifler, R., "X Window System : The Complete Reference) s -5 492 M -( to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital) s -5 481 M -( Press ISBN 1555580882, Feburary 1992.) s -5 459 M -( [POSIX] ISO/IEC, 9945-1., "Information technology -- Portable) s -5 448 M -( Operating System Interface \(POSIX\)-Part 1: System) s -5 437 M -( Application Program Interface \(API\) C Language", ANSI/IEE) s -5 426 M -( Std 1003.1, July 1996.) s -5 393 M -(Authors' Addresses) s -5 371 M -( Tatu Ylonen) s -5 360 M -( SSH Communications Security Corp) s -5 349 M -( Fredrikinkatu 42) s -5 338 M -( HELSINKI FIN-00100) s -5 327 M -( Finland) s -5 305 M -( EMail: ylo@ssh.com) s -5 272 M -( Darren J. Moffat \(editor\)) s -5 261 M -( Sun Microsystems, Inc) s -5 250 M -( 17 Network Circle) s -5 239 M -( Menlo Park CA 94025) s -5 228 M -( USA) s -5 206 M -( EMail: Darren.Moffat@Sun.COM) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]) s -_R -S -PStoPSsaved restore -%%Page: (20,21) 11 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 21 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -(Intellectual Property Statement) s -5 668 M -( The IETF takes no position regarding the validity or scope of any) s -5 657 M -( intellectual property or other rights that might be claimed to) s -5 646 M -( pertain to the implementation or use of the technology described in) s -5 635 M -( this document or the extent to which any license under such rights) s -5 624 M -( might or might not be available; neither does it represent that it) s -5 613 M -( has made any effort to identify any such rights. Information on the) s -5 602 M -( IETF's procedures with respect to rights in standards-track and) s -5 591 M -( standards-related documentation can be found in BCP-11. Copies of) s -5 580 M -( claims of rights made available for publication and any assurances of) s -5 569 M -( licenses to be made available, or the result of an attempt made to) s -5 558 M -( obtain a general license or permission for the use of such) s -5 547 M -( proprietary rights by implementors or users of this specification can) s -5 536 M -( be obtained from the IETF Secretariat.) s -5 514 M -( The IETF invites any interested party to bring to its attention any) s -5 503 M -( copyrights, patents or patent applications, or other proprietary) s -5 492 M -( rights which may cover technology that may be required to practice) s -5 481 M -( this standard. Please address the information to the IETF Executive) s -5 470 M -( Director.) s -5 448 M -( The IETF has been notified of intellectual property rights claimed in) s -5 437 M -( regard to some or all of the specification contained in this) s -5 426 M -( document. For more information consult the online list of claimed) s -5 415 M -( rights.) s -5 382 M -(Full Copyright Statement) s -5 360 M -( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s -5 338 M -( This document and translations of it may be copied and furnished to) s -5 327 M -( others, and derivative works that comment on or otherwise explain it) s -5 316 M -( or assist in its implementation may be prepared, copied, published) s -5 305 M -( and distributed, in whole or in part, without restriction of any) s -5 294 M -( kind, provided that the above copyright notice and this paragraph are) s -5 283 M -( included on all such copies and derivative works. However, this) s -5 272 M -( document itself may not be modified in any way, such as by removing) s -5 261 M -( the copyright notice or references to the Internet Society or other) s -5 250 M -( Internet organizations, except as needed for the purpose of) s -5 239 M -( developing Internet standards in which case the procedures for) s -5 228 M -( copyrights defined in the Internet Standards process must be) s -5 217 M -( followed, or as required to translate it into languages other than) s -5 206 M -( English.) s -5 184 M -( The limited permissions granted above are perpetual and will not be) s -5 173 M -( revoked by the Internet Society or its successors or assignees.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 22 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Connection Protocol Oct 2003) s -5 690 M -( This document and the information contained herein is provided on an) s -5 679 M -( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s -5 668 M -( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s -5 657 M -( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s -5 646 M -( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s -5 635 M -( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s -5 602 M -(Acknowledgment) s -5 580 M -( Funding for the RFC Editor function is currently provided by the) s -5 569 M -( Internet Society.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]) s -_R -S -PStoPSsaved restore -%%Trailer -%%Pages: 22 -%%DocumentNeededResources: font Courier-Bold Courier -%%EOF diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt deleted file mode 100644 index 1cb8ad6409..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt +++ /dev/null @@ -1,1232 +0,0 @@ - - - -Network Working Group T. Ylonen -Internet-Draft SSH Communications Security Corp -Expires: March 31, 2004 D. Moffat, Editor, Ed. - Sun Microsystems, Inc - Oct 2003 - - - SSH Connection Protocol - draft-ietf-secsh-connect-18.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on March 31, 2004. - -Copyright Notice - - Copyright (C) The Internet Society (2003). All Rights Reserved. - -Abstract - - SSH is a protocol for secure remote login and other secure network - services over an insecure network. - - This document describes the SSH Connection Protocol. It provides - interactive login sessions, remote execution of commands, forwarded - TCP/IP connections, and forwarded X11 connections. All of these - channels are multiplexed into a single encrypted tunnel. - - The SSH Connection Protocol has been designed to run on top of the - SSH transport layer and user authentication protocols. - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1] - -Internet-Draft SSH Connection Protocol Oct 2003 - - -Table of Contents - - 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 - 3. Conventions Used in This Document . . . . . . . . . . . . . 3 - 4. Global Requests . . . . . . . . . . . . . . . . . . . . . . 3 - 5. Channel Mechanism . . . . . . . . . . . . . . . . . . . . . 4 - 5.1 Opening a Channel . . . . . . . . . . . . . . . . . . . . . 4 - 5.2 Data Transfer . . . . . . . . . . . . . . . . . . . . . . . 5 - 5.3 Closing a Channel . . . . . . . . . . . . . . . . . . . . . 6 - 5.4 Channel-Specific Requests . . . . . . . . . . . . . . . . . 7 - 6. Interactive Sessions . . . . . . . . . . . . . . . . . . . . 8 - 6.1 Opening a Session . . . . . . . . . . . . . . . . . . . . . 8 - 6.2 Requesting a Pseudo-Terminal . . . . . . . . . . . . . . . . 8 - 6.3 X11 Forwarding . . . . . . . . . . . . . . . . . . . . . . . 9 - 6.3.1 Requesting X11 Forwarding . . . . . . . . . . . . . . . . . 9 - 6.3.2 X11 Channels . . . . . . . . . . . . . . . . . . . . . . . . 10 - 6.4 Environment Variable Passing . . . . . . . . . . . . . . . . 10 - 6.5 Starting a Shell or a Command . . . . . . . . . . . . . . . 10 - 6.6 Session Data Transfer . . . . . . . . . . . . . . . . . . . 11 - 6.7 Window Dimension Change Message . . . . . . . . . . . . . . 12 - 6.8 Local Flow Control . . . . . . . . . . . . . . . . . . . . . 12 - 6.9 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 12 - 6.10 Returning Exit Status . . . . . . . . . . . . . . . . . . . 13 - 7. TCP/IP Port Forwarding . . . . . . . . . . . . . . . . . . . 14 - 7.1 Requesting Port Forwarding . . . . . . . . . . . . . . . . . 14 - 7.2 TCP/IP Forwarding Channels . . . . . . . . . . . . . . . . . 15 - 8. Encoding of Terminal Modes . . . . . . . . . . . . . . . . . 16 - 9. Summary of Message Numbers . . . . . . . . . . . . . . . . . 18 - 10. Security Considerations . . . . . . . . . . . . . . . . . . 18 - 11. iana cONSiderations . . . . . . . . . . . . . . . . . . . . 19 - 12. Intellectual Property . . . . . . . . . . . . . . . . . . . 19 - Normative References . . . . . . . . . . . . . . . . . . . . 19 - Informative References . . . . . . . . . . . . . . . . . . . 20 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 20 - Intellectual Property and Copyright Statements . . . . . . . 21 - - - - - - - - - - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2] - -Internet-Draft SSH Connection Protocol Oct 2003 - - -1. Contributors - - The major original contributors of this document were: Tatu Ylonen, - Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications - Security Corp), and Markku-Juhani O. Saarinen (University of - Jyvaskyla) - - The document editor is: Darren.Moffat@Sun.COM. Comments on this - internet draft should be sent to the IETF SECSH working group, - details at: http://ietf.org/html.charters/secsh-charter.html - -2. Introduction - - The SSH Connection Protocol has been designed to run on top of the - SSH transport layer and user authentication protocols. It provides - interactive login sessions, remote execution of commands, forwarded - TCP/IP connections, and forwarded X11 connections. The service name - for this protocol is "ssh-connection". - - This document should be read only after reading the SSH architecture - document [SSH-ARCH]. This document freely uses terminology and - notation from the architecture document without reference or further - explanation. - -3. Conventions Used in This Document - - The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", - and "MAY" that appear in this document are to be interpreted as - described in [RFC2119]. - - The used data types and terminology are specified in the architecture - document [SSH-ARCH]. - - The architecture document also discusses the algorithm naming - conventions that MUST be used with the SSH protocols. - -4. Global Requests - - There are several kinds of requests that affect the state of the - remote end "globally", independent of any channels. An example is a - request to start TCP/IP forwarding for a specific port. All such - requests use the following format. - - byte SSH_MSG_GLOBAL_REQUEST - string request name (restricted to US-ASCII) - boolean want reply - ... request-specific data follows - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - Request names follow the DNS extensibility naming convention outlined - in [SSH-ARCH]. - - The recipient will respond to this message with - SSH_MSG_REQUEST_SUCCESS or SSH_MSG_REQUEST_FAILURE if `want reply' is - TRUE. - - byte SSH_MSG_REQUEST_SUCCESS - ..... response specific data - - Usually the response specific data is non-existent. - - If the recipient does not recognize or support the request, it simply - responds with SSH_MSG_REQUEST_FAILURE. - - byte SSH_MSG_REQUEST_FAILURE - - -5. Channel Mechanism - - All terminal sessions, forwarded connections, etc. are channels. - Either side may open a channel. Multiple channels are multiplexed - into a single connection. - - Channels are identified by numbers at each end. The number referring - to a channel may be different on each side. Requests to open a - channel contain the sender's channel number. Any other - channel-related messages contain the recipient's channel number for - the channel. - - Channels are flow-controlled. No data may be sent to a channel until - a message is received to indicate that window space is available. - -5.1 Opening a Channel - - When either side wishes to open a new channel, it allocates a local - number for the channel. It then sends the following message to the - other side, and includes the local channel number and initial window - size in the message. - - byte SSH_MSG_CHANNEL_OPEN - string channel type (restricted to US-ASCII) - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - ... channel type specific data follows - - The channel type is a name as described in the SSH architecture - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - document, with similar extension mechanisms. `sender channel' is a - local identifier for the channel used by the sender of this message. - `initial window size' specifies how many bytes of channel data can be - sent to the sender of this message without adjusting the window. - `Maximum packet size' specifies the maximum size of an individual - data packet that can be sent to the sender (for example, one might - want to use smaller packets for interactive connections to get better - interactive response on slow links). - - The remote side then decides whether it can open the channel, and - responds with either - - byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION - uint32 recipient channel - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - ... channel type specific data follows - - where `recipient channel' is the channel number given in the original - open request, and `sender channel' is the channel number allocated by - the other side, or - - byte SSH_MSG_CHANNEL_OPEN_FAILURE - uint32 recipient channel - uint32 reason code - string additional textual information (ISO-10646 UTF-8 [RFC2279]) - string language tag (as defined in [RFC3066]) - - If the recipient of the SSH_MSG_CHANNEL_OPEN message does not support - the specified channel type, it simply responds with - SSH_MSG_CHANNEL_OPEN_FAILURE. The client MAY show the additional - information to the user. If this is done, the client software should - take the precautions discussed in [SSH-ARCH]. - - The following reason codes are defined: - - #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1 - #define SSH_OPEN_CONNECT_FAILED 2 - #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3 - #define SSH_OPEN_RESOURCE_SHORTAGE 4 - - -5.2 Data Transfer - - The window size specifies how many bytes the other party can send - before it must wait for the window to be adjusted. Both parties use - the following message to adjust the window. - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - byte SSH_MSG_CHANNEL_WINDOW_ADJUST - uint32 recipient channel - uint32 bytes to add - - After receiving this message, the recipient MAY send the given number - of bytes more than it was previously allowed to send; the window size - is incremented. - - Data transfer is done with messages of the following type. - - byte SSH_MSG_CHANNEL_DATA - uint32 recipient channel - string data - - The maximum amount of data allowed is the current window size. The - window size is decremented by the amount of data sent. Both parties - MAY ignore all extra data sent after the allowed window is empty. - - Additionally, some channels can transfer several types of data. An - example of this is stderr data from interactive sessions. Such data - can be passed with SSH_MSG_CHANNEL_EXTENDED_DATA messages, where a - separate integer specifies the type of the data. The available types - and their interpretation depend on the type of the channel. - - byte SSH_MSG_CHANNEL_EXTENDED_DATA - uint32 recipient_channel - uint32 data_type_code - string data - - Data sent with these messages consumes the same window as ordinary - data. - - Currently, only the following type is defined. - - #define SSH_EXTENDED_DATA_STDERR 1 - - -5.3 Closing a Channel - - When a party will no longer send more data to a channel, it SHOULD - send SSH_MSG_CHANNEL_EOF. - - byte SSH_MSG_CHANNEL_EOF - uint32 recipient_channel - - No explicit response is sent to this message; however, the - application may send EOF to whatever is at the other end of the - channel. Note that the channel remains open after this message, and - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - more data may still be sent in the other direction. This message - does not consume window space and can be sent even if no window space - is available. - - When either party wishes to terminate the channel, it sends - SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST - send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this - message for the channel. The channel is considered closed for a - party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and - the party may then reuse the channel number. A party MAY send - SSH_MSG_CHANNEL_CLOSE without having sent or received - SSH_MSG_CHANNEL_EOF. - - byte SSH_MSG_CHANNEL_CLOSE - uint32 recipient_channel - - This message does not consume window space and can be sent even if no - window space is available. - - It is recommended that any data sent before this message is delivered - to the actual destination, if possible. - -5.4 Channel-Specific Requests - - Many channel types have extensions that are specific to that - particular channel type. An example is requesting a pty (pseudo - terminal) for an interactive session. - - All channel-specific requests use the following format. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string request type (restricted to US-ASCII) - boolean want reply - ... type-specific data - - If want reply is FALSE, no response will be sent to the request. - Otherwise, the recipient responds with either SSH_MSG_CHANNEL_SUCCESS - or SSH_MSG_CHANNEL_FAILURE, or request-specific continuation - messages. If the request is not recognized or is not supported for - the channel, SSH_MSG_CHANNEL_FAILURE is returned. - - This message does not consume window space and can be sent even if no - window space is available. Request types are local to each channel - type. - - The client is allowed to send further messages without waiting for - the response to the request. - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - request type names follow the DNS extensibility naming convention - outlined in [SSH-ARCH] - - byte SSH_MSG_CHANNEL_SUCCESS - uint32 recipient_channel - - - byte SSH_MSG_CHANNEL_FAILURE - uint32 recipient_channel - - These messages do not consume window space and can be sent even if no - window space is available. - -6. Interactive Sessions - - A session is a remote execution of a program. The program may be a - shell, an application, a system command, or some built-in subsystem. - It may or may not have a tty, and may or may not involve X11 - forwarding. Multiple sessions can be active simultaneously. - -6.1 Opening a Session - - A session is started by sending the following message. - - byte SSH_MSG_CHANNEL_OPEN - string "session" - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - - Client implementations SHOULD reject any session channel open - requests to make it more difficult for a corrupt server to attack the - client. - -6.2 Requesting a Pseudo-Terminal - - A pseudo-terminal can be allocated for the session by sending the - following message. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient_channel - string "pty-req" - boolean want_reply - string TERM environment variable value (e.g., vt100) - uint32 terminal width, characters (e.g., 80) - uint32 terminal height, rows (e.g., 24) - uint32 terminal width, pixels (e.g., 640) - uint32 terminal height, pixels (e.g., 480) - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - string encoded terminal modes - - The encoding of terminal modes is described in Section Encoding of - Terminal Modes (Section 8). Zero dimension parameters MUST be - ignored. The character/row dimensions override the pixel dimensions - (when nonzero). Pixel dimensions refer to the drawable area of the - window. - - The dimension parameters are only informational. - - The client SHOULD ignore pty requests. - -6.3 X11 Forwarding - -6.3.1 Requesting X11 Forwarding - - X11 forwarding may be requested for a session by sending - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "x11-req" - boolean want reply - boolean single connection - string x11 authentication protocol - string x11 authentication cookie - uint32 x11 screen number - - It is recommended that the authentication cookie that is sent be a - fake, random cookie, and that the cookie is checked and replaced by - the real cookie when a connection request is received. - - X11 connection forwarding should stop when the session channel is - closed; however, already opened forwardings should not be - automatically closed when the session channel is closed. - - If `single connection' is TRUE, only a single connection should be - forwarded. No more connections will be forwarded after the first, or - after the session channel has been closed. - - The "x11 authentication protocol" is the name of the X11 - authentication method used, e.g. "MIT-MAGIC-COOKIE-1". - - The x11 authentication cookie MUST be hexadecimal encoded. - - X Protocol is documented in [SCHEIFLER]. - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9] - -Internet-Draft SSH Connection Protocol Oct 2003 - - -6.3.2 X11 Channels - - X11 channels are opened with a channel open request. The resulting - channels are independent of the session, and closing the session - channel does not close the forwarded X11 channels. - - byte SSH_MSG_CHANNEL_OPEN - string "x11" - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - string originator address (e.g. "192.168.7.38") - uint32 originator port - - The recipient should respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION - or SSH_MSG_CHANNEL_OPEN_FAILURE. - - Implementations MUST reject any X11 channel open requests if they - have not requested X11 forwarding. - -6.4 Environment Variable Passing - - Environment variables may be passed to the shell/command to be - started later. Uncontrolled setting of environment variables in a - privileged process can be a security hazard. It is recommended that - implementations either maintain a list of allowable variable names or - only set environment variables after the server process has dropped - sufficient privileges. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "env" - boolean want reply - string variable name - string variable value - - -6.5 Starting a Shell or a Command - - Once the session has been set up, a program is started at the remote - end. The program can be a shell, an application program or a - subsystem with a host-independent name. Only one of these requests - can succeed per channel. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "shell" - boolean want reply - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - This message will request the user's default shell (typically defined - in /etc/passwd in UNIX systems) to be started at the other end. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "exec" - boolean want reply - string command - - This message will request the server to start the execution of the - given command. The command string may contain a path. Normal - precautions MUST be taken to prevent the execution of unauthorized - commands. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "subsystem" - boolean want reply - string subsystem name - - This last form executes a predefined subsystem. It is expected that - these will include a general file transfer mechanism, and possibly - other features. Implementations may also allow configuring more such - mechanisms. As the user's shell is usually used to execute the - subsystem, it is advisable for the subsystem protocol to have a - "magic cookie" at the beginning of the protocol transaction to - distinguish it from arbitrary output generated by shell - initialization scripts etc. This spurious output from the shell may - be filtered out either at the server or at the client. - - The server SHOULD not halt the execution of the protocol stack when - starting a shell or a program. All input and output from these SHOULD - be redirected to the channel or to the encrypted tunnel. - - It is RECOMMENDED to request and check the reply for these messages. - The client SHOULD ignore these messages. - - Subsystem names follow the DNS extensibility naming convention - outlined in [SSH-ARCH]. - -6.6 Session Data Transfer - - Data transfer for a session is done using SSH_MSG_CHANNEL_DATA and - SSH_MSG_CHANNEL_EXTENDED_DATA packets and the window mechanism. The - extended data type SSH_EXTENDED_DATA_STDERR has been defined for - stderr data. - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11] - -Internet-Draft SSH Connection Protocol Oct 2003 - - -6.7 Window Dimension Change Message - - When the window (terminal) size changes on the client side, it MAY - send a message to the other side to inform it of the new dimensions. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient_channel - string "window-change" - boolean FALSE - uint32 terminal width, columns - uint32 terminal height, rows - uint32 terminal width, pixels - uint32 terminal height, pixels - - No response SHOULD be sent to this message. - -6.8 Local Flow Control - - On many systems, it is possible to determine if a pseudo-terminal is - using control-S/control-Q flow control. When flow control is - allowed, it is often desirable to do the flow control at the client - end to speed up responses to user requests. This is facilitated by - the following notification. Initially, the server is responsible for - flow control. (Here, again, client means the side originating the - session, and server means the other side.) - - The message below is used by the server to inform the client when it - can or cannot perform flow control (control-S/control-Q processing). - If `client can do' is TRUE, the client is allowed to do flow control - using control-S and control-Q. The client MAY ignore this message. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "xon-xoff" - boolean FALSE - boolean client can do - - No response is sent to this message. - -6.9 Signals - - A signal can be delivered to the remote process/service using the - following message. Some systems may not implement signals, in which - case they SHOULD ignore this message. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "signal" - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - boolean FALSE - string signal name without the "SIG" prefix. - - Signal names will be encoded as discussed in the "exit-signal" - SSH_MSG_CHANNEL_REQUEST. - -6.10 Returning Exit Status - - When the command running at the other end terminates, the following - message can be sent to return the exit status of the command. - Returning the status is RECOMMENDED. No acknowledgment is sent for - this message. The channel needs to be closed with - SSH_MSG_CHANNEL_CLOSE after this message. - - The client MAY ignore these messages. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient_channel - string "exit-status" - boolean FALSE - uint32 exit_status - - The remote command may also terminate violently due to a signal. - Such a condition can be indicated by the following message. A zero - exit_status usually means that the command terminated successfully. - - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "exit-signal" - boolean FALSE - string signal name without the "SIG" prefix. - boolean core dumped - string error message (ISO-10646 UTF-8) - string language tag (as defined in [RFC3066]) - - The signal name is one of the following (these are from [POSIX]) - - ABRT - ALRM - FPE - HUP - ILL - INT - KILL - PIPE - QUIT - SEGV - TERM - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - USR1 - USR2 - - Additional signal names MAY be sent in the format "sig-name@xyz", - where `sig-name' and `xyz' may be anything a particular implementor - wants (except the `@' sign). However, it is suggested that if a - `configure' script is used, the non-standard signal names it finds be - encoded as "SIG@xyz.config.guess", where `SIG' is the signal name - without the "SIG" prefix, and `xyz' be the host type, as determined - by `config.guess'. - - The `error message' contains an additional explanation of the error - message. The message may consist of multiple lines. The client - software MAY display this message to the user. If this is done, the - client software should take the precautions discussed in [SSH-ARCH]. - -7. TCP/IP Port Forwarding - -7.1 Requesting Port Forwarding - - A party need not explicitly request forwardings from its own end to - the other direction. However, if it wishes that connections to a - port on the other side be forwarded to the local side, it must - explicitly request this. - - - byte SSH_MSG_GLOBAL_REQUEST - string "tcpip-forward" - boolean want reply - string address to bind (e.g. "0.0.0.0") - uint32 port number to bind - - `Address to bind' and `port number to bind' specify the IP address - and port to which the socket to be listened is bound. The address - should be "0.0.0.0" if connections are allowed from anywhere. (Note - that the client can still filter connections based on information - passed in the open request.) - - Implementations should only allow forwarding privileged ports if the - user has been authenticated as a privileged user. - - Client implementations SHOULD reject these messages; they are - normally only sent by the client. - - - If a client passes 0 as port number to bind and has want reply TRUE - then the server allocates the next available unprivileged port number - and replies with the following message, otherwise there is no - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - response specific data. - - - byte SSH_MSG_GLOBAL_REQUEST_SUCCESS - uint32 port that was bound on the server - - A port forwarding can be cancelled with the following message. Note - that channel open requests may be received until a reply to this - message is received. - - byte SSH_MSG_GLOBAL_REQUEST - string "cancel-tcpip-forward" - boolean want reply - string address_to_bind (e.g. "127.0.0.1") - uint32 port number to bind - - Client implementations SHOULD reject these messages; they are - normally only sent by the client. - -7.2 TCP/IP Forwarding Channels - - When a connection comes to a port for which remote forwarding has - been requested, a channel is opened to forward the port to the other - side. - - byte SSH_MSG_CHANNEL_OPEN - string "forwarded-tcpip" - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - string address that was connected - uint32 port that was connected - string originator IP address - uint32 originator port - - Implementations MUST reject these messages unless they have - previously requested a remote TCP/IP port forwarding with the given - port number. - - When a connection comes to a locally forwarded TCP/IP port, the - following packet is sent to the other side. Note that these messages - MAY be sent also for ports for which no forwarding has been - explicitly requested. The receiving side must decide whether to - allow the forwarding. - - byte SSH_MSG_CHANNEL_OPEN - string "direct-tcpip" - uint32 sender channel - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - uint32 initial window size - uint32 maximum packet size - string host to connect - uint32 port to connect - string originator IP address - uint32 originator port - - `Host to connect' and `port to connect' specify the TCP/IP host and - port where the recipient should connect the channel. `Host to - connect' may be either a domain name or a numeric IP address. - - `Originator IP address' is the numeric IP address of the machine - where the connection request comes from, and `originator port' is the - port on the originator host from where the connection came from. - - Forwarded TCP/IP channels are independent of any sessions, and - closing a session channel does not in any way imply that forwarded - connections should be closed. - - Client implementations SHOULD reject direct TCP/IP open requests for - security reasons. - -8. Encoding of Terminal Modes - - Terminal modes (as passed in a pty request) are encoded into a byte - stream. It is intended that the coding be portable across different - environments. - - The tty mode description is a stream of bytes. The stream consists - of opcode-argument pairs. It is terminated by opcode TTY_OP_END (0). - Opcodes 1 to 159 have a single uint32 argument. Opcodes 160 to 255 - are not yet defined, and cause parsing to stop (they should only be - used after any other data). - - The client SHOULD put in the stream any modes it knows about, and the - server MAY ignore any modes it does not know about. This allows some - degree of machine-independence, at least between systems that use a - POSIX-like tty interface. The protocol can support other systems as - well, but the client may need to fill reasonable values for a number - of parameters so the server pty gets set to a reasonable mode (the - server leaves all unspecified mode bits in their default values, and - only some combinations make sense). - - The following opcodes have been defined. The naming of opcodes - mostly follows the POSIX terminal mode flags. - - 0 TTY_OP_END Indicates end of options. - 1 VINTR Interrupt character; 255 if none. Similarly for the - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - other characters. Not all of these characters are - supported on all systems. - 2 VQUIT The quit character (sends SIGQUIT signal on POSIX - systems). - 3 VERASE Erase the character to left of the cursor. - 4 VKILL Kill the current input line. - 5 VEOF End-of-file character (sends EOF from the terminal). - 6 VEOL End-of-line character in addition to carriage return - and/or linefeed. - 7 VEOL2 Additional end-of-line character. - 8 VSTART Continues paused output (normally control-Q). - 9 VSTOP Pauses output (normally control-S). - 10 VSUSP Suspends the current program. - 11 VDSUSP Another suspend character. - 12 VREPRINT Reprints the current input line. - 13 VWERASE Erases a word left of cursor. - 14 VLNEXT Enter the next character typed literally, even if it - is a special character - 15 VFLUSH Character to flush output. - 16 VSWTCH Switch to a different shell layer. - 17 VSTATUS Prints system status line (load, command, pid etc). - 18 VDISCARD Toggles the flushing of terminal output. - 30 IGNPAR The ignore parity flag. The parameter SHOULD be 0 if - this flag is FALSE set, and 1 if it is TRUE. - 31 PARMRK Mark parity and framing errors. - 32 INPCK Enable checking of parity errors. - 33 ISTRIP Strip 8th bit off characters. - 34 INLCR Map NL into CR on input. - 35 IGNCR Ignore CR on input. - 36 ICRNL Map CR to NL on input. - 37 IUCLC Translate uppercase characters to lowercase. - 38 IXON Enable output flow control. - 39 IXANY Any char will restart after stop. - 40 IXOFF Enable input flow control. - 41 IMAXBEL Ring bell on input queue full. - 50 ISIG Enable signals INTR, QUIT, [D]SUSP. - 51 ICANON Canonicalize input lines. - 52 XCASE Enable input and output of uppercase characters by - preceding their lowercase equivalents with `\'. - 53 ECHO Enable echoing. - 54 ECHOE Visually erase chars. - 55 ECHOK Kill character discards current line. - 56 ECHONL Echo NL even if ECHO is off. - 57 NOFLSH Don't flush after interrupt. - 58 TOSTOP Stop background jobs from output. - 59 IEXTEN Enable extensions. - 60 ECHOCTL Echo control characters as ^(Char). - 61 ECHOKE Visual erase for line kill. - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - 62 PENDIN Retype pending input. - 70 OPOST Enable output processing. - 71 OLCUC Convert lowercase to uppercase. - 72 ONLCR Map NL to CR-NL. - 73 OCRNL Translate carriage return to newline (output). - 74 ONOCR Translate newline to carriage return-newline - (output). - 75 ONLRET Newline performs a carriage return (output). - 90 CS7 7 bit mode. - 91 CS8 8 bit mode. - 92 PARENB Parity enable. - 93 PARODD Odd parity, else even. - - 128 TTY_OP_ISPEED Specifies the input baud rate in bits per second. - 129 TTY_OP_OSPEED Specifies the output baud rate in bits per second. - - -9. Summary of Message Numbers - - #define SSH_MSG_GLOBAL_REQUEST 80 - #define SSH_MSG_REQUEST_SUCCESS 81 - #define SSH_MSG_REQUEST_FAILURE 82 - #define SSH_MSG_CHANNEL_OPEN 90 - #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91 - #define SSH_MSG_CHANNEL_OPEN_FAILURE 92 - #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93 - #define SSH_MSG_CHANNEL_DATA 94 - #define SSH_MSG_CHANNEL_EXTENDED_DATA 95 - #define SSH_MSG_CHANNEL_EOF 96 - #define SSH_MSG_CHANNEL_CLOSE 97 - #define SSH_MSG_CHANNEL_REQUEST 98 - #define SSH_MSG_CHANNEL_SUCCESS 99 - #define SSH_MSG_CHANNEL_FAILURE 100 - - -10. Security Considerations - - This protocol is assumed to run on top of a secure, authenticated - transport. User authentication and protection against network-level - attacks are assumed to be provided by the underlying protocols. - - It is RECOMMENDED that implementations disable all the potentially - dangerous features (e.g. agent forwarding, X11 forwarding, and TCP/IP - forwarding) if the host key has changed. - - Full security considerations for this protocol are provided in - Section 8 of [SSH-ARCH] - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18] - -Internet-Draft SSH Connection Protocol Oct 2003 - - -11. iana cONSiderations - - This document is part of a set, the IANA considerations for the SSH - protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH], - [SSH-CONNECT] are detailed in [SSH-NUMBERS]. - -12. Intellectual Property - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementers or users of this specification can - be obtained from the IETF Secretariat. - - The IETF has been notified of intellectual property rights claimed in - regard to some or all of the specification contained in this - document. For more information consult the online list of claimed - rights. - -Normative References - - [SSH-ARCH] - Ylonen, T., "SSH Protocol Architecture", I-D - draft-ietf-architecture-15.txt, Oct 2003. - - [SSH-TRANS] - Ylonen, T., "SSH Transport Layer Protocol", I-D - draft-ietf-transport-17.txt, Oct 2003. - - [SSH-USERAUTH] - Ylonen, T., "SSH Authentication Protocol", I-D - draft-ietf-userauth-18.txt, Oct 2003. - - [SSH-CONNECT] - Ylonen, T., "SSH Connection Protocol", I-D - draft-ietf-connect-18.txt, Oct 2003. - - [SSH-NUMBERS] - Lehtinen, S. and D. Moffat, "SSH Protocol Assigned - Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - 2003. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - -Informative References - - [RFC3066] Alvestrand, H., "Tags for the Identification of - Languages", BCP 47, RFC 3066, January 2001. - - [RFC1884] Hinden, R. and S. Deering, "IP Version 6 Addressing - Architecture", RFC 1884, December 1995. - - [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - - [SCHEIFLER] - Scheifler, R., "X Window System : The Complete Reference - to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital - Press ISBN 1555580882, Feburary 1992. - - [POSIX] ISO/IEC, 9945-1., "Information technology -- Portable - Operating System Interface (POSIX)-Part 1: System - Application Program Interface (API) C Language", ANSI/IEE - Std 1003.1, July 1996. - - -Authors' Addresses - - Tatu Ylonen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: ylo@ssh.com - - - Darren J. Moffat (editor) - Sun Microsystems, Inc - 17 Network Circle - Menlo Park CA 94025 - USA - - EMail: Darren.Moffat@Sun.COM - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20] - -Internet-Draft SSH Connection Protocol Oct 2003 - - -Intellectual Property Statement - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementors or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - The IETF has been notified of intellectual property rights claimed in - regard to some or all of the specification contained in this - document. For more information consult the online list of claimed - rights. - - -Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assignees. - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21] - -Internet-Draft SSH Connection Protocol Oct 2003 - - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - -Acknowledgment - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22] \ No newline at end of file diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps deleted file mode 100644 index 06c91bf8cd..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps +++ /dev/null @@ -1,2853 +0,0 @@ -%!PS-Adobe-3.0 -%%BoundingBox: 75 0 595 747 -%%Title: Enscript Output -%%For: Magnus Thoang -%%Creator: GNU enscript 1.6.1 -%%CreationDate: Wed Nov 12 12:26:07 2003 -%%Orientation: Portrait -%%Pages: 15 0 -%%DocumentMedia: A4 595 842 0 () () -%%DocumentNeededResources: (atend) -%%EndComments -%%BeginProlog -%%BeginProcSet: PStoPS 1 15 -userdict begin -[/showpage/erasepage/copypage]{dup where{pop dup load - type/operatortype eq{1 array cvx dup 0 3 index cvx put - bind def}{pop}ifelse}{pop}ifelse}forall -[/letter/legal/executivepage/a4/a4small/b5/com10envelope - /monarchenvelope/c5envelope/dlenvelope/lettersmall/note - /folio/quarto/a5]{dup where{dup wcheck{exch{}put} - {pop{}def}ifelse}{pop}ifelse}forall -/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put} - {pop def}ifelse}{def}ifelse -/PStoPSmatrix matrix currentmatrix def -/PStoPSxform matrix def/PStoPSclip{clippath}def -/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def -/initmatrix{matrix defaultmatrix setmatrix}bind def -/initclip[{matrix currentmatrix PStoPSmatrix setmatrix - [{currentpoint}stopped{$error/newerror false put{newpath}} - {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse] - {[/newpath cvx{/moveto cvx}{/lineto cvx} - {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop} - stopped{$error/errorname get/invalidaccess eq{cleartomark - $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop - /initclip dup load dup type dup/operatortype eq{pop exch pop} - {dup/arraytype eq exch/packedarraytype eq or - {dup xcheck{exch pop aload pop}{pop cvx}ifelse} - {pop cvx}ifelse}ifelse - {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def -/initgraphics{initmatrix newpath initclip 1 setlinewidth - 0 setlinecap 0 setlinejoin []0 setdash 0 setgray - 10 setmiterlimit}bind def -end -%%EndProcSet -%%BeginResource: procset Enscript-Prolog 1.6 1 -% -% Procedures. -% - -/_S { % save current state - /_s save def -} def -/_R { % restore from saved state - _s restore -} def - -/S { % showpage protecting gstate - gsave - showpage - grestore -} bind def - -/MF { % fontname newfontname -> - make a new encoded font - /newfontname exch def - /fontname exch def - - /fontdict fontname findfont def - /newfont fontdict maxlength dict def - - fontdict { - exch - dup /FID eq { - % skip FID pair - pop pop - } { - % copy to the new font dictionary - exch newfont 3 1 roll put - } ifelse - } forall - - newfont /FontName newfontname put - - % insert only valid encoding vectors - encoding_vector length 256 eq { - newfont /Encoding encoding_vector put - } if - - newfontname newfont definefont pop -} def - -/SF { % fontname width height -> - set a new font - /height exch def - /width exch def - - findfont - [width 0 0 height 0 0] makefont setfont -} def - -/SUF { % fontname width height -> - set a new user font - /height exch def - /width exch def - - /F-gs-user-font MF - /F-gs-user-font width height SF -} def - -/M {moveto} bind def -/s {show} bind def - -/Box { % x y w h -> - define box path - /d_h exch def /d_w exch def /d_y exch def /d_x exch def - d_x d_y moveto - d_w 0 rlineto - 0 d_h rlineto - d_w neg 0 rlineto - closepath -} def - -/bgs { % x y height blskip gray str -> - show string with bg color - /str exch def - /gray exch def - /blskip exch def - /height exch def - /y exch def - /x exch def - - gsave - x y blskip sub str stringwidth pop height Box - gray setgray - fill - grestore - x y M str s -} def - -% Highlight bars. -/highlight_bars { % nlines lineheight output_y_margin gray -> - - gsave - setgray - /ymarg exch def - /lineheight exch def - /nlines exch def - - % This 2 is just a magic number to sync highlight lines to text. - 0 d_header_y ymarg sub 2 sub translate - - /cw d_output_w cols div def - /nrows d_output_h ymarg 2 mul sub lineheight div cvi def - - % for each column - 0 1 cols 1 sub { - cw mul /xp exch def - - % for each rows - 0 1 nrows 1 sub { - /rn exch def - rn lineheight mul neg /yp exch def - rn nlines idiv 2 mod 0 eq { - % Draw highlight bar. 4 is just a magic indentation. - xp 4 add yp cw 8 sub lineheight neg Box fill - } if - } for - } for - - grestore -} def - -% Line highlight bar. -/line_highlight { % x y width height gray -> - - gsave - /gray exch def - Box gray setgray fill - grestore -} def - -% Column separator lines. -/column_lines { - gsave - .1 setlinewidth - 0 d_footer_h translate - /cw d_output_w cols div def - 1 1 cols 1 sub { - cw mul 0 moveto - 0 d_output_h rlineto stroke - } for - grestore -} def - -% Column borders. -/column_borders { - gsave - .1 setlinewidth - 0 d_footer_h moveto - 0 d_output_h rlineto - d_output_w 0 rlineto - 0 d_output_h neg rlineto - closepath stroke - grestore -} def - -% Do the actual underlay drawing -/draw_underlay { - ul_style 0 eq { - ul_str true charpath stroke - } { - ul_str show - } ifelse -} def - -% Underlay -/underlay { % - -> - - gsave - 0 d_page_h translate - d_page_h neg d_page_w atan rotate - - ul_gray setgray - ul_font setfont - /dw d_page_h dup mul d_page_w dup mul add sqrt def - ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto - draw_underlay - grestore -} def - -/user_underlay { % - -> - - gsave - ul_x ul_y translate - ul_angle rotate - ul_gray setgray - ul_font setfont - 0 0 ul_h_ptsize 2 div sub moveto - draw_underlay - grestore -} def - -% Page prefeed -/page_prefeed { % bool -> - - statusdict /prefeed known { - statusdict exch /prefeed exch put - } { - pop - } ifelse -} def - -% Wrapped line markers -/wrapped_line_mark { % x y charwith charheight type -> - - /type exch def - /h exch def - /w exch def - /y exch def - /x exch def - - type 2 eq { - % Black boxes (like TeX does) - gsave - 0 setlinewidth - x w 4 div add y M - 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto - closepath fill - grestore - } { - type 3 eq { - % Small arrows - gsave - .2 setlinewidth - x w 2 div add y h 2 div add M - w 4 div 0 rlineto - x w 4 div add y lineto stroke - - x w 4 div add w 8 div add y h 4 div add M - x w 4 div add y lineto - w 4 div h 8 div rlineto stroke - grestore - } { - % do nothing - } ifelse - } ifelse -} def - -% EPSF import. - -/BeginEPSF { - /b4_Inc_state save def % Save state for cleanup - /dict_count countdictstack def % Count objects on dict stack - /op_count count 1 sub def % Count objects on operand stack - userdict begin - /showpage { } def - 0 setgray 0 setlinecap - 1 setlinewidth 0 setlinejoin - 10 setmiterlimit [ ] 0 setdash newpath - /languagelevel where { - pop languagelevel - 1 ne { - false setstrokeadjust false setoverprint - } if - } if -} bind def - -/EndEPSF { - count op_count sub { pos } repeat % Clean up stacks - countdictstack dict_count sub { end } repeat - b4_Inc_state restore -} bind def - -% Check PostScript language level. -/languagelevel where { - pop /gs_languagelevel languagelevel def -} { - /gs_languagelevel 1 def -} ifelse -%%EndResource -%%BeginResource: procset Enscript-Encoding-88591 1.6 1 -/encoding_vector [ -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclam /quotedbl /numbersign -/dollar /percent /ampersand /quoteright -/parenleft /parenright /asterisk /plus -/comma /hyphen /period /slash -/zero /one /two /three -/four /five /six /seven -/eight /nine /colon /semicolon -/less /equal /greater /question -/at /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 /bracketleft -/backslash /bracketright /asciicircum /underscore -/quoteleft /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 /braceleft -/bar /braceright /tilde /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclamdown /cent /sterling -/currency /yen /brokenbar /section -/dieresis /copyright /ordfeminine /guillemotleft -/logicalnot /hyphen /registered /macron -/degree /plusminus /twosuperior /threesuperior -/acute /mu /paragraph /bullet -/cedilla /onesuperior /ordmasculine /guillemotright -/onequarter /onehalf /threequarters /questiondown -/Agrave /Aacute /Acircumflex /Atilde -/Adieresis /Aring /AE /Ccedilla -/Egrave /Eacute /Ecircumflex /Edieresis -/Igrave /Iacute /Icircumflex /Idieresis -/Eth /Ntilde /Ograve /Oacute -/Ocircumflex /Otilde /Odieresis /multiply -/Oslash /Ugrave /Uacute /Ucircumflex -/Udieresis /Yacute /Thorn /germandbls -/agrave /aacute /acircumflex /atilde -/adieresis /aring /ae /ccedilla -/egrave /eacute /ecircumflex /edieresis -/igrave /iacute /icircumflex /idieresis -/eth /ntilde /ograve /oacute -/ocircumflex /otilde /odieresis /divide -/oslash /ugrave /uacute /ucircumflex -/udieresis /yacute /thorn /ydieresis -] def -%%EndResource -%%EndProlog -%%BeginSetup -%%IncludeResource: font Courier-Bold -%%IncludeResource: font Courier -/HFpt_w 10 def -/HFpt_h 10 def -/Courier-Bold /HF-gs-font MF -/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def -/Courier /F-gs-font MF -/F-gs-font 10 10 SF -/#copies 1 def -/d_page_w 520 def -/d_page_h 747 def -/d_header_x 0 def -/d_header_y 747 def -/d_header_w 520 def -/d_header_h 0 def -/d_footer_x 0 def -/d_footer_y 0 def -/d_footer_w 520 def -/d_footer_h 0 def -/d_output_w 520 def -/d_output_h 747 def -/cols 1 def -userdict/PStoPSxform PStoPSmatrix matrix currentmatrix - matrix invertmatrix matrix concatmatrix - matrix invertmatrix put -%%EndSetup -%%Page: (0,1) 1 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 1 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 701 M -(Network Working Group T. Ylonen) s -5 690 M -(Internet-Draft S. Lehtinen) s -5 679 M -(Expires: April 1, 2002 SSH Communications Security Corp) s -5 668 M -( October 2001) s -5 635 M -( SSH File Transfer Protocol) s -5 624 M -( draft-ietf-secsh-filexfer-02.txt) s -5 602 M -(Status of this Memo) s -5 580 M -( This document is an Internet-Draft and is in full conformance with) s -5 569 M -( all provisions of Section 10 of RFC2026.) s -5 547 M -( Internet-Drafts are working documents of the Internet Engineering) s -5 536 M -( Task Force \(IETF\), its areas, and its working groups. Note that) s -5 525 M -( other groups may also distribute working documents as Internet-) s -5 514 M -( Drafts.) s -5 492 M -( Internet-Drafts are draft documents valid for a maximum of six months) s -5 481 M -( and may be updated, replaced, or obsoleted by other documents at any) s -5 470 M -( time. It is inappropriate to use Internet-Drafts as reference) s -5 459 M -( material or to cite them other than as "work in progress.") s -5 437 M -( The list of current Internet-Drafts can be accessed at http://) s -5 426 M -( www.ietf.org/ietf/1id-abstracts.txt.) s -5 404 M -( The list of Internet-Draft Shadow Directories can be accessed at) s -5 393 M -( http://www.ietf.org/shadow.html.) s -5 371 M -( This Internet-Draft will expire on April 1, 2002.) s -5 349 M -(Copyright Notice) s -5 327 M -( Copyright \(C\) The Internet Society \(2001\). All Rights Reserved.) s -5 305 M -(Abstract) s -5 283 M -( The SSH File Transfer Protocol provides secure file transfer) s -5 272 M -( functionality over any reliable data stream. It is the standard file) s -5 261 M -( transfer protocol for use with the SSH2 protocol. This document) s -5 250 M -( describes the file transfer protocol and its interface to the SSH2) s -5 239 M -( protocol suite.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 1]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 2 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(Table of Contents) s -5 668 M -( 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 657 M -( 2. Use with the SSH Connection Protocol . . . . . . . . . . . . 4) s -5 646 M -( 3. General Packet Format . . . . . . . . . . . . . . . . . . . 5) s -5 635 M -( 4. Protocol Initialization . . . . . . . . . . . . . . . . . . 7) s -5 624 M -( 5. File Attributes . . . . . . . . . . . . . . . . . . . . . . 8) s -5 613 M -( 6. Requests From the Client to the Server . . . . . . . . . . . 10) s -5 602 M -( 6.1 Request Synchronization and Reordering . . . . . . . . . . . 10) s -5 591 M -( 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . . 11) s -5 580 M -( 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . . 11) s -5 569 M -( 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . . 13) s -5 558 M -( 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . . 14) s -5 547 M -( 6.6 Creating and Deleting Directories . . . . . . . . . . . . . 15) s -5 536 M -( 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . . 15) s -5 525 M -( 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . . 16) s -5 514 M -( 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . . 17) s -5 503 M -( 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . . 18) s -5 492 M -( 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . . 18) s -5 481 M -( 7. Responses from the Server to the Client . . . . . . . . . . 20) s -5 470 M -( 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . . 24) s -5 459 M -( 9. Security Considerations . . . . . . . . . . . . . . . . . . 25) s -5 448 M -( 10. Changes from previous protocol versions . . . . . . . . . . 26) s -5 437 M -( 10.1 Changes between versions 3 and 2 . . . . . . . . . . . . . . 26) s -5 426 M -( 10.2 Changes between versions 2 and 1 . . . . . . . . . . . . . . 26) s -5 415 M -( 10.3 Changes between versions 1 and 0 . . . . . . . . . . . . . . 26) s -5 404 M -( 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . . 27) s -5 393 M -( References . . . . . . . . . . . . . . . . . . . . . . . . . 28) s -5 382 M -( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 28) s -5 371 M -( Full Copyright Statement . . . . . . . . . . . . . . . . . . 29) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 2]) s -_R -S -PStoPSsaved restore -%%Page: (2,3) 2 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 3 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(1. Introduction) s -5 668 M -( This protocol provides secure file transfer \(and more generally file) s -5 657 M -( system access\) functionality over a reliable data stream, such as a) s -5 646 M -( channel in the SSH2 protocol [3].) s -5 624 M -( This protocol is designed so that it could be used to implement a) s -5 613 M -( secure remote file system service, as well as a secure file transfer) s -5 602 M -( service.) s -5 580 M -( This protocol assumes that it runs over a secure channel, and that) s -5 569 M -( the server has already authenticated the user at the client end, and) s -5 558 M -( that the identity of the client user is externally available to the) s -5 547 M -( server implementation.) s -5 525 M -( In general, this protocol follows a simple request-response model.) s -5 514 M -( Each request and response contains a sequence number and multiple) s -5 503 M -( requests may be pending simultaneously. There are a relatively large) s -5 492 M -( number of different request messages, but a small number of possible) s -5 481 M -( response messages. Each request has one or more response messages) s -5 470 M -( that may be returned in result \(e.g., a read either returns data or) s -5 459 M -( reports error status\).) s -5 437 M -( The packet format descriptions in this specification follow the) s -5 426 M -( notation presented in the secsh architecture draft.[3].) s -5 404 M -( Even though this protocol is described in the context of the SSH2) s -5 393 M -( protocol, this protocol is general and independent of the rest of the) s -5 382 M -( SSH2 protocol suite. It could be used in a number of different) s -5 371 M -( applications, such as secure file transfer over TLS RFC 2246 [1] and) s -5 360 M -( transfer of management information in VPN applications.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 3]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 4 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(2. Use with the SSH Connection Protocol) s -5 668 M -( When used with the SSH2 Protocol suite, this protocol is intended to) s -5 657 M -( be used from the SSH Connection Protocol [5] as a subsystem, as) s -5 646 M -( described in section ``Starting a Shell or a Command''. The) s -5 635 M -( subsystem name used with this protocol is "sftp".) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 4]) s -_R -S -PStoPSsaved restore -%%Page: (4,5) 3 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 5 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(3. General Packet Format) s -5 668 M -( All packets transmitted over the secure connection are of the) s -5 657 M -( following format:) s -5 635 M -( uint32 length) s -5 624 M -( byte type) s -5 613 M -( byte[length - 1] data payload) s -5 591 M -( That is, they are just data preceded by 32-bit length and 8-bit type) s -5 580 M -( fields. The `length' is the length of the data area, and does not) s -5 569 M -( include the `length' field itself. The format and interpretation of) s -5 558 M -( the data area depends on the packet type.) s -5 536 M -( All packet descriptions below only specify the packet type and the) s -5 525 M -( data that goes into the data field. Thus, they should be prefixed by) s -5 514 M -( the `length' and `type' fields.) s -5 492 M -( The maximum size of a packet is in practice determined by the client) s -5 481 M -( \(the maximum size of read or write requests that it sends, plus a few) s -5 470 M -( bytes of packet overhead\). All servers SHOULD support packets of at) s -5 459 M -( least 34000 bytes \(where the packet size refers to the full length,) s -5 448 M -( including the header above\). This should allow for reads and writes) s -5 437 M -( of at most 32768 bytes.) s -5 415 M -( There is no limit on the number of outstanding \(non-acknowledged\)) s -5 404 M -( requests that the client may send to the server. In practice this is) s -5 393 M -( limited by the buffering available on the data stream and the queuing) s -5 382 M -( performed by the server. If the server's queues are full, it should) s -5 371 M -( not read any more data from the stream, and flow control will prevent) s -5 360 M -( the client from sending more requests. Note, however, that while) s -5 349 M -( there is no restriction on the protocol level, the client's API may) s -5 338 M -( provide a limit in order to prevent infinite queuing of outgoing) s -5 327 M -( requests at the client.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 5]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 6 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( The following values are defined for packet types.) s -5 668 M -( #define SSH_FXP_INIT 1) s -5 657 M -( #define SSH_FXP_VERSION 2) s -5 646 M -( #define SSH_FXP_OPEN 3) s -5 635 M -( #define SSH_FXP_CLOSE 4) s -5 624 M -( #define SSH_FXP_READ 5) s -5 613 M -( #define SSH_FXP_WRITE 6) s -5 602 M -( #define SSH_FXP_LSTAT 7) s -5 591 M -( #define SSH_FXP_FSTAT 8) s -5 580 M -( #define SSH_FXP_SETSTAT 9) s -5 569 M -( #define SSH_FXP_FSETSTAT 10) s -5 558 M -( #define SSH_FXP_OPENDIR 11) s -5 547 M -( #define SSH_FXP_READDIR 12) s -5 536 M -( #define SSH_FXP_REMOVE 13) s -5 525 M -( #define SSH_FXP_MKDIR 14) s -5 514 M -( #define SSH_FXP_RMDIR 15) s -5 503 M -( #define SSH_FXP_REALPATH 16) s -5 492 M -( #define SSH_FXP_STAT 17) s -5 481 M -( #define SSH_FXP_RENAME 18) s -5 470 M -( #define SSH_FXP_READLINK 19) s -5 459 M -( #define SSH_FXP_SYMLINK 20) s -5 448 M -( #define SSH_FXP_STATUS 101) s -5 437 M -( #define SSH_FXP_HANDLE 102) s -5 426 M -( #define SSH_FXP_DATA 103) s -5 415 M -( #define SSH_FXP_NAME 104) s -5 404 M -( #define SSH_FXP_ATTRS 105) s -5 393 M -( #define SSH_FXP_EXTENDED 200) s -5 382 M -( #define SSH_FXP_EXTENDED_REPLY 201) s -5 360 M -( Additional packet types should only be defined if the protocol) s -5 349 M -( version number \(see Section ``Protocol Initialization''\) is) s -5 338 M -( incremented, and their use MUST be negotiated using the version) s -5 327 M -( number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY) s -5 316 M -( packets can be used to implement vendor-specific extensions. See) s -5 305 M -( Section ``Vendor-Specific-Extensions'' for more details.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 6]) s -_R -S -PStoPSsaved restore -%%Page: (6,7) 4 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 7 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(4. Protocol Initialization) s -5 668 M -( When the file transfer protocol starts, it first sends a SSH_FXP_INIT) s -5 657 M -( \(including its version number\) packet to the server. The server) s -5 646 M -( responds with a SSH_FXP_VERSION packet, supplying the lowest of its) s -5 635 M -( own and the client's version number. Both parties should from then) s -5 624 M -( on adhere to particular version of the protocol.) s -5 602 M -( The SSH_FXP_INIT packet \(from client to server\) has the following) s -5 591 M -( data:) s -5 569 M -( uint32 version) s -5 558 M -( ) s -5 536 M -( The SSH_FXP_VERSION packet \(from server to client\) has the following) s -5 525 M -( data:) s -5 503 M -( uint32 version) s -5 492 M -( ) s -5 470 M -( The version number of the protocol specified in this document is 3.) s -5 459 M -( The version number should be incremented for each incompatible) s -5 448 M -( revision of this protocol.) s -5 426 M -( The extension data in the above packets may be empty, or may be a) s -5 415 M -( sequence of) s -5 393 M -( string extension_name) s -5 382 M -( string extension_data) s -5 360 M -( pairs \(both strings MUST always be present if one is, but the) s -5 349 M -( `extension_data' string may be of zero length\). If present, these) s -5 338 M -( strings indicate extensions to the baseline protocol. The) s -5 327 M -( `extension_name' field\(s\) identify the name of the extension. The) s -5 316 M -( name should be of the form "name@domain", where the domain is the DNS) s -5 305 M -( domain name of the organization defining the extension. Additional) s -5 294 M -( names that are not of this format may be defined later by the IETF.) s -5 283 M -( Implementations MUST silently ignore any extensions whose name they) s -5 272 M -( do not recognize.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 7]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 8 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(5. File Attributes) s -5 668 M -( A new compound data type is defined for encoding file attributes. It) s -5 657 M -( is basically just a combination of elementary types, but is defined) s -5 646 M -( once because of the non-trivial description of the fields and to) s -5 635 M -( ensure maintainability.) s -5 613 M -( The same encoding is used both when returning file attributes from) s -5 602 M -( the server and when sending file attributes to the server. When) s -5 591 M -( sending it to the server, the flags field specifies which attributes) s -5 580 M -( are included, and the server will use default values for the) s -5 569 M -( remaining attributes \(or will not modify the values of remaining) s -5 558 M -( attributes\). When receiving attributes from the server, the flags) s -5 547 M -( specify which attributes are included in the returned data. The) s -5 536 M -( server normally returns all attributes it knows about.) s -5 514 M -( uint32 flags) s -5 503 M -( uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE) s -5 492 M -( uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID) s -5 481 M -( uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID) s -5 470 M -( uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS) s -5 459 M -( uint32 atime present only if flag SSH_FILEXFER_ACMODTIME) s -5 448 M -( uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME) s -5 437 M -( uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED) s -5 426 M -( string extended_type) s -5 415 M -( string extended_data) s -5 404 M -( ... more extended data \(extended_type - extended_data pairs\),) s -5 393 M -( so that number of pairs equals extended_count) s -5 371 M -( The `flags' specify which of the fields are present. Those fields) s -5 360 M -( for which the corresponding flag is not set are not present \(not) s -5 349 M -( included in the packet\). New flags can only be added by incrementing) s -5 338 M -( the protocol version number \(or by using the extension mechanism) s -5 327 M -( described below\).) s -5 305 M -( The `size' field specifies the size of the file in bytes.) s -5 283 M -( The `uid' and `gid' fields contain numeric Unix-like user and group) s -5 272 M -( identifiers, respectively.) s -5 250 M -( The `permissions' field contains a bit mask of file permissions as) s -5 239 M -( defined by posix [1].) s -5 217 M -( The `atime' and `mtime' contain the access and modification times of) s -5 206 M -( the files, respectively. They are represented as seconds from Jan 1,) s -5 195 M -( 1970 in UTC.) s -5 173 M -( The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 8]) s -_R -S -PStoPSsaved restore -%%Page: (8,9) 5 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 9 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( mechanism for vendor-specific extensions. If the flag is specified,) s -5 679 M -( then the `extended_count' field is present. It specifies the number) s -5 668 M -( of extended_type-extended_data pairs that follow. Each of these) s -5 657 M -( pairs specifies an extended attribute. For each of the attributes,) s -5 646 M -( the extended_type field should be a string of the format) s -5 635 M -( "name@domain", where "domain" is a valid, registered domain name and) s -5 624 M -( "name" identifies the method. The IETF may later standardize certain) s -5 613 M -( names that deviate from this format \(e.g., that do not contain the) s -5 602 M -( "@" sign\). The interpretation of `extended_data' depends on the) s -5 591 M -( type. Implementations SHOULD ignore extended data fields that they) s -5 580 M -( do not understand.) s -5 558 M -( Additional fields can be added to the attributes by either defining) s -5 547 M -( additional bits to the flags field to indicate their presence, or by) s -5 536 M -( defining extended attributes for them. The extended attributes) s -5 525 M -( mechanism is recommended for most purposes; additional flags bits) s -5 514 M -( should only be defined by an IETF standards action that also) s -5 503 M -( increments the protocol version number. The use of such new fields) s -5 492 M -( MUST be negotiated by the version number in the protocol exchange.) s -5 481 M -( It is a protocol error if a packet with unsupported protocol bits is) s -5 470 M -( received.) s -5 448 M -( The flags bits are defined to have the following values:) s -5 426 M -( #define SSH_FILEXFER_ATTR_SIZE 0x00000001) s -5 415 M -( #define SSH_FILEXFER_ATTR_UIDGID 0x00000002) s -5 404 M -( #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004) s -5 393 M -( #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008) s -5 382 M -( #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 9]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 10 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(6. Requests From the Client to the Server) s -5 668 M -( Requests from the client to the server represent the various file) s -5 657 M -( system operations. Each request begins with an `id' field, which is) s -5 646 M -( a 32-bit identifier identifying the request \(selected by the client\).) s -5 635 M -( The same identifier will be returned in the response to the request.) s -5 624 M -( One possible implementation of it is a monotonically increasing) s -5 613 M -( request sequence number \(modulo 2^32\).) s -5 591 M -( Many operations in the protocol operate on open files. The) s -5 580 M -( SSH_FXP_OPEN request can return a file handle \(which is an opaque) s -5 569 M -( variable-length string\) which may be used to access the file later) s -5 558 M -( \(e.g. in a read operation\). The client MUST NOT send requests the) s -5 547 M -( server with bogus or closed handles. However, the server MUST) s -5 536 M -( perform adequate checks on the handle in order to avoid security) s -5 525 M -( risks due to fabricated handles.) s -5 503 M -( This design allows either stateful and stateless server) s -5 492 M -( implementation, as well as an implementation which caches state) s -5 481 M -( between requests but may also flush it. The contents of the file) s -5 470 M -( handle string are entirely up to the server and its design. The) s -5 459 M -( client should not modify or attempt to interpret the file handle) s -5 448 M -( strings.) s -5 426 M -( The file handle strings MUST NOT be longer than 256 bytes.) s -5 404 M -(6.1 Request Synchronization and Reordering) s -5 382 M -( The protocol and implementations MUST process requests relating to) s -5 371 M -( the same file in the order in which they are received. In other) s -5 360 M -( words, if an application submits multiple requests to the server, the) s -5 349 M -( results in the responses will be the same as if it had sent the) s -5 338 M -( requests one at a time and waited for the response in each case. For) s -5 327 M -( example, the server may process non-overlapping read/write requests) s -5 316 M -( to the same file in parallel, but overlapping reads and writes cannot) s -5 305 M -( be reordered or parallelized. However, there are no ordering) s -5 294 M -( restrictions on the server for processing requests from two different) s -5 283 M -( file transfer connections. The server may interleave and parallelize) s -5 272 M -( them at will.) s -5 250 M -( There are no restrictions on the order in which responses to) s -5 239 M -( outstanding requests are delivered to the client, except that the) s -5 228 M -( server must ensure fairness in the sense that processing of no) s -5 217 M -( request will be indefinitely delayed even if the client is sending) s -5 206 M -( other requests so that there are multiple outstanding requests all) s -5 195 M -( the time.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 10]) s -_R -S -PStoPSsaved restore -%%Page: (10,11) 6 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 11 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(6.2 File Names) s -5 668 M -( This protocol represents file names as strings. File names are) s -5 657 M -( assumed to use the slash \('/'\) character as a directory separator.) s -5 635 M -( File names starting with a slash are "absolute", and are relative to) s -5 624 M -( the root of the file system. Names starting with any other character) s -5 613 M -( are relative to the user's default directory \(home directory\). Note) s -5 602 M -( that identifying the user is assumed to take place outside of this) s -5 591 M -( protocol.) s -5 569 M -( Servers SHOULD interpret a path name component ".." as referring to) s -5 558 M -( the parent directory, and "." as referring to the current directory.) s -5 547 M -( If the server implementation limits access to certain parts of the) s -5 536 M -( file system, it must be extra careful in parsing file names when) s -5 525 M -( enforcing such restrictions. There have been numerous reported) s -5 514 M -( security bugs where a ".." in a path name has allowed access outside) s -5 503 M -( the intended area.) s -5 481 M -( An empty path name is valid, and it refers to the user's default) s -5 470 M -( directory \(usually the user's home directory\).) s -5 448 M -( Otherwise, no syntax is defined for file names by this specification.) s -5 437 M -( Clients should not make any other assumptions; however, they can) s -5 426 M -( splice path name components returned by SSH_FXP_READDIR together) s -5 415 M -( using a slash \('/'\) as the separator, and that will work as expected.) s -5 393 M -( It is understood that the lack of well-defined semantics for file) s -5 382 M -( names may cause interoperability problems between clients and servers) s -5 371 M -( using radically different operating systems. However, this approach) s -5 360 M -( is known to work acceptably with most systems, and alternative) s -5 349 M -( approaches that e.g. treat file names as sequences of structured) s -5 338 M -( components are quite complicated.) s -5 316 M -(6.3 Opening, Creating, and Closing Files) s -5 294 M -( Files are opened and created using the SSH_FXP_OPEN message, whose) s -5 283 M -( data part is as follows:) s -5 261 M -( uint32 id) s -5 250 M -( string filename) s -5 239 M -( uint32 pflags) s -5 228 M -( ATTRS attrs) s -5 206 M -( The `id' field is the request identifier as for all requests.) s -5 184 M -( The `filename' field specifies the file name. See Section ``File) s -5 173 M -( Names'' for more information.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 11]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 12 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( The `pflags' field is a bitmask. The following bits have been) s -5 679 M -( defined.) s -5 657 M -( #define SSH_FXF_READ 0x00000001) s -5 646 M -( #define SSH_FXF_WRITE 0x00000002) s -5 635 M -( #define SSH_FXF_APPEND 0x00000004) s -5 624 M -( #define SSH_FXF_CREAT 0x00000008) s -5 613 M -( #define SSH_FXF_TRUNC 0x00000010) s -5 602 M -( #define SSH_FXF_EXCL 0x00000020) s -5 580 M -( These have the following meanings:) s -5 558 M -( SSH_FXF_READ) s -5 547 M -( Open the file for reading.) s -5 525 M -( SSH_FXF_WRITE) s -5 514 M -( Open the file for writing. If both this and SSH_FXF_READ are) s -5 503 M -( specified, the file is opened for both reading and writing.) s -5 481 M -( SSH_FXF_APPEND) s -5 470 M -( Force all writes to append data at the end of the file.) s -5 448 M -( SSH_FXF_CREAT) s -5 437 M -( If this flag is specified, then a new file will be created if one) s -5 426 M -( does not already exist \(if O_TRUNC is specified, the new file will) s -5 415 M -( be truncated to zero length if it previously exists\).) s -5 393 M -( SSH_FXF_TRUNC) s -5 382 M -( Forces an existing file with the same name to be truncated to zero) s -5 371 M -( length when creating a file by specifying SSH_FXF_CREAT.) s -5 360 M -( SSH_FXF_CREAT MUST also be specified if this flag is used.) s -5 338 M -( SSH_FXF_EXCL) s -5 327 M -( Causes the request to fail if the named file already exists.) s -5 316 M -( SSH_FXF_CREAT MUST also be specified if this flag is used.) s -5 294 M -( The `attrs' field specifies the initial attributes for the file.) s -5 283 M -( Default values will be used for those attributes that are not) s -5 272 M -( specified. See Section ``File Attributes'' for more information.) s -5 250 M -( Regardless the server operating system, the file will always be) s -5 239 M -( opened in "binary" mode \(i.e., no translations between different) s -5 228 M -( character sets and newline encodings\).) s -5 206 M -( The response to this message will be either SSH_FXP_HANDLE \(if the) s -5 195 M -( operation is successful\) or SSH_FXP_STATUS \(if the operation fails\).) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 12]) s -_R -S -PStoPSsaved restore -%%Page: (12,13) 7 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 13 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( A file is closed by using the SSH_FXP_CLOSE request. Its data field) s -5 679 M -( has the following format:) s -5 657 M -( uint32 id) s -5 646 M -( string handle) s -5 624 M -( where `id' is the request identifier, and `handle' is a handle) s -5 613 M -( previously returned in the response to SSH_FXP_OPEN or) s -5 602 M -( SSH_FXP_OPENDIR. The handle becomes invalid immediately after this) s -5 591 M -( request has been sent.) s -5 569 M -( The response to this request will be a SSH_FXP_STATUS message. One) s -5 558 M -( should note that on some server platforms even a close can fail.) s -5 547 M -( This can happen e.g. if the server operating system caches writes,) s -5 536 M -( and an error occurs while flushing cached writes during the close.) s -5 514 M -(6.4 Reading and Writing) s -5 492 M -( Once a file has been opened, it can be read using the SSH_FXP_READ) s -5 481 M -( message, which has the following format:) s -5 459 M -( uint32 id) s -5 448 M -( string handle) s -5 437 M -( uint64 offset) s -5 426 M -( uint32 len) s -5 404 M -( where `id' is the request identifier, `handle' is an open file handle) s -5 393 M -( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) relative) s -5 382 M -( to the beginning of the file from where to start reading, and `len') s -5 371 M -( is the maximum number of bytes to read.) s -5 349 M -( In response to this request, the server will read as many bytes as it) s -5 338 M -( can from the file \(up to `len'\), and return them in a SSH_FXP_DATA) s -5 327 M -( message. If an error occurs or EOF is encountered before reading any) s -5 316 M -( data, the server will respond with SSH_FXP_STATUS. For normal disk) s -5 305 M -( files, it is guaranteed that this will read the specified number of) s -5 294 M -( bytes, or up to end of file. For e.g. device files this may return) s -5 283 M -( fewer bytes than requested.) s -5 261 M -( Writing to a file is achieved using the SSH_FXP_WRITE message, which) s -5 250 M -( has the following format:) s -5 228 M -( uint32 id) s -5 217 M -( string handle) s -5 206 M -( uint64 offset) s -5 195 M -( string data) s -5 173 M -( where `id' is a request identifier, `handle' is a file handle) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 13]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 14 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) from the) s -5 679 M -( beginning of the file where to start writing, and `data' is the data) s -5 668 M -( to be written.) s -5 646 M -( The write will extend the file if writing beyond the end of the file.) s -5 635 M -( It is legal to write way beyond the end of the file; the semantics) s -5 624 M -( are to write zeroes from the end of the file to the specified offset) s -5 613 M -( and then the data. On most operating systems, such writes do not) s -5 602 M -( allocate disk space but instead leave "holes" in the file.) s -5 580 M -( The server responds to a write request with a SSH_FXP_STATUS message.) s -5 558 M -(6.5 Removing and Renaming Files) s -5 536 M -( Files can be removed using the SSH_FXP_REMOVE message. It has the) s -5 525 M -( following format:) s -5 503 M -( uint32 id) s -5 492 M -( string filename) s -5 470 M -( where `id' is the request identifier and `filename' is the name of) s -5 459 M -( the file to be removed. See Section ``File Names'' for more) s -5 448 M -( information. This request cannot be used to remove directories.) s -5 426 M -( The server will respond to this request with a SSH_FXP_STATUS) s -5 415 M -( message.) s -5 393 M -( Files \(and directories\) can be renamed using the SSH_FXP_RENAME) s -5 382 M -( message. Its data is as follows:) s -5 360 M -( uint32 id) s -5 349 M -( string oldpath) s -5 338 M -( string newpath) s -5 316 M -( where `id' is the request identifier, `oldpath' is the name of an) s -5 305 M -( existing file or directory, and `newpath' is the new name for the) s -5 294 M -( file or directory. It is an error if there already exists a file) s -5 283 M -( with the name specified by newpath. The server may also fail rename) s -5 272 M -( requests in other situations, for example if `oldpath' and `newpath') s -5 261 M -( point to different file systems on the server.) s -5 239 M -( The server will respond to this request with a SSH_FXP_STATUS) s -5 228 M -( message.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 14]) s -_R -S -PStoPSsaved restore -%%Page: (14,15) 8 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 15 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(6.6 Creating and Deleting Directories) s -5 668 M -( New directories can be created using the SSH_FXP_MKDIR request. It) s -5 657 M -( has the following format:) s -5 635 M -( uint32 id) s -5 624 M -( string path) s -5 613 M -( ATTRS attrs) s -5 591 M -( where `id' is the request identifier, `path' and `attrs' specifies) s -5 580 M -( the modifications to be made to its attributes. See Section ``File) s -5 569 M -( Names'' for more information on file names. Attributes are discussed) s -5 558 M -( in more detail in Section ``File Attributes''. specifies the) s -5 547 M -( directory to be created. An error will be returned if a file or) s -5 536 M -( directory with the specified path already exists. The server will) s -5 525 M -( respond to this request with a SSH_FXP_STATUS message.) s -5 503 M -( Directories can be removed using the SSH_FXP_RMDIR request, which) s -5 492 M -( has the following format:) s -5 470 M -( uint32 id) s -5 459 M -( string path) s -5 437 M -( where `id' is the request identifier, and `path' specifies the) s -5 426 M -( directory to be removed. See Section ``File Names'' for more) s -5 415 M -( information on file names. An error will be returned if no directory) s -5 404 M -( with the specified path exists, or if the specified directory is not) s -5 393 M -( empty, or if the path specified a file system object other than a) s -5 382 M -( directory. The server responds to this request with a SSH_FXP_STATUS) s -5 371 M -( message.) s -5 349 M -(6.7 Scanning Directories) s -5 327 M -( The files in a directory can be listed using the SSH_FXP_OPENDIR and) s -5 316 M -( SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one) s -5 305 M -( or more file names with full file attributes for each file. The) s -5 294 M -( client should call SSH_FXP_READDIR repeatedly until it has found the) s -5 283 M -( file it is looking for or until the server responds with a) s -5 272 M -( SSH_FXP_STATUS message indicating an error \(normally SSH_FX_EOF if) s -5 261 M -( there are no more files in the directory\). The client should then) s -5 250 M -( close the handle using the SSH_FXP_CLOSE request.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 15]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 16 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( The SSH_FXP_OPENDIR opens a directory for reading. It has the) s -5 679 M -( following format:) s -5 657 M -( uint32 id) s -5 646 M -( string path) s -5 624 M -( where `id' is the request identifier and `path' is the path name of) s -5 613 M -( the directory to be listed \(without any trailing slash\). See Section) s -5 602 M -( ``File Names'' for more information on file names. This will return) s -5 591 M -( an error if the path does not specify a directory or if the directory) s -5 580 M -( is not readable. The server will respond to this request with either) s -5 569 M -( a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.) s -5 547 M -( Once the directory has been successfully opened, files \(and) s -5 536 M -( directories\) contained in it can be listed using SSH_FXP_READDIR) s -5 525 M -( requests. These are of the format) s -5 503 M -( uint32 id) s -5 492 M -( string handle) s -5 470 M -( where `id' is the request identifier, and `handle' is a handle) s -5 459 M -( returned by SSH_FXP_OPENDIR. \(It is a protocol error to attempt to) s -5 448 M -( use an ordinary file handle returned by SSH_FXP_OPEN.\)) s -5 426 M -( The server responds to this request with either a SSH_FXP_NAME or a) s -5 415 M -( SSH_FXP_STATUS message. One or more names may be returned at a time.) s -5 404 M -( Full status information is returned for each name in order to speed) s -5 393 M -( up typical directory listings.) s -5 371 M -( When the client no longer wishes to read more names from the) s -5 360 M -( directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle) s -5 349 M -( should be closed regardless of whether an error has occurred or not.) s -5 327 M -(6.8 Retrieving File Attributes) s -5 305 M -( Very often, file attributes are automatically returned by) s -5 294 M -( SSH_FXP_READDIR. However, sometimes there is need to specifically) s -5 283 M -( retrieve the attributes for a named file. This can be done using the) s -5 272 M -( SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.) s -5 250 M -( SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT) s -5 239 M -( follows symbolic links on the server, whereas SSH_FXP_LSTAT does not) s -5 228 M -( follow symbolic links. Both have the same format:) s -5 206 M -( uint32 id) s -5 195 M -( string path) s -5 173 M -( where `id' is the request identifier, and `path' specifies the file) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 16]) s -_R -S -PStoPSsaved restore -%%Page: (16,17) 9 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 17 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( system object for which status is to be returned. The server) s -5 679 M -( responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.) s -5 657 M -( SSH_FXP_FSTAT differs from the others in that it returns status) s -5 646 M -( information for an open file \(identified by the file handle\). Its) s -5 635 M -( format is as follows:) s -5 613 M -( uint32 id) s -5 602 M -( string handle) s -5 580 M -( where `id' is the request identifier and `handle' is a file handle) s -5 569 M -( returned by SSH_FXP_OPEN. The server responds to this request with) s -5 558 M -( SSH_FXP_ATTRS or SSH_FXP_STATUS.) s -5 536 M -(6.9 Setting File Attributes) s -5 514 M -( File attributes may be modified using the SSH_FXP_SETSTAT and) s -5 503 M -( SSH_FXP_FSETSTAT requests. These requests are used for operations) s -5 492 M -( such as changing the ownership, permissions or access times, as well) s -5 481 M -( as for truncating a file.) s -5 459 M -( The SSH_FXP_SETSTAT request is of the following format:) s -5 437 M -( uint32 id) s -5 426 M -( string path) s -5 415 M -( ATTRS attrs) s -5 393 M -( where `id' is the request identifier, `path' specifies the file) s -5 382 M -( system object \(e.g. file or directory\) whose attributes are to be) s -5 371 M -( modified, and `attrs' specifies the modifications to be made to its) s -5 360 M -( attributes. Attributes are discussed in more detail in Section) s -5 349 M -( ``File Attributes''.) s -5 327 M -( An error will be returned if the specified file system object does) s -5 316 M -( not exist or the user does not have sufficient rights to modify the) s -5 305 M -( specified attributes. The server responds to this request with a) s -5 294 M -( SSH_FXP_STATUS message.) s -5 272 M -( The SSH_FXP_FSETSTAT request modifies the attributes of a file which) s -5 261 M -( is already open. It has the following format:) s -5 239 M -( uint32 id) s -5 228 M -( string handle) s -5 217 M -( ATTRS attrs) s -5 195 M -( where `id' is the request identifier, `handle' \(MUST be returned by) s -5 184 M -( SSH_FXP_OPEN\) identifies the file whose attributes are to be) s -5 173 M -( modified, and `attrs' specifies the modifications to be made to its) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 17]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 18 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( attributes. Attributes are discussed in more detail in Section) s -5 679 M -( ``File Attributes''. The server will respond to this request with) s -5 668 M -( SSH_FXP_STATUS.) s -5 646 M -(6.10 Dealing with Symbolic links) s -5 624 M -( The SSH_FXP_READLINK request may be used to read the target of a) s -5 613 M -( symbolic link. It would have a data part as follows:) s -5 591 M -( uint32 id) s -5 580 M -( string path) s -5 558 M -( where `id' is the request identifier and `path' specifies the path) s -5 547 M -( name of the symlink to be read.) s -5 525 M -( The server will respond with a SSH_FXP_NAME packet containing only) s -5 514 M -( one name and a dummy attributes value. The name in the returned) s -5 503 M -( packet contains the target of the link. If an error occurs, the) s -5 492 M -( server may respond with SSH_FXP_STATUS.) s -5 470 M -( The SSH_FXP_SYMLINK request will create a symbolic link on the) s -5 459 M -( server. It is of the following format) s -5 437 M -( uint32 id) s -5 426 M -( string linkpath) s -5 415 M -( string targetpath) s -5 393 M -( where `id' is the request identifier, `linkpath' specifies the path) s -5 382 M -( name of the symlink to be created and `targetpath' specifies the) s -5 371 M -( target of the symlink. The server shall respond with a) s -5 360 M -( SSH_FXP_STATUS indicating either success \(SSH_FX_OK\) or an error) s -5 349 M -( condition.) s -5 327 M -(6.11 Canonicalizing the Server-Side Path Name) s -5 305 M -( The SSH_FXP_REALPATH request can be used to have the server) s -5 294 M -( canonicalize any given path name to an absolute path. This is useful) s -5 283 M -( for converting path names containing ".." components or relative) s -5 272 M -( pathnames without a leading slash into absolute paths. The format of) s -5 261 M -( the request is as follows:) s -5 239 M -( uint32 id) s -5 228 M -( string path) s -5 206 M -( where `id' is the request identifier and `path' specifies the path) s -5 195 M -( name to be canonicalized. The server will respond with a) s -5 184 M -( SSH_FXP_NAME packet containing only one name and a dummy attributes) s -5 173 M -( value. The name is the returned packet will be in canonical form.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 18]) s -_R -S -PStoPSsaved restore -%%Page: (18,19) 10 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 19 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( If an error occurs, the server may also respond with SSH_FXP_STATUS.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 19]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 20 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(7. Responses from the Server to the Client) s -5 668 M -( The server responds to the client using one of a few response) s -5 657 M -( packets. All requests can return a SSH_FXP_STATUS response upon) s -5 646 M -( failure. When the operation is successful, any of the responses may) s -5 635 M -( be returned \(depending on the operation\). If no data needs to be) s -5 624 M -( returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK) s -5 613 M -( status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used) s -5 602 M -( to return a file handle \(for SSH_FXP_OPEN and SSH_FXP_OPENDIR) s -5 591 M -( requests\), SSH_FXP_DATA is used to return data from SSH_FXP_READ,) s -5 580 M -( SSH_FXP_NAME is used to return one or more file names from a) s -5 569 M -( SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is) s -5 558 M -( used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and) s -5 547 M -( SSH_FXP_FSTAT requests.) s -5 525 M -( Exactly one response will be returned for each request. Each) s -5 514 M -( response packet contains a request identifier which can be used to) s -5 503 M -( match each response with the corresponding request. Note that it is) s -5 492 M -( legal to have several requests outstanding simultaneously, and the) s -5 481 M -( server is allowed to send responses to them in a different order from) s -5 470 M -( the order in which the requests were sent \(the result of their) s -5 459 M -( execution, however, is guaranteed to be as if they had been processed) s -5 448 M -( one at a time in the order in which the requests were sent\).) s -5 426 M -( Response packets are of the same general format as request packets.) s -5 415 M -( Each response packet begins with the request identifier.) s -5 393 M -( The format of the data portion of the SSH_FXP_STATUS response is as) s -5 382 M -( follows:) s -5 360 M -( uint32 id) s -5 349 M -( uint32 error/status code) s -5 338 M -( string error message \(ISO-10646 UTF-8 [RFC-2279]\)) s -5 327 M -( string language tag \(as defined in [RFC-1766]\)) s -5 305 M -( where `id' is the request identifier, and `error/status code') s -5 294 M -( indicates the result of the requested operation. The value SSH_FX_OK) s -5 283 M -( indicates success, and all other values indicate failure.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 20]) s -_R -S -PStoPSsaved restore -%%Page: (20,21) 11 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 21 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( Currently, the following values are defined \(other values may be) s -5 679 M -( defined by future versions of this protocol\):) s -5 657 M -( #define SSH_FX_OK 0) s -5 646 M -( #define SSH_FX_EOF 1) s -5 635 M -( #define SSH_FX_NO_SUCH_FILE 2) s -5 624 M -( #define SSH_FX_PERMISSION_DENIED 3) s -5 613 M -( #define SSH_FX_FAILURE 4) s -5 602 M -( #define SSH_FX_BAD_MESSAGE 5) s -5 591 M -( #define SSH_FX_NO_CONNECTION 6) s -5 580 M -( #define SSH_FX_CONNECTION_LOST 7) s -5 569 M -( #define SSH_FX_OP_UNSUPPORTED 8) s -5 547 M -( SSH_FX_OK) s -5 536 M -( Indicates successful completion of the operation.) s -5 514 M -( SSH_FX_EOF) s -5 503 M -( indicates end-of-file condition; for SSH_FX_READ it means that no) s -5 492 M -( more data is available in the file, and for SSH_FX_READDIR it) s -5 481 M -( indicates that no more files are contained in the directory.) s -5 459 M -( SSH_FX_NO_SUCH_FILE) s -5 448 M -( is returned when a reference is made to a file which should exist) s -5 437 M -( but doesn't.) s -5 415 M -( SSH_FX_PERMISSION_DENIED) s -5 404 M -( is returned when the authenticated user does not have sufficient) s -5 393 M -( permissions to perform the operation.) s -5 371 M -( SSH_FX_FAILURE) s -5 360 M -( is a generic catch-all error message; it should be returned if an) s -5 349 M -( error occurs for which there is no more specific error code) s -5 338 M -( defined.) s -5 316 M -( SSH_FX_BAD_MESSAGE) s -5 305 M -( may be returned if a badly formatted packet or protocol) s -5 294 M -( incompatibility is detected.) s -5 272 M -( SSH_FX_NO_CONNECTION) s -5 261 M -( is a pseudo-error which indicates that the client has no) s -5 250 M -( connection to the server \(it can only be generated locally by the) s -5 239 M -( client, and MUST NOT be returned by servers\).) s -5 217 M -( SSH_FX_CONNECTION_LOST) s -5 206 M -( is a pseudo-error which indicates that the connection to the) s -5 195 M -( server has been lost \(it can only be generated locally by the) s -5 184 M -( client, and MUST NOT be returned by servers\).) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 21]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 22 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( SSH_FX_OP_UNSUPPORTED) s -5 679 M -( indicates that an attempt was made to perform an operation which) s -5 668 M -( is not supported for the server \(it may be generated locally by) s -5 657 M -( the client if e.g. the version number exchange indicates that a) s -5 646 M -( required feature is not supported by the server, or it may be) s -5 635 M -( returned by the server if the server does not implement an) s -5 624 M -( operation\).) s -5 602 M -( The SSH_FXP_HANDLE response has the following format:) s -5 580 M -( uint32 id) s -5 569 M -( string handle) s -5 547 M -( where `id' is the request identifier, and `handle' is an arbitrary) s -5 536 M -( string that identifies an open file or directory on the server. The) s -5 525 M -( handle is opaque to the client; the client MUST NOT attempt to) s -5 514 M -( interpret or modify it in any way. The length of the handle string) s -5 503 M -( MUST NOT exceed 256 data bytes.) s -5 481 M -( The SSH_FXP_DATA response has the following format:) s -5 459 M -( uint32 id) s -5 448 M -( string data) s -5 426 M -( where `id' is the request identifier, and `data' is an arbitrary byte) s -5 415 M -( string containing the requested data. The data string may be at most) s -5 404 M -( the number of bytes requested in a SSH_FXP_READ request, but may also) s -5 393 M -( be shorter if end of file is reached or if the read is from something) s -5 382 M -( other than a regular file.) s -5 360 M -( The SSH_FXP_NAME response has the following format:) s -5 338 M -( uint32 id) s -5 327 M -( uint32 count) s -5 316 M -( repeats count times:) s -5 305 M -( string filename) s -5 294 M -( string longname) s -5 283 M -( ATTRS attrs) s -5 261 M -( where `id' is the request identifier, `count' is the number of names) s -5 250 M -( returned in this response, and the remaining fields repeat `count') s -5 239 M -( times \(so that all three fields are first included for the first) s -5 228 M -( file, then for the second file, etc\). In the repeated part,) s -5 217 M -( `filename' is a file name being returned \(for SSH_FXP_READDIR, it) s -5 206 M -( will be a relative name within the directory, without any path) s -5 195 M -( components; for SSH_FXP_REALPATH it will be an absolute path name\),) s -5 184 M -( `longname' is an expanded format for the file name, similar to what) s -5 173 M -( is returned by "ls -l" on Unix systems, and `attrs' is the attributes) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 22]) s -_R -S -PStoPSsaved restore -%%Page: (22,23) 12 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 23 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -( of the file as described in Section ``File Attributes''.) s -5 668 M -( The format of the `longname' field is unspecified by this protocol.) s -5 657 M -( It MUST be suitable for use in the output of a directory listing) s -5 646 M -( command \(in fact, the recommended operation for a directory listing) s -5 635 M -( command is to simply display this data\). However, clients SHOULD NOT) s -5 624 M -( attempt to parse the longname field for file attributes; they SHOULD) s -5 613 M -( use the attrs field instead.) s -5 591 M -( The recommended format for the longname field is as follows:) s -5 569 M -( -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer) s -5 558 M -( 1234567890 123 12345678 12345678 12345678 123456789012) s -5 536 M -( Here, the first line is sample output, and the second field indicates) s -5 525 M -( widths of the various fields. Fields are separated by spaces. The) s -5 514 M -( first field lists file permissions for user, group, and others; the) s -5 503 M -( second field is link count; the third field is the name of the user) s -5 492 M -( who owns the file; the fourth field is the name of the group that) s -5 481 M -( owns the file; the fifth field is the size of the file in bytes; the) s -5 470 M -( sixth field \(which actually may contain spaces, but is fixed to 12) s -5 459 M -( characters\) is the file modification time, and the seventh field is) s -5 448 M -( the file name. Each field is specified to be a minimum of certain) s -5 437 M -( number of character positions \(indicated by the second line above\),) s -5 426 M -( but may also be longer if the data does not fit in the specified) s -5 415 M -( length.) s -5 393 M -( The SSH_FXP_ATTRS response has the following format:) s -5 371 M -( uint32 id) s -5 360 M -( ATTRS attrs) s -5 338 M -( where `id' is the request identifier, and `attrs' is the returned) s -5 327 M -( file attributes as described in Section ``File Attributes''.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 23]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 24 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(8. Vendor-Specific Extensions) s -5 668 M -( The SSH_FXP_EXTENDED request provides a generic extension mechanism) s -5 657 M -( for adding vendor-specific commands. The request has the following) s -5 646 M -( format:) s -5 624 M -( uint32 id) s -5 613 M -( string extended-request) s -5 602 M -( ... any request-specific data ...) s -5 580 M -( where `id' is the request identifier, and `extended-request' is a) s -5 569 M -( string of the format "name@domain", where domain is an internet) s -5 558 M -( domain name of the vendor defining the request. The rest of the) s -5 547 M -( request is completely vendor-specific, and servers should only) s -5 536 M -( attempt to interpret it if they recognize the `extended-request') s -5 525 M -( name.) s -5 503 M -( The server may respond to such requests using any of the response) s -5 492 M -( packets defined in Section ``Responses from the Server to the) s -5 481 M -( Client''. Additionally, the server may also respond with a) s -5 470 M -( SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does) s -5 459 M -( not recognize the `extended-request' name, then the server MUST) s -5 448 M -( respond with SSH_FXP_STATUS with error/status set to) s -5 437 M -( SSH_FX_OP_UNSUPPORTED.) s -5 415 M -( The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary) s -5 404 M -( extension-specific data from the server to the client. It is of the) s -5 393 M -( following format:) s -5 371 M -( uint32 id) s -5 360 M -( ... any request-specific data ...) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 24]) s -_R -S -PStoPSsaved restore -%%Page: (24,25) 13 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 25 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(9. Security Considerations) s -5 668 M -( This protocol assumes that it is run over a secure channel and that) s -5 657 M -( the endpoints of the channel have been authenticated. Thus, this) s -5 646 M -( protocol assumes that it is externally protected from network-level) s -5 635 M -( attacks.) s -5 613 M -( This protocol provides file system access to arbitrary files on the) s -5 602 M -( server \(only constrained by the server implementation\). It is the) s -5 591 M -( responsibility of the server implementation to enforce any access) s -5 580 M -( controls that may be required to limit the access allowed for any) s -5 569 M -( particular user \(the user being authenticated externally to this) s -5 558 M -( protocol, typically using the SSH User Authentication Protocol [6].) s -5 536 M -( Care must be taken in the server implementation to check the validity) s -5 525 M -( of received file handle strings. The server should not rely on them) s -5 514 M -( directly; it MUST check the validity of each handle before relying on) s -5 503 M -( it.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 25]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 26 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(10. Changes from previous protocol versions) s -5 668 M -( The SSH File Transfer Protocol has changed over time, before it's) s -5 657 M -( standardization. The following is a description of the incompatible) s -5 646 M -( changes between different versions.) s -5 624 M -(10.1 Changes between versions 3 and 2) s -5 602 M -( o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.) s -5 580 M -( o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were) s -5 569 M -( added.) s -5 547 M -( o The SSH_FXP_STATUS message was changed to include fields `error) s -5 536 M -( message' and `language tag'.) s -5 503 M -(10.2 Changes between versions 2 and 1) s -5 481 M -( o The SSH_FXP_RENAME message was added.) s -5 448 M -(10.3 Changes between versions 1 and 0) s -5 426 M -( o Implementation changes, no actual protocol changes.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 26]) s -_R -S -PStoPSsaved restore -%%Page: (26,27) 14 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 27 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(11. Trademark Issues) s -5 668 M -( "ssh" is a registered trademark of SSH Communications Security Corp) s -5 657 M -( in the United States and/or other countries.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 27]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 28 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(References) s -5 668 M -( [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and) s -5 657 M -( P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January) s -5 646 M -( 1999.) s -5 624 M -( [2] Institute of Electrical and Electronics Engineers, "Information) s -5 613 M -( Technology - Portable Operating System Interface \(POSIX\) - Part) s -5 602 M -( 1: System Application Program Interface \(API\) [C Language]",) s -5 591 M -( IEEE Standard 1003.2, 1996.) s -5 569 M -( [3] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 558 M -( Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-) s -5 547 M -( architecture-09 \(work in progress\), July 2001.) s -5 525 M -( [4] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 514 M -( Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-) s -5 503 M -( architecture-09 \(work in progress\), July 2001.) s -5 481 M -( [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 470 M -( Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-11) s -5 459 M -( \(work in progress\), July 2001.) s -5 437 M -( [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 426 M -( Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-) s -5 415 M -( userauth-11 \(work in progress\), July 2001.) s -5 382 M -(Authors' Addresses) s -5 360 M -( Tatu Ylonen) s -5 349 M -( SSH Communications Security Corp) s -5 338 M -( Fredrikinkatu 42) s -5 327 M -( HELSINKI FIN-00100) s -5 316 M -( Finland) s -5 294 M -( EMail: ylo@ssh.com) s -5 261 M -( Sami Lehtinen) s -5 250 M -( SSH Communications Security Corp) s -5 239 M -( Fredrikinkatu 42) s -5 228 M -( HELSINKI FIN-00100) s -5 217 M -( Finland) s -5 195 M -( EMail: sjl@ssh.com) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 28]) s -_R -S -PStoPSsaved restore -%%Page: (28,29) 15 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 29 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2001) s -5 690 M -(Full Copyright Statement) s -5 668 M -( Copyright \(C\) The Internet Society \(2001\). All Rights Reserved.) s -5 646 M -( This document and translations of it may be copied and furnished to) s -5 635 M -( others, and derivative works that comment on or otherwise explain it) s -5 624 M -( or assist in its implementation may be prepared, copied, published) s -5 613 M -( and distributed, in whole or in part, without restriction of any) s -5 602 M -( kind, provided that the above copyright notice and this paragraph are) s -5 591 M -( included on all such copies and derivative works. However, this) s -5 580 M -( document itself may not be modified in any way, such as by removing) s -5 569 M -( the copyright notice or references to the Internet Society or other) s -5 558 M -( Internet organizations, except as needed for the purpose of) s -5 547 M -( developing Internet standards in which case the procedures for) s -5 536 M -( copyrights defined in the Internet Standards process must be) s -5 525 M -( followed, or as required to translate it into languages other than) s -5 514 M -( English.) s -5 492 M -( The limited permissions granted above are perpetual and will not be) s -5 481 M -( revoked by the Internet Society or its successors or assigns.) s -5 459 M -( This document and the information contained herein is provided on an) s -5 448 M -( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s -5 437 M -( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s -5 426 M -( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s -5 415 M -( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s -5 404 M -( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s -5 382 M -(Acknowledgement) s -5 360 M -( Funding for the RFC Editor function is currently provided by the) s -5 349 M -( Internet Society.) s -5 129 M -(Ylonen & Lehtinen Expires April 1, 2002 [Page 29]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 30 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -_R -S -PStoPSsaved restore -%%Trailer -%%Pages: 30 -%%DocumentNeededResources: font Courier-Bold Courier -%%EOF diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt deleted file mode 100644 index c4ec8c1125..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt +++ /dev/null @@ -1,1627 +0,0 @@ - - - -Network Working Group T. Ylonen -Internet-Draft S. Lehtinen -Expires: April 1, 2002 SSH Communications Security Corp - October 2001 - - - SSH File Transfer Protocol - draft-ietf-secsh-filexfer-02.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that - other groups may also distribute working documents as Internet- - Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on April 1, 2002. - -Copyright Notice - - Copyright (C) The Internet Society (2001). All Rights Reserved. - -Abstract - - The SSH File Transfer Protocol provides secure file transfer - functionality over any reliable data stream. It is the standard file - transfer protocol for use with the SSH2 protocol. This document - describes the file transfer protocol and its interface to the SSH2 - protocol suite. - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 1] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -Table of Contents - - 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. Use with the SSH Connection Protocol . . . . . . . . . . . . 4 - 3. General Packet Format . . . . . . . . . . . . . . . . . . . 5 - 4. Protocol Initialization . . . . . . . . . . . . . . . . . . 7 - 5. File Attributes . . . . . . . . . . . . . . . . . . . . . . 8 - 6. Requests From the Client to the Server . . . . . . . . . . . 10 - 6.1 Request Synchronization and Reordering . . . . . . . . . . . 10 - 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . . 11 - 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . . 11 - 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . . 13 - 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . . 14 - 6.6 Creating and Deleting Directories . . . . . . . . . . . . . 15 - 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . . 15 - 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . . 16 - 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . . 17 - 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . . 18 - 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . . 18 - 7. Responses from the Server to the Client . . . . . . . . . . 20 - 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . . 24 - 9. Security Considerations . . . . . . . . . . . . . . . . . . 25 - 10. Changes from previous protocol versions . . . . . . . . . . 26 - 10.1 Changes between versions 3 and 2 . . . . . . . . . . . . . . 26 - 10.2 Changes between versions 2 and 1 . . . . . . . . . . . . . . 26 - 10.3 Changes between versions 1 and 0 . . . . . . . . . . . . . . 26 - 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . . 27 - References . . . . . . . . . . . . . . . . . . . . . . . . . 28 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 28 - Full Copyright Statement . . . . . . . . . . . . . . . . . . 29 - - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 2] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -1. Introduction - - This protocol provides secure file transfer (and more generally file - system access) functionality over a reliable data stream, such as a - channel in the SSH2 protocol [3]. - - This protocol is designed so that it could be used to implement a - secure remote file system service, as well as a secure file transfer - service. - - This protocol assumes that it runs over a secure channel, and that - the server has already authenticated the user at the client end, and - that the identity of the client user is externally available to the - server implementation. - - In general, this protocol follows a simple request-response model. - Each request and response contains a sequence number and multiple - requests may be pending simultaneously. There are a relatively large - number of different request messages, but a small number of possible - response messages. Each request has one or more response messages - that may be returned in result (e.g., a read either returns data or - reports error status). - - The packet format descriptions in this specification follow the - notation presented in the secsh architecture draft.[3]. - - Even though this protocol is described in the context of the SSH2 - protocol, this protocol is general and independent of the rest of the - SSH2 protocol suite. It could be used in a number of different - applications, such as secure file transfer over TLS RFC 2246 [1] and - transfer of management information in VPN applications. - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 3] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -2. Use with the SSH Connection Protocol - - When used with the SSH2 Protocol suite, this protocol is intended to - be used from the SSH Connection Protocol [5] as a subsystem, as - described in section ``Starting a Shell or a Command''. The - subsystem name used with this protocol is "sftp". - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 4] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -3. General Packet Format - - All packets transmitted over the secure connection are of the - following format: - - uint32 length - byte type - byte[length - 1] data payload - - That is, they are just data preceded by 32-bit length and 8-bit type - fields. The `length' is the length of the data area, and does not - include the `length' field itself. The format and interpretation of - the data area depends on the packet type. - - All packet descriptions below only specify the packet type and the - data that goes into the data field. Thus, they should be prefixed by - the `length' and `type' fields. - - The maximum size of a packet is in practice determined by the client - (the maximum size of read or write requests that it sends, plus a few - bytes of packet overhead). All servers SHOULD support packets of at - least 34000 bytes (where the packet size refers to the full length, - including the header above). This should allow for reads and writes - of at most 32768 bytes. - - There is no limit on the number of outstanding (non-acknowledged) - requests that the client may send to the server. In practice this is - limited by the buffering available on the data stream and the queuing - performed by the server. If the server's queues are full, it should - not read any more data from the stream, and flow control will prevent - the client from sending more requests. Note, however, that while - there is no restriction on the protocol level, the client's API may - provide a limit in order to prevent infinite queuing of outgoing - requests at the client. - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 5] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - The following values are defined for packet types. - - #define SSH_FXP_INIT 1 - #define SSH_FXP_VERSION 2 - #define SSH_FXP_OPEN 3 - #define SSH_FXP_CLOSE 4 - #define SSH_FXP_READ 5 - #define SSH_FXP_WRITE 6 - #define SSH_FXP_LSTAT 7 - #define SSH_FXP_FSTAT 8 - #define SSH_FXP_SETSTAT 9 - #define SSH_FXP_FSETSTAT 10 - #define SSH_FXP_OPENDIR 11 - #define SSH_FXP_READDIR 12 - #define SSH_FXP_REMOVE 13 - #define SSH_FXP_MKDIR 14 - #define SSH_FXP_RMDIR 15 - #define SSH_FXP_REALPATH 16 - #define SSH_FXP_STAT 17 - #define SSH_FXP_RENAME 18 - #define SSH_FXP_READLINK 19 - #define SSH_FXP_SYMLINK 20 - #define SSH_FXP_STATUS 101 - #define SSH_FXP_HANDLE 102 - #define SSH_FXP_DATA 103 - #define SSH_FXP_NAME 104 - #define SSH_FXP_ATTRS 105 - #define SSH_FXP_EXTENDED 200 - #define SSH_FXP_EXTENDED_REPLY 201 - - Additional packet types should only be defined if the protocol - version number (see Section ``Protocol Initialization'') is - incremented, and their use MUST be negotiated using the version - number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY - packets can be used to implement vendor-specific extensions. See - Section ``Vendor-Specific-Extensions'' for more details. - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 6] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -4. Protocol Initialization - - When the file transfer protocol starts, it first sends a SSH_FXP_INIT - (including its version number) packet to the server. The server - responds with a SSH_FXP_VERSION packet, supplying the lowest of its - own and the client's version number. Both parties should from then - on adhere to particular version of the protocol. - - The SSH_FXP_INIT packet (from client to server) has the following - data: - - uint32 version - - - The SSH_FXP_VERSION packet (from server to client) has the following - data: - - uint32 version - - - The version number of the protocol specified in this document is 3. - The version number should be incremented for each incompatible - revision of this protocol. - - The extension data in the above packets may be empty, or may be a - sequence of - - string extension_name - string extension_data - - pairs (both strings MUST always be present if one is, but the - `extension_data' string may be of zero length). If present, these - strings indicate extensions to the baseline protocol. The - `extension_name' field(s) identify the name of the extension. The - name should be of the form "name@domain", where the domain is the DNS - domain name of the organization defining the extension. Additional - names that are not of this format may be defined later by the IETF. - Implementations MUST silently ignore any extensions whose name they - do not recognize. - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 7] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -5. File Attributes - - A new compound data type is defined for encoding file attributes. It - is basically just a combination of elementary types, but is defined - once because of the non-trivial description of the fields and to - ensure maintainability. - - The same encoding is used both when returning file attributes from - the server and when sending file attributes to the server. When - sending it to the server, the flags field specifies which attributes - are included, and the server will use default values for the - remaining attributes (or will not modify the values of remaining - attributes). When receiving attributes from the server, the flags - specify which attributes are included in the returned data. The - server normally returns all attributes it knows about. - - uint32 flags - uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE - uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID - uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID - uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS - uint32 atime present only if flag SSH_FILEXFER_ACMODTIME - uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME - uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED - string extended_type - string extended_data - ... more extended data (extended_type - extended_data pairs), - so that number of pairs equals extended_count - - The `flags' specify which of the fields are present. Those fields - for which the corresponding flag is not set are not present (not - included in the packet). New flags can only be added by incrementing - the protocol version number (or by using the extension mechanism - described below). - - The `size' field specifies the size of the file in bytes. - - The `uid' and `gid' fields contain numeric Unix-like user and group - identifiers, respectively. - - The `permissions' field contains a bit mask of file permissions as - defined by posix [1]. - - The `atime' and `mtime' contain the access and modification times of - the files, respectively. They are represented as seconds from Jan 1, - 1970 in UTC. - - The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 8] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - mechanism for vendor-specific extensions. If the flag is specified, - then the `extended_count' field is present. It specifies the number - of extended_type-extended_data pairs that follow. Each of these - pairs specifies an extended attribute. For each of the attributes, - the extended_type field should be a string of the format - "name@domain", where "domain" is a valid, registered domain name and - "name" identifies the method. The IETF may later standardize certain - names that deviate from this format (e.g., that do not contain the - "@" sign). The interpretation of `extended_data' depends on the - type. Implementations SHOULD ignore extended data fields that they - do not understand. - - Additional fields can be added to the attributes by either defining - additional bits to the flags field to indicate their presence, or by - defining extended attributes for them. The extended attributes - mechanism is recommended for most purposes; additional flags bits - should only be defined by an IETF standards action that also - increments the protocol version number. The use of such new fields - MUST be negotiated by the version number in the protocol exchange. - It is a protocol error if a packet with unsupported protocol bits is - received. - - The flags bits are defined to have the following values: - - #define SSH_FILEXFER_ATTR_SIZE 0x00000001 - #define SSH_FILEXFER_ATTR_UIDGID 0x00000002 - #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004 - #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008 - #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000 - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 9] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -6. Requests From the Client to the Server - - Requests from the client to the server represent the various file - system operations. Each request begins with an `id' field, which is - a 32-bit identifier identifying the request (selected by the client). - The same identifier will be returned in the response to the request. - One possible implementation of it is a monotonically increasing - request sequence number (modulo 2^32). - - Many operations in the protocol operate on open files. The - SSH_FXP_OPEN request can return a file handle (which is an opaque - variable-length string) which may be used to access the file later - (e.g. in a read operation). The client MUST NOT send requests the - server with bogus or closed handles. However, the server MUST - perform adequate checks on the handle in order to avoid security - risks due to fabricated handles. - - This design allows either stateful and stateless server - implementation, as well as an implementation which caches state - between requests but may also flush it. The contents of the file - handle string are entirely up to the server and its design. The - client should not modify or attempt to interpret the file handle - strings. - - The file handle strings MUST NOT be longer than 256 bytes. - -6.1 Request Synchronization and Reordering - - The protocol and implementations MUST process requests relating to - the same file in the order in which they are received. In other - words, if an application submits multiple requests to the server, the - results in the responses will be the same as if it had sent the - requests one at a time and waited for the response in each case. For - example, the server may process non-overlapping read/write requests - to the same file in parallel, but overlapping reads and writes cannot - be reordered or parallelized. However, there are no ordering - restrictions on the server for processing requests from two different - file transfer connections. The server may interleave and parallelize - them at will. - - There are no restrictions on the order in which responses to - outstanding requests are delivered to the client, except that the - server must ensure fairness in the sense that processing of no - request will be indefinitely delayed even if the client is sending - other requests so that there are multiple outstanding requests all - the time. - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 10] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -6.2 File Names - - This protocol represents file names as strings. File names are - assumed to use the slash ('/') character as a directory separator. - - File names starting with a slash are "absolute", and are relative to - the root of the file system. Names starting with any other character - are relative to the user's default directory (home directory). Note - that identifying the user is assumed to take place outside of this - protocol. - - Servers SHOULD interpret a path name component ".." as referring to - the parent directory, and "." as referring to the current directory. - If the server implementation limits access to certain parts of the - file system, it must be extra careful in parsing file names when - enforcing such restrictions. There have been numerous reported - security bugs where a ".." in a path name has allowed access outside - the intended area. - - An empty path name is valid, and it refers to the user's default - directory (usually the user's home directory). - - Otherwise, no syntax is defined for file names by this specification. - Clients should not make any other assumptions; however, they can - splice path name components returned by SSH_FXP_READDIR together - using a slash ('/') as the separator, and that will work as expected. - - It is understood that the lack of well-defined semantics for file - names may cause interoperability problems between clients and servers - using radically different operating systems. However, this approach - is known to work acceptably with most systems, and alternative - approaches that e.g. treat file names as sequences of structured - components are quite complicated. - -6.3 Opening, Creating, and Closing Files - - Files are opened and created using the SSH_FXP_OPEN message, whose - data part is as follows: - - uint32 id - string filename - uint32 pflags - ATTRS attrs - - The `id' field is the request identifier as for all requests. - - The `filename' field specifies the file name. See Section ``File - Names'' for more information. - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 11] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - The `pflags' field is a bitmask. The following bits have been - defined. - - #define SSH_FXF_READ 0x00000001 - #define SSH_FXF_WRITE 0x00000002 - #define SSH_FXF_APPEND 0x00000004 - #define SSH_FXF_CREAT 0x00000008 - #define SSH_FXF_TRUNC 0x00000010 - #define SSH_FXF_EXCL 0x00000020 - - These have the following meanings: - - SSH_FXF_READ - Open the file for reading. - - SSH_FXF_WRITE - Open the file for writing. If both this and SSH_FXF_READ are - specified, the file is opened for both reading and writing. - - SSH_FXF_APPEND - Force all writes to append data at the end of the file. - - SSH_FXF_CREAT - If this flag is specified, then a new file will be created if one - does not already exist (if O_TRUNC is specified, the new file will - be truncated to zero length if it previously exists). - - SSH_FXF_TRUNC - Forces an existing file with the same name to be truncated to zero - length when creating a file by specifying SSH_FXF_CREAT. - SSH_FXF_CREAT MUST also be specified if this flag is used. - - SSH_FXF_EXCL - Causes the request to fail if the named file already exists. - SSH_FXF_CREAT MUST also be specified if this flag is used. - - The `attrs' field specifies the initial attributes for the file. - Default values will be used for those attributes that are not - specified. See Section ``File Attributes'' for more information. - - Regardless the server operating system, the file will always be - opened in "binary" mode (i.e., no translations between different - character sets and newline encodings). - - The response to this message will be either SSH_FXP_HANDLE (if the - operation is successful) or SSH_FXP_STATUS (if the operation fails). - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 12] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - A file is closed by using the SSH_FXP_CLOSE request. Its data field - has the following format: - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is a handle - previously returned in the response to SSH_FXP_OPEN or - SSH_FXP_OPENDIR. The handle becomes invalid immediately after this - request has been sent. - - The response to this request will be a SSH_FXP_STATUS message. One - should note that on some server platforms even a close can fail. - This can happen e.g. if the server operating system caches writes, - and an error occurs while flushing cached writes during the close. - -6.4 Reading and Writing - - Once a file has been opened, it can be read using the SSH_FXP_READ - message, which has the following format: - - uint32 id - string handle - uint64 offset - uint32 len - - where `id' is the request identifier, `handle' is an open file handle - returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative - to the beginning of the file from where to start reading, and `len' - is the maximum number of bytes to read. - - In response to this request, the server will read as many bytes as it - can from the file (up to `len'), and return them in a SSH_FXP_DATA - message. If an error occurs or EOF is encountered before reading any - data, the server will respond with SSH_FXP_STATUS. For normal disk - files, it is guaranteed that this will read the specified number of - bytes, or up to end of file. For e.g. device files this may return - fewer bytes than requested. - - Writing to a file is achieved using the SSH_FXP_WRITE message, which - has the following format: - - uint32 id - string handle - uint64 offset - string data - - where `id' is a request identifier, `handle' is a file handle - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 13] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the - beginning of the file where to start writing, and `data' is the data - to be written. - - The write will extend the file if writing beyond the end of the file. - It is legal to write way beyond the end of the file; the semantics - are to write zeroes from the end of the file to the specified offset - and then the data. On most operating systems, such writes do not - allocate disk space but instead leave "holes" in the file. - - The server responds to a write request with a SSH_FXP_STATUS message. - -6.5 Removing and Renaming Files - - Files can be removed using the SSH_FXP_REMOVE message. It has the - following format: - - uint32 id - string filename - - where `id' is the request identifier and `filename' is the name of - the file to be removed. See Section ``File Names'' for more - information. This request cannot be used to remove directories. - - The server will respond to this request with a SSH_FXP_STATUS - message. - - Files (and directories) can be renamed using the SSH_FXP_RENAME - message. Its data is as follows: - - uint32 id - string oldpath - string newpath - - where `id' is the request identifier, `oldpath' is the name of an - existing file or directory, and `newpath' is the new name for the - file or directory. It is an error if there already exists a file - with the name specified by newpath. The server may also fail rename - requests in other situations, for example if `oldpath' and `newpath' - point to different file systems on the server. - - The server will respond to this request with a SSH_FXP_STATUS - message. - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 14] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -6.6 Creating and Deleting Directories - - New directories can be created using the SSH_FXP_MKDIR request. It - has the following format: - - uint32 id - string path - ATTRS attrs - - where `id' is the request identifier, `path' and `attrs' specifies - the modifications to be made to its attributes. See Section ``File - Names'' for more information on file names. Attributes are discussed - in more detail in Section ``File Attributes''. specifies the - directory to be created. An error will be returned if a file or - directory with the specified path already exists. The server will - respond to this request with a SSH_FXP_STATUS message. - - Directories can be removed using the SSH_FXP_RMDIR request, which - has the following format: - - uint32 id - string path - - where `id' is the request identifier, and `path' specifies the - directory to be removed. See Section ``File Names'' for more - information on file names. An error will be returned if no directory - with the specified path exists, or if the specified directory is not - empty, or if the path specified a file system object other than a - directory. The server responds to this request with a SSH_FXP_STATUS - message. - -6.7 Scanning Directories - - The files in a directory can be listed using the SSH_FXP_OPENDIR and - SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one - or more file names with full file attributes for each file. The - client should call SSH_FXP_READDIR repeatedly until it has found the - file it is looking for or until the server responds with a - SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if - there are no more files in the directory). The client should then - close the handle using the SSH_FXP_CLOSE request. - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 15] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - The SSH_FXP_OPENDIR opens a directory for reading. It has the - following format: - - uint32 id - string path - - where `id' is the request identifier and `path' is the path name of - the directory to be listed (without any trailing slash). See Section - ``File Names'' for more information on file names. This will return - an error if the path does not specify a directory or if the directory - is not readable. The server will respond to this request with either - a SSH_FXP_HANDLE or a SSH_FXP_STATUS message. - - Once the directory has been successfully opened, files (and - directories) contained in it can be listed using SSH_FXP_READDIR - requests. These are of the format - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is a handle - returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to - use an ordinary file handle returned by SSH_FXP_OPEN.) - - The server responds to this request with either a SSH_FXP_NAME or a - SSH_FXP_STATUS message. One or more names may be returned at a time. - Full status information is returned for each name in order to speed - up typical directory listings. - - When the client no longer wishes to read more names from the - directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle - should be closed regardless of whether an error has occurred or not. - -6.8 Retrieving File Attributes - - Very often, file attributes are automatically returned by - SSH_FXP_READDIR. However, sometimes there is need to specifically - retrieve the attributes for a named file. This can be done using the - SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests. - - SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT - follows symbolic links on the server, whereas SSH_FXP_LSTAT does not - follow symbolic links. Both have the same format: - - uint32 id - string path - - where `id' is the request identifier, and `path' specifies the file - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 16] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - system object for which status is to be returned. The server - responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS. - - SSH_FXP_FSTAT differs from the others in that it returns status - information for an open file (identified by the file handle). Its - format is as follows: - - uint32 id - string handle - - where `id' is the request identifier and `handle' is a file handle - returned by SSH_FXP_OPEN. The server responds to this request with - SSH_FXP_ATTRS or SSH_FXP_STATUS. - -6.9 Setting File Attributes - - File attributes may be modified using the SSH_FXP_SETSTAT and - SSH_FXP_FSETSTAT requests. These requests are used for operations - such as changing the ownership, permissions or access times, as well - as for truncating a file. - - The SSH_FXP_SETSTAT request is of the following format: - - uint32 id - string path - ATTRS attrs - - where `id' is the request identifier, `path' specifies the file - system object (e.g. file or directory) whose attributes are to be - modified, and `attrs' specifies the modifications to be made to its - attributes. Attributes are discussed in more detail in Section - ``File Attributes''. - - An error will be returned if the specified file system object does - not exist or the user does not have sufficient rights to modify the - specified attributes. The server responds to this request with a - SSH_FXP_STATUS message. - - The SSH_FXP_FSETSTAT request modifies the attributes of a file which - is already open. It has the following format: - - uint32 id - string handle - ATTRS attrs - - where `id' is the request identifier, `handle' (MUST be returned by - SSH_FXP_OPEN) identifies the file whose attributes are to be - modified, and `attrs' specifies the modifications to be made to its - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 17] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - attributes. Attributes are discussed in more detail in Section - ``File Attributes''. The server will respond to this request with - SSH_FXP_STATUS. - -6.10 Dealing with Symbolic links - - The SSH_FXP_READLINK request may be used to read the target of a - symbolic link. It would have a data part as follows: - - uint32 id - string path - - where `id' is the request identifier and `path' specifies the path - name of the symlink to be read. - - The server will respond with a SSH_FXP_NAME packet containing only - one name and a dummy attributes value. The name in the returned - packet contains the target of the link. If an error occurs, the - server may respond with SSH_FXP_STATUS. - - The SSH_FXP_SYMLINK request will create a symbolic link on the - server. It is of the following format - - uint32 id - string linkpath - string targetpath - - where `id' is the request identifier, `linkpath' specifies the path - name of the symlink to be created and `targetpath' specifies the - target of the symlink. The server shall respond with a - SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error - condition. - -6.11 Canonicalizing the Server-Side Path Name - - The SSH_FXP_REALPATH request can be used to have the server - canonicalize any given path name to an absolute path. This is useful - for converting path names containing ".." components or relative - pathnames without a leading slash into absolute paths. The format of - the request is as follows: - - uint32 id - string path - - where `id' is the request identifier and `path' specifies the path - name to be canonicalized. The server will respond with a - SSH_FXP_NAME packet containing only one name and a dummy attributes - value. The name is the returned packet will be in canonical form. - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 18] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - If an error occurs, the server may also respond with SSH_FXP_STATUS. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 19] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -7. Responses from the Server to the Client - - The server responds to the client using one of a few response - packets. All requests can return a SSH_FXP_STATUS response upon - failure. When the operation is successful, any of the responses may - be returned (depending on the operation). If no data needs to be - returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK - status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used - to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR - requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ, - SSH_FXP_NAME is used to return one or more file names from a - SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is - used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and - SSH_FXP_FSTAT requests. - - Exactly one response will be returned for each request. Each - response packet contains a request identifier which can be used to - match each response with the corresponding request. Note that it is - legal to have several requests outstanding simultaneously, and the - server is allowed to send responses to them in a different order from - the order in which the requests were sent (the result of their - execution, however, is guaranteed to be as if they had been processed - one at a time in the order in which the requests were sent). - - Response packets are of the same general format as request packets. - Each response packet begins with the request identifier. - - The format of the data portion of the SSH_FXP_STATUS response is as - follows: - - uint32 id - uint32 error/status code - string error message (ISO-10646 UTF-8 [RFC-2279]) - string language tag (as defined in [RFC-1766]) - - where `id' is the request identifier, and `error/status code' - indicates the result of the requested operation. The value SSH_FX_OK - indicates success, and all other values indicate failure. - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 20] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - Currently, the following values are defined (other values may be - defined by future versions of this protocol): - - #define SSH_FX_OK 0 - #define SSH_FX_EOF 1 - #define SSH_FX_NO_SUCH_FILE 2 - #define SSH_FX_PERMISSION_DENIED 3 - #define SSH_FX_FAILURE 4 - #define SSH_FX_BAD_MESSAGE 5 - #define SSH_FX_NO_CONNECTION 6 - #define SSH_FX_CONNECTION_LOST 7 - #define SSH_FX_OP_UNSUPPORTED 8 - - SSH_FX_OK - Indicates successful completion of the operation. - - SSH_FX_EOF - indicates end-of-file condition; for SSH_FX_READ it means that no - more data is available in the file, and for SSH_FX_READDIR it - indicates that no more files are contained in the directory. - - SSH_FX_NO_SUCH_FILE - is returned when a reference is made to a file which should exist - but doesn't. - - SSH_FX_PERMISSION_DENIED - is returned when the authenticated user does not have sufficient - permissions to perform the operation. - - SSH_FX_FAILURE - is a generic catch-all error message; it should be returned if an - error occurs for which there is no more specific error code - defined. - - SSH_FX_BAD_MESSAGE - may be returned if a badly formatted packet or protocol - incompatibility is detected. - - SSH_FX_NO_CONNECTION - is a pseudo-error which indicates that the client has no - connection to the server (it can only be generated locally by the - client, and MUST NOT be returned by servers). - - SSH_FX_CONNECTION_LOST - is a pseudo-error which indicates that the connection to the - server has been lost (it can only be generated locally by the - client, and MUST NOT be returned by servers). - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 21] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - SSH_FX_OP_UNSUPPORTED - indicates that an attempt was made to perform an operation which - is not supported for the server (it may be generated locally by - the client if e.g. the version number exchange indicates that a - required feature is not supported by the server, or it may be - returned by the server if the server does not implement an - operation). - - The SSH_FXP_HANDLE response has the following format: - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is an arbitrary - string that identifies an open file or directory on the server. The - handle is opaque to the client; the client MUST NOT attempt to - interpret or modify it in any way. The length of the handle string - MUST NOT exceed 256 data bytes. - - The SSH_FXP_DATA response has the following format: - - uint32 id - string data - - where `id' is the request identifier, and `data' is an arbitrary byte - string containing the requested data. The data string may be at most - the number of bytes requested in a SSH_FXP_READ request, but may also - be shorter if end of file is reached or if the read is from something - other than a regular file. - - The SSH_FXP_NAME response has the following format: - - uint32 id - uint32 count - repeats count times: - string filename - string longname - ATTRS attrs - - where `id' is the request identifier, `count' is the number of names - returned in this response, and the remaining fields repeat `count' - times (so that all three fields are first included for the first - file, then for the second file, etc). In the repeated part, - `filename' is a file name being returned (for SSH_FXP_READDIR, it - will be a relative name within the directory, without any path - components; for SSH_FXP_REALPATH it will be an absolute path name), - `longname' is an expanded format for the file name, similar to what - is returned by "ls -l" on Unix systems, and `attrs' is the attributes - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 22] - -Internet-Draft SSH File Transfer Protocol October 2001 - - - of the file as described in Section ``File Attributes''. - - The format of the `longname' field is unspecified by this protocol. - It MUST be suitable for use in the output of a directory listing - command (in fact, the recommended operation for a directory listing - command is to simply display this data). However, clients SHOULD NOT - attempt to parse the longname field for file attributes; they SHOULD - use the attrs field instead. - - The recommended format for the longname field is as follows: - - -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer - 1234567890 123 12345678 12345678 12345678 123456789012 - - Here, the first line is sample output, and the second field indicates - widths of the various fields. Fields are separated by spaces. The - first field lists file permissions for user, group, and others; the - second field is link count; the third field is the name of the user - who owns the file; the fourth field is the name of the group that - owns the file; the fifth field is the size of the file in bytes; the - sixth field (which actually may contain spaces, but is fixed to 12 - characters) is the file modification time, and the seventh field is - the file name. Each field is specified to be a minimum of certain - number of character positions (indicated by the second line above), - but may also be longer if the data does not fit in the specified - length. - - The SSH_FXP_ATTRS response has the following format: - - uint32 id - ATTRS attrs - - where `id' is the request identifier, and `attrs' is the returned - file attributes as described in Section ``File Attributes''. - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 23] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -8. Vendor-Specific Extensions - - The SSH_FXP_EXTENDED request provides a generic extension mechanism - for adding vendor-specific commands. The request has the following - format: - - uint32 id - string extended-request - ... any request-specific data ... - - where `id' is the request identifier, and `extended-request' is a - string of the format "name@domain", where domain is an internet - domain name of the vendor defining the request. The rest of the - request is completely vendor-specific, and servers should only - attempt to interpret it if they recognize the `extended-request' - name. - - The server may respond to such requests using any of the response - packets defined in Section ``Responses from the Server to the - Client''. Additionally, the server may also respond with a - SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does - not recognize the `extended-request' name, then the server MUST - respond with SSH_FXP_STATUS with error/status set to - SSH_FX_OP_UNSUPPORTED. - - The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary - extension-specific data from the server to the client. It is of the - following format: - - uint32 id - ... any request-specific data ... - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 24] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -9. Security Considerations - - This protocol assumes that it is run over a secure channel and that - the endpoints of the channel have been authenticated. Thus, this - protocol assumes that it is externally protected from network-level - attacks. - - This protocol provides file system access to arbitrary files on the - server (only constrained by the server implementation). It is the - responsibility of the server implementation to enforce any access - controls that may be required to limit the access allowed for any - particular user (the user being authenticated externally to this - protocol, typically using the SSH User Authentication Protocol [6]. - - Care must be taken in the server implementation to check the validity - of received file handle strings. The server should not rely on them - directly; it MUST check the validity of each handle before relying on - it. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 25] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -10. Changes from previous protocol versions - - The SSH File Transfer Protocol has changed over time, before it's - standardization. The following is a description of the incompatible - changes between different versions. - -10.1 Changes between versions 3 and 2 - - o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added. - - o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were - added. - - o The SSH_FXP_STATUS message was changed to include fields `error - message' and `language tag'. - - -10.2 Changes between versions 2 and 1 - - o The SSH_FXP_RENAME message was added. - - -10.3 Changes between versions 1 and 0 - - o Implementation changes, no actual protocol changes. - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 26] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -11. Trademark Issues - - "ssh" is a registered trademark of SSH Communications Security Corp - in the United States and/or other countries. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 27] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -References - - [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and - P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January - 1999. - - [2] Institute of Electrical and Electronics Engineers, "Information - Technology - Portable Operating System Interface (POSIX) - Part - 1: System Application Program Interface (API) [C Language]", - IEEE Standard 1003.2, 1996. - - [3] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh- - architecture-09 (work in progress), July 2001. - - [4] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh- - architecture-09 (work in progress), July 2001. - - [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-11 - (work in progress), July 2001. - - [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh- - userauth-11 (work in progress), July 2001. - - -Authors' Addresses - - Tatu Ylonen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: ylo@ssh.com - - - Sami Lehtinen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: sjl@ssh.com - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 28] - -Internet-Draft SSH File Transfer Protocol October 2001 - - -Full Copyright Statement - - Copyright (C) The Internet Society (2001). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Ylonen & Lehtinen Expires April 1, 2002 [Page 29] - - - diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps deleted file mode 100644 index 6a40cd6067..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps +++ /dev/null @@ -1,3511 +0,0 @@ -%!PS-Adobe-3.0 -%%BoundingBox: 75 0 595 747 -%%Title: Enscript Output -%%For: Magnus Thoang -%%Creator: GNU enscript 1.6.1 -%%CreationDate: Wed Nov 12 12:18:50 2003 -%%Orientation: Portrait -%%Pages: 18 0 -%%DocumentMedia: A4 595 842 0 () () -%%DocumentNeededResources: (atend) -%%EndComments -%%BeginProlog -%%BeginProcSet: PStoPS 1 15 -userdict begin -[/showpage/erasepage/copypage]{dup where{pop dup load - type/operatortype eq{1 array cvx dup 0 3 index cvx put - bind def}{pop}ifelse}{pop}ifelse}forall -[/letter/legal/executivepage/a4/a4small/b5/com10envelope - /monarchenvelope/c5envelope/dlenvelope/lettersmall/note - /folio/quarto/a5]{dup where{dup wcheck{exch{}put} - {pop{}def}ifelse}{pop}ifelse}forall -/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put} - {pop def}ifelse}{def}ifelse -/PStoPSmatrix matrix currentmatrix def -/PStoPSxform matrix def/PStoPSclip{clippath}def -/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def -/initmatrix{matrix defaultmatrix setmatrix}bind def -/initclip[{matrix currentmatrix PStoPSmatrix setmatrix - [{currentpoint}stopped{$error/newerror false put{newpath}} - {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse] - {[/newpath cvx{/moveto cvx}{/lineto cvx} - {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop} - stopped{$error/errorname get/invalidaccess eq{cleartomark - $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop - /initclip dup load dup type dup/operatortype eq{pop exch pop} - {dup/arraytype eq exch/packedarraytype eq or - {dup xcheck{exch pop aload pop}{pop cvx}ifelse} - {pop cvx}ifelse}ifelse - {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def -/initgraphics{initmatrix newpath initclip 1 setlinewidth - 0 setlinecap 0 setlinejoin []0 setdash 0 setgray - 10 setmiterlimit}bind def -end -%%EndProcSet -%%BeginResource: procset Enscript-Prolog 1.6 1 -% -% Procedures. -% - -/_S { % save current state - /_s save def -} def -/_R { % restore from saved state - _s restore -} def - -/S { % showpage protecting gstate - gsave - showpage - grestore -} bind def - -/MF { % fontname newfontname -> - make a new encoded font - /newfontname exch def - /fontname exch def - - /fontdict fontname findfont def - /newfont fontdict maxlength dict def - - fontdict { - exch - dup /FID eq { - % skip FID pair - pop pop - } { - % copy to the new font dictionary - exch newfont 3 1 roll put - } ifelse - } forall - - newfont /FontName newfontname put - - % insert only valid encoding vectors - encoding_vector length 256 eq { - newfont /Encoding encoding_vector put - } if - - newfontname newfont definefont pop -} def - -/SF { % fontname width height -> - set a new font - /height exch def - /width exch def - - findfont - [width 0 0 height 0 0] makefont setfont -} def - -/SUF { % fontname width height -> - set a new user font - /height exch def - /width exch def - - /F-gs-user-font MF - /F-gs-user-font width height SF -} def - -/M {moveto} bind def -/s {show} bind def - -/Box { % x y w h -> - define box path - /d_h exch def /d_w exch def /d_y exch def /d_x exch def - d_x d_y moveto - d_w 0 rlineto - 0 d_h rlineto - d_w neg 0 rlineto - closepath -} def - -/bgs { % x y height blskip gray str -> - show string with bg color - /str exch def - /gray exch def - /blskip exch def - /height exch def - /y exch def - /x exch def - - gsave - x y blskip sub str stringwidth pop height Box - gray setgray - fill - grestore - x y M str s -} def - -% Highlight bars. -/highlight_bars { % nlines lineheight output_y_margin gray -> - - gsave - setgray - /ymarg exch def - /lineheight exch def - /nlines exch def - - % This 2 is just a magic number to sync highlight lines to text. - 0 d_header_y ymarg sub 2 sub translate - - /cw d_output_w cols div def - /nrows d_output_h ymarg 2 mul sub lineheight div cvi def - - % for each column - 0 1 cols 1 sub { - cw mul /xp exch def - - % for each rows - 0 1 nrows 1 sub { - /rn exch def - rn lineheight mul neg /yp exch def - rn nlines idiv 2 mod 0 eq { - % Draw highlight bar. 4 is just a magic indentation. - xp 4 add yp cw 8 sub lineheight neg Box fill - } if - } for - } for - - grestore -} def - -% Line highlight bar. -/line_highlight { % x y width height gray -> - - gsave - /gray exch def - Box gray setgray fill - grestore -} def - -% Column separator lines. -/column_lines { - gsave - .1 setlinewidth - 0 d_footer_h translate - /cw d_output_w cols div def - 1 1 cols 1 sub { - cw mul 0 moveto - 0 d_output_h rlineto stroke - } for - grestore -} def - -% Column borders. -/column_borders { - gsave - .1 setlinewidth - 0 d_footer_h moveto - 0 d_output_h rlineto - d_output_w 0 rlineto - 0 d_output_h neg rlineto - closepath stroke - grestore -} def - -% Do the actual underlay drawing -/draw_underlay { - ul_style 0 eq { - ul_str true charpath stroke - } { - ul_str show - } ifelse -} def - -% Underlay -/underlay { % - -> - - gsave - 0 d_page_h translate - d_page_h neg d_page_w atan rotate - - ul_gray setgray - ul_font setfont - /dw d_page_h dup mul d_page_w dup mul add sqrt def - ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto - draw_underlay - grestore -} def - -/user_underlay { % - -> - - gsave - ul_x ul_y translate - ul_angle rotate - ul_gray setgray - ul_font setfont - 0 0 ul_h_ptsize 2 div sub moveto - draw_underlay - grestore -} def - -% Page prefeed -/page_prefeed { % bool -> - - statusdict /prefeed known { - statusdict exch /prefeed exch put - } { - pop - } ifelse -} def - -% Wrapped line markers -/wrapped_line_mark { % x y charwith charheight type -> - - /type exch def - /h exch def - /w exch def - /y exch def - /x exch def - - type 2 eq { - % Black boxes (like TeX does) - gsave - 0 setlinewidth - x w 4 div add y M - 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto - closepath fill - grestore - } { - type 3 eq { - % Small arrows - gsave - .2 setlinewidth - x w 2 div add y h 2 div add M - w 4 div 0 rlineto - x w 4 div add y lineto stroke - - x w 4 div add w 8 div add y h 4 div add M - x w 4 div add y lineto - w 4 div h 8 div rlineto stroke - grestore - } { - % do nothing - } ifelse - } ifelse -} def - -% EPSF import. - -/BeginEPSF { - /b4_Inc_state save def % Save state for cleanup - /dict_count countdictstack def % Count objects on dict stack - /op_count count 1 sub def % Count objects on operand stack - userdict begin - /showpage { } def - 0 setgray 0 setlinecap - 1 setlinewidth 0 setlinejoin - 10 setmiterlimit [ ] 0 setdash newpath - /languagelevel where { - pop languagelevel - 1 ne { - false setstrokeadjust false setoverprint - } if - } if -} bind def - -/EndEPSF { - count op_count sub { pos } repeat % Clean up stacks - countdictstack dict_count sub { end } repeat - b4_Inc_state restore -} bind def - -% Check PostScript language level. -/languagelevel where { - pop /gs_languagelevel languagelevel def -} { - /gs_languagelevel 1 def -} ifelse -%%EndResource -%%BeginResource: procset Enscript-Encoding-88591 1.6 1 -/encoding_vector [ -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclam /quotedbl /numbersign -/dollar /percent /ampersand /quoteright -/parenleft /parenright /asterisk /plus -/comma /hyphen /period /slash -/zero /one /two /three -/four /five /six /seven -/eight /nine /colon /semicolon -/less /equal /greater /question -/at /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 /bracketleft -/backslash /bracketright /asciicircum /underscore -/quoteleft /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 /braceleft -/bar /braceright /tilde /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclamdown /cent /sterling -/currency /yen /brokenbar /section -/dieresis /copyright /ordfeminine /guillemotleft -/logicalnot /hyphen /registered /macron -/degree /plusminus /twosuperior /threesuperior -/acute /mu /paragraph /bullet -/cedilla /onesuperior /ordmasculine /guillemotright -/onequarter /onehalf /threequarters /questiondown -/Agrave /Aacute /Acircumflex /Atilde -/Adieresis /Aring /AE /Ccedilla -/Egrave /Eacute /Ecircumflex /Edieresis -/Igrave /Iacute /Icircumflex /Idieresis -/Eth /Ntilde /Ograve /Oacute -/Ocircumflex /Otilde /Odieresis /multiply -/Oslash /Ugrave /Uacute /Ucircumflex -/Udieresis /Yacute /Thorn /germandbls -/agrave /aacute /acircumflex /atilde -/adieresis /aring /ae /ccedilla -/egrave /eacute /ecircumflex /edieresis -/igrave /iacute /icircumflex /idieresis -/eth /ntilde /ograve /oacute -/ocircumflex /otilde /odieresis /divide -/oslash /ugrave /uacute /ucircumflex -/udieresis /yacute /thorn /ydieresis -] def -%%EndResource -%%EndProlog -%%BeginSetup -%%IncludeResource: font Courier-Bold -%%IncludeResource: font Courier -/HFpt_w 10 def -/HFpt_h 10 def -/Courier-Bold /HF-gs-font MF -/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def -/Courier /F-gs-font MF -/F-gs-font 10 10 SF -/#copies 1 def -/d_page_w 520 def -/d_page_h 747 def -/d_header_x 0 def -/d_header_y 747 def -/d_header_w 520 def -/d_header_h 0 def -/d_footer_x 0 def -/d_footer_y 0 def -/d_footer_w 520 def -/d_footer_h 0 def -/d_output_w 520 def -/d_output_h 747 def -/cols 1 def -userdict/PStoPSxform PStoPSmatrix matrix currentmatrix - matrix invertmatrix matrix concatmatrix - matrix invertmatrix put -%%EndSetup -%%Page: (0,1) 1 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 1 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 701 M -(Secure Shell Working Group J. Galbraith) s -5 690 M -(Internet-Draft VanDyke Software) s -5 679 M -(Expires: April 16, 2003 T. Ylonen) s -5 668 M -( S. Lehtinen) s -5 657 M -( SSH Communications Security Corp) s -5 646 M -( October 16, 2002) s -5 613 M -( SSH File Transfer Protocol) s -5 602 M -( draft-ietf-secsh-filexfer-03.txt) s -5 580 M -(Status of this Memo) s -5 558 M -( This document is an Internet-Draft and is in full conformance with) s -5 547 M -( all provisions of Section 10 of RFC2026.) s -5 525 M -( Internet-Drafts are working documents of the Internet Engineering) s -5 514 M -( Task Force \(IETF\), its areas, and its working groups. Note that) s -5 503 M -( other groups may also distribute working documents as Internet-) s -5 492 M -( Drafts.) s -5 470 M -( Internet-Drafts are draft documents valid for a maximum of six months) s -5 459 M -( and may be updated, replaced, or obsoleted by other documents at any) s -5 448 M -( time. It is inappropriate to use Internet-Drafts as reference) s -5 437 M -( material or to cite them other than as "work in progress.") s -5 415 M -( The list of current Internet-Drafts can be accessed at http://) s -5 404 M -( www.ietf.org/ietf/1id-abstracts.txt.) s -5 382 M -( The list of Internet-Draft Shadow Directories can be accessed at) s -5 371 M -( http://www.ietf.org/shadow.html.) s -5 349 M -( This Internet-Draft will expire on April 16, 2003.) s -5 327 M -(Copyright Notice) s -5 305 M -( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s -5 283 M -(Abstract) s -5 261 M -( The SSH File Transfer Protocol provides secure file transfer) s -5 250 M -( functionality over any reliable data stream. It is the standard file) s -5 239 M -( transfer protocol for use with the SSH2 protocol. This document) s -5 228 M -( describes the file transfer protocol and its interface to the SSH2) s -5 217 M -( protocol suite.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 1]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 2 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(Table of Contents) s -5 668 M -( 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 657 M -( 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4) s -5 646 M -( 3. General Packet Format . . . . . . . . . . . . . . . . . . 5) s -5 635 M -( 4. Protocol Initialization . . . . . . . . . . . . . . . . . 7) s -5 624 M -( 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 7) s -5 613 M -( 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 7) s -5 602 M -( 4.3 Determining Server Newline Convention . . . . . . . . . . 8) s -5 591 M -( 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 9) s -5 580 M -( 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 9) s -5 569 M -( 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 10) s -5 558 M -( 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 10) s -5 547 M -( 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 10) s -5 536 M -( 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 11) s -5 525 M -( 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 11) s -5 514 M -( 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 11) s -5 503 M -( 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 12) s -5 492 M -( 6. Requests From the Client to the Server . . . . . . . . . . 13) s -5 481 M -( 6.1 Request Synchronization and Reordering . . . . . . . . . . 13) s -5 470 M -( 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 14) s -5 459 M -( 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 14) s -5 448 M -( 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 17) s -5 437 M -( 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 18) s -5 426 M -( 6.6 Creating and Deleting Directories . . . . . . . . . . . . 19) s -5 415 M -( 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 19) s -5 404 M -( 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 20) s -5 393 M -( 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 21) s -5 382 M -( 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 22) s -5 371 M -( 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 23) s -5 360 M -( 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 23) s -5 349 M -( 7. Responses from the Server to the Client . . . . . . . . . 24) s -5 338 M -( 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 28) s -5 327 M -( 9. Security Considerations . . . . . . . . . . . . . . . . . 29) s -5 316 M -( 10. Changes from previous protocol versions . . . . . . . . . 30) s -5 305 M -( 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 30) s -5 294 M -( 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 31) s -5 283 M -( 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 31) s -5 272 M -( 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 31) s -5 261 M -( 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 32) s -5 250 M -( References . . . . . . . . . . . . . . . . . . . . . . . . 33) s -5 239 M -( Authors' Addresses . . . . . . . . . . . . . . . . . . . . 33) s -5 228 M -( Full Copyright Statement . . . . . . . . . . . . . . . . . 35) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 2]) s -_R -S -PStoPSsaved restore -%%Page: (2,3) 2 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 3 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(1. Introduction) s -5 668 M -( This protocol provides secure file transfer \(and more generally file) s -5 657 M -( system access\) functionality over a reliable data stream, such as a) s -5 646 M -( channel in the SSH2 protocol [5].) s -5 624 M -( This protocol is designed so that it could be used to implement a) s -5 613 M -( secure remote file system service, as well as a secure file transfer) s -5 602 M -( service.) s -5 580 M -( This protocol assumes that it runs over a secure channel, and that) s -5 569 M -( the server has already authenticated the user at the client end, and) s -5 558 M -( that the identity of the client user is externally available to the) s -5 547 M -( server implementation.) s -5 525 M -( In general, this protocol follows a simple request-response model.) s -5 514 M -( Each request and response contains a sequence number and multiple) s -5 503 M -( requests may be pending simultaneously. There are a relatively large) s -5 492 M -( number of different request messages, but a small number of possible) s -5 481 M -( response messages. Each request has one or more response messages) s -5 470 M -( that may be returned in result \(e.g., a read either returns data or) s -5 459 M -( reports error status\).) s -5 437 M -( The packet format descriptions in this specification follow the) s -5 426 M -( notation presented in the secsh architecture draft. [5]) s -5 404 M -( Even though this protocol is described in the context of the SSH2) s -5 393 M -( protocol, this protocol is general and independent of the rest of the) s -5 382 M -( SSH2 protocol suite. It could be used in a number of different) s -5 371 M -( applications, such as secure file transfer over TLS RFC 2246 [1] and) s -5 360 M -( transfer of management information in VPN applications.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 3]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 4 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(2. Use with the SSH Connection Protocol) s -5 668 M -( When used with the SSH2 Protocol suite, this protocol is intended to) s -5 657 M -( be used from the SSH Connection Protocol [7] as a subsystem, as) s -5 646 M -( described in section ``Starting a Shell or a Command''. The) s -5 635 M -( subsystem name used with this protocol is "sftp".) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 4]) s -_R -S -PStoPSsaved restore -%%Page: (4,5) 3 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 5 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(3. General Packet Format) s -5 668 M -( All packets transmitted over the secure connection are of the) s -5 657 M -( following format:) s -5 635 M -( uint32 length) s -5 624 M -( byte type) s -5 613 M -( byte[length - 1] data payload) s -5 591 M -( That is, they are just data preceded by 32-bit length and 8-bit type) s -5 580 M -( fields. The `length' is the length of the data area, and does not) s -5 569 M -( include the `length' field itself. The format and interpretation of) s -5 558 M -( the data area depends on the packet type.) s -5 536 M -( All packet descriptions below only specify the packet type and the) s -5 525 M -( data that goes into the data field. Thus, they should be prefixed by) s -5 514 M -( the `length' and `type' fields.) s -5 492 M -( The maximum size of a packet is in practice determined by the client) s -5 481 M -( \(the maximum size of read or write requests that it sends, plus a few) s -5 470 M -( bytes of packet overhead\). All servers SHOULD support packets of at) s -5 459 M -( least 34000 bytes \(where the packet size refers to the full length,) s -5 448 M -( including the header above\). This should allow for reads and writes) s -5 437 M -( of at most 32768 bytes.) s -5 415 M -( There is no limit on the number of outstanding \(non-acknowledged\)) s -5 404 M -( requests that the client may send to the server. In practice this is) s -5 393 M -( limited by the buffering available on the data stream and the queuing) s -5 382 M -( performed by the server. If the server's queues are full, it should) s -5 371 M -( not read any more data from the stream, and flow control will prevent) s -5 360 M -( the client from sending more requests. Note, however, that while) s -5 349 M -( there is no restriction on the protocol level, the client's API may) s -5 338 M -( provide a limit in order to prevent infinite queuing of outgoing) s -5 327 M -( requests at the client.) s -5 305 M -( The following values are defined for packet types.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 5]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 6 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( #define SSH_FXP_INIT 1) s -5 679 M -( #define SSH_FXP_VERSION 2) s -5 668 M -( #define SSH_FXP_OPEN 3) s -5 657 M -( #define SSH_FXP_CLOSE 4) s -5 646 M -( #define SSH_FXP_READ 5) s -5 635 M -( #define SSH_FXP_WRITE 6) s -5 624 M -( #define SSH_FXP_LSTAT 7) s -5 613 M -( #define SSH_FXP_FSTAT 8) s -5 602 M -( #define SSH_FXP_SETSTAT 9) s -5 591 M -( #define SSH_FXP_FSETSTAT 10) s -5 580 M -( #define SSH_FXP_OPENDIR 11) s -5 569 M -( #define SSH_FXP_READDIR 12) s -5 558 M -( #define SSH_FXP_REMOVE 13) s -5 547 M -( #define SSH_FXP_MKDIR 14) s -5 536 M -( #define SSH_FXP_RMDIR 15) s -5 525 M -( #define SSH_FXP_REALPATH 16) s -5 514 M -( #define SSH_FXP_STAT 17) s -5 503 M -( #define SSH_FXP_RENAME 18) s -5 492 M -( #define SSH_FXP_READLINK 19) s -5 481 M -( #define SSH_FXP_SYMLINK 20) s -5 459 M -( #define SSH_FXP_STATUS 101) s -5 448 M -( #define SSH_FXP_HANDLE 102) s -5 437 M -( #define SSH_FXP_DATA 103) s -5 426 M -( #define SSH_FXP_NAME 104) s -5 415 M -( #define SSH_FXP_ATTRS 105) s -5 393 M -( #define SSH_FXP_EXTENDED 200) s -5 382 M -( #define SSH_FXP_EXTENDED_REPLY 201) s -5 360 M -( RESERVED_FOR_EXTENSIONS 210-255) s -5 338 M -( Additional packet types should only be defined if the protocol) s -5 327 M -( version number \(see Section ``Protocol Initialization''\) is) s -5 316 M -( incremented, and their use MUST be negotiated using the version) s -5 305 M -( number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY) s -5 294 M -( packets can be used to implement vendor-specific extensions. See) s -5 283 M -( Section ``Vendor-Specific-Extensions'' for more details.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 6]) s -_R -S -PStoPSsaved restore -%%Page: (6,7) 4 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 7 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(4. Protocol Initialization) s -5 668 M -( When the file transfer protocol starts, the client first sends a) s -5 657 M -( SSH_FXP_INIT \(including its version number\) packet to the server.) s -5 646 M -( The server responds with a SSH_FXP_VERSION packet, supplying the) s -5 635 M -( lowest of its own and the client's version number. Both parties) s -5 624 M -( should from then on adhere to particular version of the protocol.) s -5 602 M -( The version number of the protocol specified in this document is 4.) s -5 591 M -( The version number should be incremented for each incompatible) s -5 580 M -( revision of this protocol.) s -5 558 M -(4.1 Client Initialization) s -5 536 M -( The SSH_FXP_INIT packet \(from client to server\) has the following) s -5 525 M -( data:) s -5 503 M -( uint32 version) s -5 481 M -( Version 3 of this protocol allowed clients to include extensions in) s -5 470 M -( the SSH_FXP_INIT packet; however, this can cause interoperability) s -5 459 M -( problems with version 1 and version 2 servers because the client must) s -5 448 M -( send this packet before knowing the servers version.) s -5 426 M -( In this version of the protocol, clients MUST use the) s -5 415 M -( SSH_FXP_EXTENDED packet to send extensions to the server after) s -5 404 M -( version exchange has completed. Clients MUST NOT include extensions) s -5 393 M -( in the version packet. This will prevent interoperability problems) s -5 382 M -( with older servers) s -5 360 M -(4.2 Server Initialization) s -5 338 M -( The SSH_FXP_VERSION packet \(from server to client\) has the following) s -5 327 M -( data:) s -5 305 M -( uint32 version) s -5 294 M -( ) s -5 272 M -( 'version' is the lower of the protocol version supported by the) s -5 261 M -( server and the version number received from the client.) s -5 239 M -( The extension data may be empty, or may be a sequence of) s -5 217 M -( string extension_name) s -5 206 M -( string extension_data) s -5 184 M -( pairs \(both strings MUST always be present if one is, but the) s -5 173 M -( `extension_data' string may be of zero length\). If present, these) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 7]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 8 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( strings indicate extensions to the baseline protocol. The) s -5 679 M -( `extension_name' field\(s\) identify the name of the extension. The) s -5 668 M -( name should be of the form "name@domain", where the domain is the DNS) s -5 657 M -( domain name of the organization defining the extension. Additional) s -5 646 M -( names that are not of this format may be defined later by the IETF.) s -5 635 M -( Implementations MUST silently ignore any extensions whose name they) s -5 624 M -( do not recognize.) s -5 602 M -(4.3 Determining Server Newline Convention) s -5 580 M -( In order to correctly process text files in a cross platform) s -5 569 M -( compatible way, the newline convention must be converted from that of) s -5 558 M -( the server to that of the client, or, during an upload, from that of) s -5 547 M -( the client to that of the server.) s -5 525 M -( Versions 3 and prior of this protocol made no provisions for) s -5 514 M -( processing text files. Many clients implemented some sort of) s -5 503 M -( conversion algorithm, but without either a 'canonical' on the wire) s -5 492 M -( format or knowledge of the servers newline convention, correct) s -5 481 M -( conversion was not always possible.) s -5 459 M -( Starting with Version 4, the SSH_FXF_TEXT file open flag \(Section) s -5 448 M -( 6.3\) makes it possible to request that the server translate a file to) s -5 437 M -( a 'canonical' on the wire format. This format uses \\r\\n as the line) s -5 426 M -( separator.) s -5 404 M -( Servers for systems using multiple newline characters \(for example,) s -5 393 M -( Mac OS X or VMS\) or systems using counted records, MUST translate to) s -5 382 M -( the canonical form.) s -5 360 M -( However, to ease the burden of implementation on servers that use a) s -5 349 M -( single, simple separator sequence, the following extension allows the) s -5 338 M -( canonical format to be changed.) s -5 316 M -( string "newline") s -5 305 M -( string new-canonical-separator \(usually "\\r" or "\\n" or "\\r\\n"\)) s -5 283 M -( All clients MUST support this extension.) s -5 261 M -( When processing text files, clients SHOULD NOT translate any) s -5 250 M -( character or sequence that is not an exact match of the servers) s -5 239 M -( newline separator.) s -5 217 M -( In particular, if the newline sequence being used is the canonical) s -5 206 M -( "\\r\\n" sequence, a lone \\r or a lone \\n SHOULD be written through) s -5 195 M -( without change.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 8]) s -_R -S -PStoPSsaved restore -%%Page: (8,9) 5 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 9 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(5. File Attributes) s -5 668 M -( A new compound data type is defined for encoding file attributes.) s -5 657 M -( The same encoding is used both when returning file attributes from) s -5 646 M -( the server and when sending file attributes to the server. When) s -5 635 M -( sending it to the server, the flags field specifies which attributes) s -5 624 M -( are included, and the server will use default values for the) s -5 613 M -( remaining attributes \(or will not modify the values of remaining) s -5 602 M -( attributes\). When receiving attributes from the server, the flags) s -5 591 M -( specify which attributes are included in the returned data. The) s -5 580 M -( server normally returns all attributes it knows about.) s -5 558 M -( uint32 flags) s -5 547 M -( byte type always present) s -5 536 M -( uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE) s -5 525 M -( string owner present only if flag SSH_FILEXFER_ATTR_OWNERGROUP) s -5 514 M -( string group present only if flag SSH_FILEXFER_ATTR_OWNERGROUP) s -5 503 M -( uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS) s -5 492 M -( uint32 atime present only if flag SSH_FILEXFER_ATTR_ACCESSTIME) s -5 481 M -( uint32 createtime present only if flag SSH_FILEXFER_ATTR_CREATETIME) s -5 470 M -( uint32 mtime present only if flag SSH_FILEXFER_ATTR_MODIFYTIME) s -5 459 M -( string acl present only if flag SSH_FILEXFER_ATTR_ACL) s -5 448 M -( uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED) s -5 437 M -( string extended_type) s -5 426 M -( string extended_data) s -5 415 M -( ... more extended data \(extended_type - extended_data pairs\),) s -5 404 M -( so that number of pairs equals extended_count) s -5 371 M -(5.1 Flags) s -5 349 M -( The `flags' specify which of the fields are present. Those fields) s -5 338 M -( for which the corresponding flag is not set are not present \(not) s -5 327 M -( included in the packet\). New flags can only be added by incrementing) s -5 316 M -( the protocol version number \(or by using the extension mechanism) s -5 305 M -( described below\).) s -5 283 M -( The flags bits are defined to have the following values:) s -5 261 M -( #define SSH_FILEXFER_ATTR_SIZE 0x00000001) s -5 250 M -( #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004) s -5 239 M -( #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008) s -5 228 M -( #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010) s -5 217 M -( #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020) s -5 206 M -( #define SSH_FILEXFER_ATTR_ACL 0x00000040) s -5 195 M -( #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080) s -5 184 M -( #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 9]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 10 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( In previous versions of this protocol flags value 0x00000002 was) s -5 679 M -( SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP) s -5 668 M -( was given a new value in order to ease implementation burden.) s -5 657 M -( 0x00000002 MUST NOT appear in the mask. Some future version of this) s -5 646 M -( protocol may reuse flag 0x00000002.) s -5 624 M -(5.2 Type) s -5 602 M -( The type field is always present. The following types are defined:) s -5 580 M -( #define SSH_FILEXFER_TYPE_REGULAR 1) s -5 569 M -( #define SSH_FILEXFER_TYPE_DIRECTORY 2) s -5 558 M -( #define SSH_FILEXFER_TYPE_SYMLINK 3) s -5 547 M -( #define SSH_FILEXFER_TYPE_SPECIAL 4) s -5 536 M -( #define SSH_FILEXFER_TYPE_UNKNOWN 5) s -5 514 M -( On a POSIX system, these values would be derived from the permission) s -5 503 M -( field.) s -5 481 M -(5.3 Size) s -5 459 M -( The `size' field specifies the size of the file on disk, in bytes.) s -5 448 M -( If it is present during file creation, it should be considered a hint) s -5 437 M -( as to the files eventual size.) s -5 415 M -( Files opened with the SSH_FXF_TEXT flag may have a size that is) s -5 404 M -( greater or less than the value of the size field.) s -5 382 M -(5.4 Owner and Group) s -5 360 M -( The `owner' and `group' fields are represented as UTF-8 strings; this) s -5 349 M -( is the form used by NFS v4. See NFS version 4 Protocol. [3] The) s -5 338 M -( following text is selected quotations from section 5.6.) s -5 316 M -( To avoid a representation that is tied to a particular underlying) s -5 305 M -( implementation at the client or server, the use of UTF-8 strings has) s -5 294 M -( been chosen. The string should be of the form user@dns_domain".) s -5 283 M -( This will allow for a client and server that do not use the same) s -5 272 M -( local representation the ability to translate to a common syntax that) s -5 261 M -( can be interpreted by both. In the case where there is no) s -5 250 M -( translation available to the client or server, the attribute value) s -5 239 M -( must be constructed without the "@". Therefore, the absence of the @) s -5 228 M -( from the owner or owner_group attribute signifies that no translation) s -5 217 M -( was available and the receiver of the attribute should not place any) s -5 206 M -( special meaning with the attribute value. Even though the attribute) s -5 195 M -( value can not be translated, it may still be useful. In the case of) s -5 184 M -( a client, the attribute string may be used for local display of) s -5 173 M -( ownership.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 10]) s -_R -S -PStoPSsaved restore -%%Page: (10,11) 6 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 11 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(5.5 Permissions) s -5 668 M -( The `permissions' field contains a bit mask of file permissions as) s -5 657 M -( defined by POSIX [1].) s -5 635 M -(5.6 Times) s -5 613 M -( The 'atime', 'createtime', and 'mtime' contain the access, creation,) s -5 602 M -( and modification times of the files, respectively. They are) s -5 591 M -( represented as seconds from Jan 1, 1970 in UTC.) s -5 569 M -(5.7 ACL) s -5 547 M -( The 'ACL' field contains an ACL similar to that defined in section) s -5 536 M -( 5.9 of NFS version 4 Protocol [3].) s -5 514 M -( uint32 ace-count) s -5 492 M -( repeated ace-count time:) s -5 481 M -( uint32 ace-type) s -5 470 M -( uint32 ace-flag) s -5 459 M -( uint32 ace-mask) s -5 448 M -( string who [UTF-8]) s -5 426 M -( ace-type is one of the following four values \(taken from NFS Version) s -5 415 M -( 4 Protocol [3]:) s -5 393 M -( const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;) s -5 382 M -( const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;) s -5 371 M -( const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;) s -5 360 M -( const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;) s -5 338 M -( ace-flag is a combination of the following flag values. See NFS) s -5 327 M -( Version 4 Protocol [3] section 5.9.2:) s -5 305 M -( const ACE4_FILE_INHERIT_ACE = 0x00000001;) s -5 294 M -( const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;) s -5 283 M -( const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;) s -5 272 M -( const ACE4_INHERIT_ONLY_ACE = 0x00000008;) s -5 261 M -( const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;) s -5 250 M -( const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;) s -5 239 M -( const ACE4_IDENTIFIER_GROUP = 0x00000040;) s -5 217 M -( ace-mask is any combination of the following flags \(taken from NFS) s -5 206 M -( Version 4 Protocol [3] section 5.9.3:) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 11]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 12 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( const ACE4_READ_DATA = 0x00000001;) s -5 679 M -( const ACE4_LIST_DIRECTORY = 0x00000001;) s -5 668 M -( const ACE4_WRITE_DATA = 0x00000002;) s -5 657 M -( const ACE4_ADD_FILE = 0x00000002;) s -5 646 M -( const ACE4_APPEND_DATA = 0x00000004;) s -5 635 M -( const ACE4_ADD_SUBDIRECTORY = 0x00000004;) s -5 624 M -( const ACE4_READ_NAMED_ATTRS = 0x00000008;) s -5 613 M -( const ACE4_WRITE_NAMED_ATTRS = 0x00000010;) s -5 602 M -( const ACE4_EXECUTE = 0x00000020;) s -5 591 M -( const ACE4_DELETE_CHILD = 0x00000040;) s -5 580 M -( const ACE4_READ_ATTRIBUTES = 0x00000080;) s -5 569 M -( const ACE4_WRITE_ATTRIBUTES = 0x00000100;) s -5 558 M -( const ACE4_DELETE = 0x00010000;) s -5 547 M -( const ACE4_READ_ACL = 0x00020000;) s -5 536 M -( const ACE4_WRITE_ACL = 0x00040000;) s -5 525 M -( const ACE4_WRITE_OWNER = 0x00080000;) s -5 514 M -( const ACE4_SYNCHRONIZE = 0x00100000;) s -5 492 M -( who is a UTF-8 string of the form described in 'Owner and Group') s -5 481 M -( \(Section 5.4\)) s -5 459 M -(5.8 Extended attributes) s -5 437 M -( The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension) s -5 426 M -( mechanism for vendor-specific extensions. If the flag is specified,) s -5 415 M -( then the `extended_count' field is present. It specifies the number) s -5 404 M -( of extended_type-extended_data pairs that follow. Each of these) s -5 393 M -( pairs specifies an extended attribute. For each of the attributes,) s -5 382 M -( the extended_type field should be a string of the format) s -5 371 M -( "name@domain", where "domain" is a valid, registered domain name and) s -5 360 M -( "name" identifies the method. The IETF may later standardize certain) s -5 349 M -( names that deviate from this format \(e.g., that do not contain the) s -5 338 M -( "@" sign\). The interpretation of `extended_data' depends on the) s -5 327 M -( type. Implementations SHOULD ignore extended data fields that they) s -5 316 M -( do not understand.) s -5 294 M -( Additional fields can be added to the attributes by either defining) s -5 283 M -( additional bits to the flags field to indicate their presence, or by) s -5 272 M -( defining extended attributes for them. The extended attributes) s -5 261 M -( mechanism is recommended for most purposes; additional flags bits) s -5 250 M -( should only be defined by an IETF standards action that also) s -5 239 M -( increments the protocol version number. The use of such new fields) s -5 228 M -( MUST be negotiated by the version number in the protocol exchange.) s -5 217 M -( It is a protocol error if a packet with unsupported protocol bits is) s -5 206 M -( received.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 12]) s -_R -S -PStoPSsaved restore -%%Page: (12,13) 7 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 13 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(6. Requests From the Client to the Server) s -5 668 M -( Requests from the client to the server represent the various file) s -5 657 M -( system operations. Each request begins with an `id' field, which is) s -5 646 M -( a 32-bit identifier identifying the request \(selected by the client\).) s -5 635 M -( The same identifier will be returned in the response to the request.) s -5 624 M -( One possible implementation is a monotonically increasing request) s -5 613 M -( sequence number \(modulo 2^32\).) s -5 591 M -( Many operations in the protocol operate on open files. The) s -5 580 M -( SSH_FXP_OPEN request can return a file handle \(which is an opaque) s -5 569 M -( variable-length string\) which may be used to access the file later) s -5 558 M -( \(e.g. in a read operation\). The client MUST NOT send requests the) s -5 547 M -( server with bogus or closed handles. However, the server MUST) s -5 536 M -( perform adequate checks on the handle in order to avoid security) s -5 525 M -( risks due to fabricated handles.) s -5 503 M -( This design allows either stateful and stateless server) s -5 492 M -( implementation, as well as an implementation which caches state) s -5 481 M -( between requests but may also flush it. The contents of the file) s -5 470 M -( handle string are entirely up to the server and its design. The) s -5 459 M -( client should not modify or attempt to interpret the file handle) s -5 448 M -( strings.) s -5 426 M -( The file handle strings MUST NOT be longer than 256 bytes.) s -5 404 M -(6.1 Request Synchronization and Reordering) s -5 382 M -( The protocol and implementations MUST process requests relating to) s -5 371 M -( the same file in the order in which they are received. In other) s -5 360 M -( words, if an application submits multiple requests to the server, the) s -5 349 M -( results in the responses will be the same as if it had sent the) s -5 338 M -( requests one at a time and waited for the response in each case. For) s -5 327 M -( example, the server may process non-overlapping read/write requests) s -5 316 M -( to the same file in parallel, but overlapping reads and writes cannot) s -5 305 M -( be reordered or parallelized. However, there are no ordering) s -5 294 M -( restrictions on the server for processing requests from two different) s -5 283 M -( file transfer connections. The server may interleave and parallelize) s -5 272 M -( them at will.) s -5 250 M -( There are no restrictions on the order in which responses to) s -5 239 M -( outstanding requests are delivered to the client, except that the) s -5 228 M -( server must ensure fairness in the sense that processing of no) s -5 217 M -( request will be indefinitely delayed even if the client is sending) s -5 206 M -( other requests so that there are multiple outstanding requests all) s -5 195 M -( the time.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 13]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 14 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(6.2 File Names) s -5 668 M -( This protocol represents file names as strings. File names are) s -5 657 M -( assumed to use the slash \('/'\) character as a directory separator.) s -5 635 M -( File names starting with a slash are "absolute", and are relative to) s -5 624 M -( the root of the file system. Names starting with any other character) s -5 613 M -( are relative to the user's default directory \(home directory\). Note) s -5 602 M -( that identifying the user is assumed to take place outside of this) s -5 591 M -( protocol.) s -5 569 M -( Servers SHOULD interpret a path name component ".." as referring to) s -5 558 M -( the parent directory, and "." as referring to the current directory.) s -5 547 M -( If the server implementation limits access to certain parts of the) s -5 536 M -( file system, it must be extra careful in parsing file names when) s -5 525 M -( enforcing such restrictions. There have been numerous reported) s -5 514 M -( security bugs where a ".." in a path name has allowed access outside) s -5 503 M -( the intended area.) s -5 481 M -( An empty path name is valid, and it refers to the user's default) s -5 470 M -( directory \(usually the user's home directory\).) s -5 448 M -( Otherwise, no syntax is defined for file names by this specification.) s -5 437 M -( Clients should not make any other assumptions; however, they can) s -5 426 M -( splice path name components returned by SSH_FXP_READDIR together) s -5 415 M -( using a slash \('/'\) as the separator, and that will work as expected.) s -5 393 M -( In order to comply with IETF Policy on Character Sets and Languages) s -5 382 M -( [2], all filenames are to be encoded in UTF-8. The shortest valid) s -5 371 M -( UTF-8 encoding of the UNICODE data MUST be used. The server is) s -5 360 M -( responsible for converting the UNICODE data to whatever canonical) s -5 349 M -( form it requires.) s -5 327 M -( For example, if the server requires that precomposed characters) s -5 316 M -( always be used, the server MUST NOT assume the filename as sent by) s -5 305 M -( the client has this attribute, but must do this normalization itself.) s -5 283 M -( It is understood that the lack of well-defined semantics for file) s -5 272 M -( names may cause interoperability problems between clients and servers) s -5 261 M -( using radically different operating systems. However, this approach) s -5 250 M -( is known to work acceptably with most systems, and alternative) s -5 239 M -( approaches that e.g. treat file names as sequences of structured) s -5 228 M -( components are quite complicated.) s -5 206 M -(6.3 Opening, Creating, and Closing Files) s -5 184 M -( Files are opened and created using the SSH_FXP_OPEN message, whose) s -5 173 M -( data part is as follows:) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 14]) s -_R -S -PStoPSsaved restore -%%Page: (14,15) 8 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 15 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( uint32 id) s -5 679 M -( string filename [UTF-8]) s -5 668 M -( uint32 pflags) s -5 657 M -( ATTRS attrs) s -5 635 M -( The `id' field is the request identifier as for all requests.) s -5 613 M -( The `filename' field specifies the file name. See Section ``File) s -5 602 M -( Names'' for more information.) s -5 580 M -( The `pflags' field is a bitmask. The following bits have been) s -5 569 M -( defined.) s -5 547 M -( #define SSH_FXF_READ 0x00000001) s -5 536 M -( #define SSH_FXF_WRITE 0x00000002) s -5 525 M -( #define SSH_FXF_APPEND 0x00000004) s -5 514 M -( #define SSH_FXF_CREAT 0x00000008) s -5 503 M -( #define SSH_FXF_TRUNC 0x00000010) s -5 492 M -( #define SSH_FXF_EXCL 0x00000020) s -5 481 M -( #define SSH_FXF_TEXT 0x00000040) s -5 459 M -( These have the following meanings:) s -5 437 M -( SSH_FXF_READ) s -5 426 M -( Open the file for reading.) s -5 404 M -( SSH_FXF_WRITE) s -5 393 M -( Open the file for writing. If both this and SSH_FXF_READ are) s -5 382 M -( specified, the file is opened for both reading and writing.) s -5 360 M -( SSH_FXF_APPEND) s -5 349 M -( Force all writes to append data at the end of the file. The) s -5 338 M -( offset parameter to write will be ignored.) s -5 316 M -( SSH_FXF_CREAT) s -5 305 M -( If this flag is specified, then a new file will be created if one) s -5 294 M -( does not already exist \(if O_TRUNC is specified, the new file will) s -5 283 M -( be truncated to zero length if it previously exists\).) s -5 261 M -( SSH_FXF_TRUNC) s -5 250 M -( Forces an existing file with the same name to be truncated to zero) s -5 239 M -( length when creating a file by specifying SSH_FXF_CREAT.) s -5 228 M -( SSH_FXF_CREAT MUST also be specified if this flag is used.) s -5 206 M -( SSH_FXF_EXCL) s -5 195 M -( Causes the request to fail if the named file already exists.) s -5 184 M -( SSH_FXF_CREAT MUST also be specified if this flag is used.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 15]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 16 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( SSH_FXF_TEXT) s -5 679 M -( Indicates that the server should treat the file as text and) s -5 668 M -( convert it to the canonical newline convention in use. \(See) s -5 657 M -( Determining Server Newline Convention. \(Section 4.3\)) s -5 635 M -( When a file is opened with the FXF_TEXT flag, the offset field in) s -5 624 M -( both the read and write function are ignored.) s -5 602 M -( Servers MUST correctly process multiple parallel reads and writes) s -5 591 M -( correctly in this mode. Naturally, it is permissible for them to) s -5 580 M -( do this by serializing the requests. It would not be possible for) s -5 569 M -( a client to reliably detect a server that does not implement) s -5 558 M -( parallel writes in time to prevent damage.) s -5 536 M -( Clients SHOULD use the SSH_FXF_APPEND flag to append data to a) s -5 525 M -( text file rather then using write with a calculated offset.) s -5 503 M -( To support seeks on text file the following SSH_FXP_EXTENDED) s -5 492 M -( packet is defined.) s -5 448 M -( string "text-seek") s -5 437 M -( string file-handle) s -5 426 M -( uint64 line-number) s -5 404 M -( line-number is the index of the line number to seek to, where byte) s -5 393 M -( 0 in the file is line number 0, and the byte directly following) s -5 382 M -( the first newline sequence in the file is line number 1 and so on.) s -5 360 M -( The response to a "text-seek" request is an SSH_FXP_STATUS) s -5 349 M -( message.) s -5 327 M -( An attempt to seek past the end-of-file should result in a) s -5 316 M -( SSH_FX_EOF status.) s -5 294 M -( Servers SHOULD support at least one "text-seek" in order to) s -5 283 M -( support resume. However, a client MUST be prepared to receive) s -5 272 M -( SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation.) s -5 261 M -( The client can then try a fall-back strategy, if it has one.) s -5 239 M -( Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned) s -5 228 M -( for read or write operations that are not sequential.) s -5 206 M -( The `attrs' field specifies the initial attributes for the file.) s -5 195 M -( Default values will be used for those attributes that are not) s -5 184 M -( specified. See Section ``File Attributes'' for more information.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 16]) s -_R -S -PStoPSsaved restore -%%Page: (16,17) 9 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 17 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( The response to this message will be either SSH_FXP_HANDLE \(if the) s -5 679 M -( operation is successful\) or SSH_FXP_STATUS \(if the operation fails\).) s -5 657 M -( A file is closed by using the SSH_FXP_CLOSE request. Its data field) s -5 646 M -( has the following format:) s -5 624 M -( uint32 id) s -5 613 M -( string handle) s -5 591 M -( where `id' is the request identifier, and `handle' is a handle) s -5 580 M -( previously returned in the response to SSH_FXP_OPEN or) s -5 569 M -( SSH_FXP_OPENDIR. The handle becomes invalid immediately after this) s -5 558 M -( request has been sent.) s -5 536 M -( The response to this request will be a SSH_FXP_STATUS message. One) s -5 525 M -( should note that on some server platforms even a close can fail.) s -5 514 M -( This can happen e.g. if the server operating system caches writes,) s -5 503 M -( and an error occurs while flushing cached writes during the close.) s -5 481 M -(6.4 Reading and Writing) s -5 459 M -( Once a file has been opened, it can be read using the SSH_FXP_READ) s -5 448 M -( message, which has the following format:) s -5 426 M -( uint32 id) s -5 415 M -( string handle) s -5 404 M -( uint64 offset) s -5 393 M -( uint32 len) s -5 371 M -( where `id' is the request identifier, `handle' is an open file handle) s -5 360 M -( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) relative) s -5 349 M -( to the beginning of the file from where to start reading, and `len') s -5 338 M -( is the maximum number of bytes to read.) s -5 316 M -( In response to this request, the server will read as many bytes as it) s -5 305 M -( can from the file \(up to `len'\), and return them in a SSH_FXP_DATA) s -5 294 M -( message. If an error occurs or EOF is encountered before reading any) s -5 283 M -( data, the server will respond with SSH_FXP_STATUS. For normal disk) s -5 272 M -( files, it is guaranteed that this will read the specified number of) s -5 261 M -( bytes, or up to end of file. For e.g. device files this may return) s -5 250 M -( fewer bytes than requested.) s -5 228 M -( Writing to a file is achieved using the SSH_FXP_WRITE message, which) s -5 217 M -( has the following format:) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 17]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 18 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( uint32 id) s -5 679 M -( string handle) s -5 668 M -( uint64 offset) s -5 657 M -( string data) s -5 635 M -( where `id' is a request identifier, `handle' is a file handle) s -5 624 M -( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) from the) s -5 613 M -( beginning of the file where to start writing, and `data' is the data) s -5 602 M -( to be written.) s -5 580 M -( The write will extend the file if writing beyond the end of the file.) s -5 569 M -( It is legal to write way beyond the end of the file; the semantics) s -5 558 M -( are to write zeroes from the end of the file to the specified offset) s -5 547 M -( and then the data. On most operating systems, such writes do not) s -5 536 M -( allocate disk space but instead leave "holes" in the file.) s -5 514 M -( The server responds to a write request with a SSH_FXP_STATUS message.) s -5 492 M -(6.5 Removing and Renaming Files) s -5 470 M -( Files can be removed using the SSH_FXP_REMOVE message. It has the) s -5 459 M -( following format:) s -5 437 M -( uint32 id) s -5 426 M -( string filename [UTF-8]) s -5 404 M -( where `id' is the request identifier and `filename' is the name of) s -5 393 M -( the file to be removed. See Section ``File Names'' for more) s -5 382 M -( information. This request cannot be used to remove directories.) s -5 360 M -( The server will respond to this request with a SSH_FXP_STATUS) s -5 349 M -( message.) s -5 327 M -( Files \(and directories\) can be renamed using the SSH_FXP_RENAME) s -5 316 M -( message. Its data is as follows:) s -5 294 M -( uint32 id) s -5 283 M -( string oldpath [UTF-8]) s -5 272 M -( string newpath [UTF-8]) s -5 250 M -( where `id' is the request identifier, `oldpath' is the name of an) s -5 239 M -( existing file or directory, and `newpath' is the new name for the) s -5 228 M -( file or directory. It is an error if there already exists a file) s -5 217 M -( with the name specified by newpath. The server may also fail rename) s -5 206 M -( requests in other situations, for example if `oldpath' and `newpath') s -5 195 M -( point to different file systems on the server.) s -5 173 M -( The server will respond to this request with a SSH_FXP_STATUS) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 18]) s -_R -S -PStoPSsaved restore -%%Page: (18,19) 10 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 19 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( message.) s -5 668 M -(6.6 Creating and Deleting Directories) s -5 646 M -( New directories can be created using the SSH_FXP_MKDIR request. It) s -5 635 M -( has the following format:) s -5 613 M -( uint32 id) s -5 602 M -( string path [UTF-8]) s -5 591 M -( ATTRS attrs) s -5 569 M -( where `id' is the request identifier.) s -5 547 M -( `path' specifies the directory to be created. See Section ``File) s -5 536 M -( Names'' for more information on file names.) s -5 514 M -( `attrs' specifies the attributes that should be applied to it upon) s -5 503 M -( creation. Attributes are discussed in more detail in Section ``File) s -5 492 M -( Attributes''.) s -5 470 M -( The server will respond to this request with a SSH_FXP_STATUS) s -5 459 M -( message. If a file or directory with the specified path already) s -5 448 M -( exists, an error will be returned.) s -5 426 M -( Directories can be removed using the SSH_FXP_RMDIR request, which has) s -5 415 M -( the following format:) s -5 393 M -( uint32 id) s -5 382 M -( string path [UTF-8]) s -5 360 M -( where `id' is the request identifier, and `path' specifies the) s -5 349 M -( directory to be removed. See Section ``File Names'' for more) s -5 338 M -( information on file names.) s -5 316 M -( The server responds to this request with a SSH_FXP_STATUS message.) s -5 305 M -( Errors may be returned from this operation for various reasons,) s -5 294 M -( including, but not limited to, the path does not exist, the path does) s -5 283 M -( not refer to a directory object, the directory is not empty, or the) s -5 272 M -( user has insufficient access or permission to perform the requested) s -5 261 M -( operation.) s -5 239 M -(6.7 Scanning Directories) s -5 217 M -( The files in a directory can be listed using the SSH_FXP_OPENDIR and) s -5 206 M -( SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one) s -5 195 M -( or more file names with full file attributes for each file. The) s -5 184 M -( client should call SSH_FXP_READDIR repeatedly until it has found the) s -5 173 M -( file it is looking for or until the server responds with a) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 19]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 20 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( SSH_FXP_STATUS message indicating an error \(normally SSH_FX_EOF if) s -5 679 M -( there are no more files in the directory\). The client should then) s -5 668 M -( close the handle using the SSH_FXP_CLOSE request.) s -5 646 M -( The SSH_FXP_OPENDIR opens a directory for reading. It has the) s -5 635 M -( following format:) s -5 613 M -( uint32 id) s -5 602 M -( string path [UTF-8]) s -5 580 M -( where `id' is the request identifier and `path' is the path name of) s -5 569 M -( the directory to be listed \(without any trailing slash\). See Section) s -5 558 M -( ``File Names'' for more information on file names. This will return) s -5 547 M -( an error if the path does not specify a directory or if the directory) s -5 536 M -( is not readable. The server will respond to this request with either) s -5 525 M -( a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.) s -5 503 M -( Once the directory has been successfully opened, files \(and) s -5 492 M -( directories\) contained in it can be listed using SSH_FXP_READDIR) s -5 481 M -( requests. These are of the format) s -5 459 M -( uint32 id) s -5 448 M -( string handle) s -5 426 M -( where `id' is the request identifier, and `handle' is a handle) s -5 415 M -( returned by SSH_FXP_OPENDIR. \(It is a protocol error to attempt to) s -5 404 M -( use an ordinary file handle returned by SSH_FXP_OPEN.\)) s -5 382 M -( The server responds to this request with either a SSH_FXP_NAME or a) s -5 371 M -( SSH_FXP_STATUS message. One or more names may be returned at a time.) s -5 360 M -( Full status information is returned for each name in order to speed) s -5 349 M -( up typical directory listings.) s -5 327 M -( If there are no more names available to be read, the server MUST) s -5 316 M -( respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF.) s -5 294 M -( When the client no longer wishes to read more names from the) s -5 283 M -( directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle) s -5 272 M -( should be closed regardless of whether an error has occurred or not.) s -5 250 M -(6.8 Retrieving File Attributes) s -5 228 M -( Very often, file attributes are automatically returned by) s -5 217 M -( SSH_FXP_READDIR. However, sometimes there is need to specifically) s -5 206 M -( retrieve the attributes for a named file. This can be done using the) s -5 195 M -( SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.) s -5 173 M -( SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 20]) s -_R -S -PStoPSsaved restore -%%Page: (20,21) 11 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 21 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( follows symbolic links on the server, whereas SSH_FXP_LSTAT does not) s -5 679 M -( follow symbolic links. Both have the same format:) s -5 657 M -( uint32 id) s -5 646 M -( string path [UTF-8]) s -5 635 M -( uint32 flags) s -5 613 M -( where `id' is the request identifier, and `path' specifies the file) s -5 602 M -( system object for which status is to be returned. The server) s -5 591 M -( responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.) s -5 569 M -( The flags field specify the attribute flags in which the client has) s -5 558 M -( particular interest. This is a hint to the server. For example,) s -5 547 M -( because retrieving owner / group and acl information can be an) s -5 536 M -( expensive operation under some operating systems, the server may) s -5 525 M -( choose not to retrieve this information unless the client expresses a) s -5 514 M -( specific interest in it.) s -5 492 M -( The client has no guarantee the server will provide all the fields) s -5 481 M -( that it has expressed an interest in.) s -5 459 M -( SSH_FXP_FSTAT differs from the others in that it returns status) s -5 448 M -( information for an open file \(identified by the file handle\). Its) s -5 437 M -( format is as follows:) s -5 415 M -( uint32 id) s -5 404 M -( string handle) s -5 393 M -( uint32 flags) s -5 371 M -( where `id' is the request identifier and `handle' is a file handle) s -5 360 M -( returned by SSH_FXP_OPEN. The server responds to this request with) s -5 349 M -( SSH_FXP_ATTRS or SSH_FXP_STATUS.) s -5 327 M -(6.9 Setting File Attributes) s -5 305 M -( File attributes may be modified using the SSH_FXP_SETSTAT and) s -5 294 M -( SSH_FXP_FSETSTAT requests. These requests are used for operations) s -5 283 M -( such as changing the ownership, permissions or access times, as well) s -5 272 M -( as for truncating a file.) s -5 250 M -( The SSH_FXP_SETSTAT request is of the following format:) s -5 228 M -( uint32 id) s -5 217 M -( string path [UTF-8]) s -5 206 M -( ATTRS attrs) s -5 184 M -( where `id' is the request identifier, `path' specifies the file) s -5 173 M -( system object \(e.g. file or directory\) whose attributes are to be) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 21]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 22 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( modified, and `attrs' specifies the modifications to be made to its) s -5 679 M -( attributes. Attributes are discussed in more detail in Section) s -5 668 M -( ``File Attributes''.) s -5 646 M -( An error will be returned if the specified file system object does) s -5 635 M -( not exist or the user does not have sufficient rights to modify the) s -5 624 M -( specified attributes. The server responds to this request with a) s -5 613 M -( SSH_FXP_STATUS message.) s -5 591 M -( The SSH_FXP_FSETSTAT request modifies the attributes of a file which) s -5 580 M -( is already open. It has the following format:) s -5 558 M -( uint32 id) s -5 547 M -( string handle) s -5 536 M -( ATTRS attrs) s -5 514 M -( where `id' is the request identifier, `handle' \(MUST be returned by) s -5 503 M -( SSH_FXP_OPEN\) identifies the file whose attributes are to be) s -5 492 M -( modified, and `attrs' specifies the modifications to be made to its) s -5 481 M -( attributes. Attributes are discussed in more detail in Section) s -5 470 M -( ``File Attributes''. The server will respond to this request with) s -5 459 M -( SSH_FXP_STATUS.) s -5 437 M -(6.10 Dealing with Symbolic links) s -5 415 M -( The SSH_FXP_READLINK request may be used to read the target of a) s -5 404 M -( symbolic link. It would have a data part as follows:) s -5 382 M -( uint32 id) s -5 371 M -( string path [UTF-8]) s -5 349 M -( where `id' is the request identifier and `path' specifies the path) s -5 338 M -( name of the symlink to be read.) s -5 316 M -( The server will respond with a SSH_FXP_NAME packet containing only) s -5 305 M -( one name and a dummy attributes value. The name in the returned) s -5 294 M -( packet contains the target of the link. If an error occurs, the) s -5 283 M -( server may respond with SSH_FXP_STATUS.) s -5 261 M -( The SSH_FXP_SYMLINK request will create a symbolic link on the) s -5 250 M -( server. It is of the following format) s -5 228 M -( uint32 id) s -5 217 M -( string linkpath [UTF-8]) s -5 206 M -( string targetpath [UTF-8]) s -5 184 M -( where `id' is the request identifier, `linkpath' specifies the path) s -5 173 M -( name of the symlink to be created and `targetpath' specifies the) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 22]) s -_R -S -PStoPSsaved restore -%%Page: (22,23) 12 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 23 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( target of the symlink. The server shall respond with a) s -5 679 M -( SSH_FXP_STATUS indicating either success \(SSH_FX_OK\) or an error) s -5 668 M -( condition.) s -5 646 M -(6.11 Canonicalizing the Server-Side Path Name) s -5 624 M -( The SSH_FXP_REALPATH request can be used to have the server) s -5 613 M -( canonicalize any given path name to an absolute path. This is useful) s -5 602 M -( for converting path names containing ".." components or relative) s -5 591 M -( pathnames without a leading slash into absolute paths. The format of) s -5 580 M -( the request is as follows:) s -5 558 M -( uint32 id) s -5 547 M -( string path [UTF-8]) s -5 525 M -( where `id' is the request identifier and `path' specifies the path) s -5 514 M -( name to be canonicalized. The server will respond with a) s -5 503 M -( SSH_FXP_NAME packet containing the name in canonical form and a dummy) s -5 492 M -( attributes value. If an error occurs, the server may also respond) s -5 481 M -( with SSH_FXP_STATUS.) s -5 459 M -(6.11.1 Best practice for dealing with paths) s -5 437 M -( The client SHOULD treat the results of SSH_FXP_REALPATH as a) s -5 426 M -( canonical absolute path, even if the path does not appear to be) s -5 415 M -( absolute. A client that use REALPATH\("."\) and treats the result as) s -5 404 M -( absolute, even if there is no leading slash, will continue to) s -5 393 M -( function correctly, even when talking to a Windows NT or VMS style) s -5 382 M -( system, where absolute paths may not begin with a slash.) s -5 360 M -( For example, if the client wishes to change directory up, and the) s -5 349 M -( server has returned "c:/x/y/z" from REALPATH, the client SHOULD use) s -5 338 M -( "c:/x/y/z/..".) s -5 316 M -( As a second example, if the client wishes to open the file "x.txt" in) s -5 305 M -( the current directory, and server has returned "dka100:/x/y/z" as the) s -5 294 M -( canonical path of the directory, the client SHOULD open "dka100:/x/y/) s -5 283 M -( z/x.txt") s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 23]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 24 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(7. Responses from the Server to the Client) s -5 668 M -( The server responds to the client using one of a few response) s -5 657 M -( packets. All requests can return a SSH_FXP_STATUS response upon) s -5 646 M -( failure. When the operation is successful, any of the responses may) s -5 635 M -( be returned \(depending on the operation\). If no data needs to be) s -5 624 M -( returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK) s -5 613 M -( status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used) s -5 602 M -( to return a file handle \(for SSH_FXP_OPEN and SSH_FXP_OPENDIR) s -5 591 M -( requests\), SSH_FXP_DATA is used to return data from SSH_FXP_READ,) s -5 580 M -( SSH_FXP_NAME is used to return one or more file names from a) s -5 569 M -( SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is) s -5 558 M -( used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and) s -5 547 M -( SSH_FXP_FSTAT requests.) s -5 525 M -( Exactly one response will be returned for each request. Each) s -5 514 M -( response packet contains a request identifier which can be used to) s -5 503 M -( match each response with the corresponding request. Note that it is) s -5 492 M -( legal to have several requests outstanding simultaneously, and the) s -5 481 M -( server is allowed to send responses to them in a different order from) s -5 470 M -( the order in which the requests were sent \(the result of their) s -5 459 M -( execution, however, is guaranteed to be as if they had been processed) s -5 448 M -( one at a time in the order in which the requests were sent\).) s -5 426 M -( Response packets are of the same general format as request packets.) s -5 415 M -( Each response packet begins with the request identifier.) s -5 393 M -( The format of the data portion of the SSH_FXP_STATUS response is as) s -5 382 M -( follows:) s -5 360 M -( uint32 id) s -5 349 M -( uint32 error/status code) s -5 338 M -( string error message \(ISO-10646 UTF-8 [RFC-2279]\)) s -5 327 M -( string language tag \(as defined in [RFC-1766]\)) s -5 305 M -( where `id' is the request identifier, and `error/status code') s -5 294 M -( indicates the result of the requested operation. The value SSH_FX_OK) s -5 283 M -( indicates success, and all other values indicate failure.) s -5 261 M -( Currently, the following values are defined \(other values may be) s -5 250 M -( defined by future versions of this protocol\):) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 24]) s -_R -S -PStoPSsaved restore -%%Page: (24,25) 13 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 25 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( #define SSH_FX_OK 0) s -5 679 M -( #define SSH_FX_EOF 1) s -5 668 M -( #define SSH_FX_NO_SUCH_FILE 2) s -5 657 M -( #define SSH_FX_PERMISSION_DENIED 3) s -5 646 M -( #define SSH_FX_FAILURE 4) s -5 635 M -( #define SSH_FX_BAD_MESSAGE 5) s -5 624 M -( #define SSH_FX_NO_CONNECTION 6) s -5 613 M -( #define SSH_FX_CONNECTION_LOST 7) s -5 602 M -( #define SSH_FX_OP_UNSUPPORTED 8) s -5 591 M -( #define SSH_FX_INVALID_HANDLE 9) s -5 580 M -( #define SSH_FX_NO_SUCH_PATH 10) s -5 569 M -( #define SSH_FX_FILE_ALREADY_EXISTS 11) s -5 558 M -( #define SSH_FX_WRITE_PROTECT 12) s -5 536 M -( SSH_FX_OK) s -5 525 M -( Indicates successful completion of the operation.) s -5 503 M -( SSH_FX_EOF) s -5 492 M -( indicates end-of-file condition; for SSH_FX_READ it means that no) s -5 481 M -( more data is available in the file, and for SSH_FX_READDIR it) s -5 470 M -( indicates that no more files are contained in the directory.) s -5 448 M -( SSH_FX_NO_SUCH_FILE) s -5 437 M -( is returned when a reference is made to a file which does not) s -5 426 M -( exist.) s -5 404 M -( SSH_FX_PERMISSION_DENIED) s -5 393 M -( is returned when the authenticated user does not have sufficient) s -5 382 M -( permissions to perform the operation.) s -5 360 M -( SSH_FX_FAILURE) s -5 349 M -( is a generic catch-all error message; it should be returned if an) s -5 338 M -( error occurs for which there is no more specific error code) s -5 327 M -( defined.) s -5 305 M -( SSH_FX_BAD_MESSAGE) s -5 294 M -( may be returned if a badly formatted packet or protocol) s -5 283 M -( incompatibility is detected.) s -5 261 M -( SSH_FX_NO_CONNECTION) s -5 250 M -( is a pseudo-error which indicates that the client has no) s -5 239 M -( connection to the server \(it can only be generated locally by the) s -5 228 M -( client, and MUST NOT be returned by servers\).) s -5 206 M -( SSH_FX_CONNECTION_LOST) s -5 195 M -( is a pseudo-error which indicates that the connection to the) s -5 184 M -( server has been lost \(it can only be generated locally by the) s -5 173 M -( client, and MUST NOT be returned by servers\).) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 25]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 26 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( SSH_FX_OP_UNSUPPORTED) s -5 679 M -( indicates that an attempt was made to perform an operation which) s -5 668 M -( is not supported for the server \(it may be generated locally by) s -5 657 M -( the client if e.g. the version number exchange indicates that a) s -5 646 M -( required feature is not supported by the server, or it may be) s -5 635 M -( returned by the server if the server does not implement an) s -5 624 M -( operation\).) s -5 602 M -( SSH_FX_INVALID_HANDLE) s -5 591 M -( The handle value was invalid.) s -5 569 M -( SSH_FX_NO_SUCH_PATH) s -5 558 M -( The file path does not exist or is invalid.) s -5 536 M -( SSH_FX_FILE_ALREADY_EXISTS) s -5 525 M -( The file already exists.) s -5 503 M -( SSH_FX_WRITE_PROTECT) s -5 492 M -( The file is on read only media, or the media is write protected.) s -5 470 M -( The SSH_FXP_HANDLE response has the following format:) s -5 448 M -( uint32 id) s -5 437 M -( string handle) s -5 415 M -( where `id' is the request identifier, and `handle' is an arbitrary) s -5 404 M -( string that identifies an open file or directory on the server. The) s -5 393 M -( handle is opaque to the client; the client MUST NOT attempt to) s -5 382 M -( interpret or modify it in any way. The length of the handle string) s -5 371 M -( MUST NOT exceed 256 data bytes.) s -5 349 M -( The SSH_FXP_DATA response has the following format:) s -5 327 M -( uint32 id) s -5 316 M -( string data) s -5 294 M -( where `id' is the request identifier, and `data' is an arbitrary byte) s -5 283 M -( string containing the requested data. The data string may be at most) s -5 272 M -( the number of bytes requested in a SSH_FXP_READ request, but may also) s -5 261 M -( be shorter if end of file is reached or if the read is from something) s -5 250 M -( other than a regular file.) s -5 228 M -( The SSH_FXP_NAME response has the following format:) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 26]) s -_R -S -PStoPSsaved restore -%%Page: (26,27) 14 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 27 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( uint32 id) s -5 679 M -( uint32 count) s -5 668 M -( repeats count times:) s -5 657 M -( string filename [UTF-8]) s -5 646 M -( ATTRS attrs) s -5 624 M -( where `id' is the request identifier, `count' is the number of names) s -5 613 M -( returned in this response, and the remaining fields repeat `count') s -5 602 M -( times \(so that all three fields are first included for the first) s -5 591 M -( file, then for the second file, etc\). In the repeated part,) s -5 580 M -( `filename' is a file name being returned \(for SSH_FXP_READDIR, it) s -5 569 M -( will be a relative name within the directory, without any path) s -5 558 M -( components; for SSH_FXP_REALPATH it will be an absolute path name\),) s -5 547 M -( and `attrs' is the attributes of the file as described in Section) s -5 536 M -( ``File Attributes''.) s -5 514 M -( The SSH_FXP_ATTRS response has the following format:) s -5 492 M -( uint32 id) s -5 481 M -( ATTRS attrs) s -5 459 M -( where `id' is the request identifier, and `attrs' is the returned) s -5 448 M -( file attributes as described in Section ``File Attributes''.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 27]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 28 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(8. Vendor-Specific Extensions) s -5 668 M -( The SSH_FXP_EXTENDED request provides a generic extension mechanism) s -5 657 M -( for adding vendor-specific commands. The request has the following) s -5 646 M -( format:) s -5 624 M -( uint32 id) s -5 613 M -( string extended-request) s -5 602 M -( ... any request-specific data ...) s -5 580 M -( where `id' is the request identifier, and `extended-request' is a) s -5 569 M -( string of the format "name@domain", where domain is an internet) s -5 558 M -( domain name of the vendor defining the request. The rest of the) s -5 547 M -( request is completely vendor-specific, and servers should only) s -5 536 M -( attempt to interpret it if they recognize the `extended-request') s -5 525 M -( name.) s -5 503 M -( The server may respond to such requests using any of the response) s -5 492 M -( packets defined in Section ``Responses from the Server to the) s -5 481 M -( Client''. Additionally, the server may also respond with a) s -5 470 M -( SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does) s -5 459 M -( not recognize the `extended-request' name, then the server MUST) s -5 448 M -( respond with SSH_FXP_STATUS with error/status set to) s -5 437 M -( SSH_FX_OP_UNSUPPORTED.) s -5 415 M -( The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary) s -5 404 M -( extension-specific data from the server to the client. It is of the) s -5 393 M -( following format:) s -5 371 M -( uint32 id) s -5 360 M -( ... any request-specific data ...) s -5 338 M -( There is a range of packet types reserved for use by extensions. In) s -5 327 M -( order to avoid collision, extensions that turn on the use of) s -5 316 M -( additional packet types should determine those numbers dynamically.) s -5 294 M -( The suggested way of doing this is have an extension request from the) s -5 283 M -( client to the server that enables the extension; the extension) s -5 272 M -( response from the server to the client would specify the actual type) s -5 261 M -( values to use, in additional to any other data.) s -5 239 M -( Extension authors should be mindful of the limited range of packet) s -5 228 M -( types available \(there are only 45 values available\) and avoid) s -5 217 M -( requiring a new packet type where possible.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 28]) s -_R -S -PStoPSsaved restore -%%Page: (28,29) 15 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 29 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(9. Security Considerations) s -5 668 M -( This protocol assumes that it is run over a secure channel and that) s -5 657 M -( the endpoints of the channel have been authenticated. Thus, this) s -5 646 M -( protocol assumes that it is externally protected from network-level) s -5 635 M -( attacks.) s -5 613 M -( This protocol provides file system access to arbitrary files on the) s -5 602 M -( server \(only constrained by the server implementation\). It is the) s -5 591 M -( responsibility of the server implementation to enforce any access) s -5 580 M -( controls that may be required to limit the access allowed for any) s -5 569 M -( particular user \(the user being authenticated externally to this) s -5 558 M -( protocol, typically using the SSH User Authentication Protocol [8].) s -5 536 M -( Care must be taken in the server implementation to check the validity) s -5 525 M -( of received file handle strings. The server should not rely on them) s -5 514 M -( directly; it MUST check the validity of each handle before relying on) s -5 503 M -( it.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 29]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 30 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(10. Changes from previous protocol versions) s -5 668 M -( The SSH File Transfer Protocol has changed over time, before it's) s -5 657 M -( standardization. The following is a description of the incompatible) s -5 646 M -( changes between different versions.) s -5 624 M -(10.1 Changes between versions 4 and 3) s -5 602 M -( Many of the changes between version 4 and version 3 are to the) s -5 591 M -( attribute structure to make it more flexible for non-unix platforms.) s -5 569 M -( o Make all filenames UTF-8.) s -5 547 M -( o Added 'newline' extension.) s -5 525 M -( o Made file attribute owner and group strings so they can actually) s -5 514 M -( be used on disparate systems.) s -5 492 M -( o Added createtime field, and added separate flags for atime,) s -5 481 M -( createtime, and mtime so they can be set separately.) s -5 459 M -( o Split the file type out of the permissions field and into it's own) s -5 448 M -( field \(which is always present.\)) s -5 426 M -( o Added acl attribute.) s -5 404 M -( o Added SSH_FXF_TEXT file open flag.) s -5 382 M -( o Added flags field to the get stat commands so that the client can) s -5 371 M -( specifically request information the server might not normally) s -5 360 M -( included for performance reasons.) s -5 338 M -( o Removed the long filename from the names structure-- it can now be) s -5 327 M -( built from information available in the attrs structure.) s -5 305 M -( o Added reserved range of packet numbers for extensions.) s -5 283 M -( o Added several additional error codes.) s -5 261 M -( o Change the way version negotiate works slightly. Previously, if) s -5 250 M -( the client version were higher than the server version, the server) s -5 239 M -( was supposed to 'echo back' the clients version. The server now) s -5 228 M -( sends it's own version and the lower of the two is considered to) s -5 217 M -( be the one in use.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 30]) s -_R -S -PStoPSsaved restore -%%Page: (30,31) 16 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 31 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(10.2 Changes between versions 3 and 2) s -5 668 M -( o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.) s -5 646 M -( o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were) s -5 635 M -( added.) s -5 613 M -( o The SSH_FXP_STATUS message was changed to include fields `error) s -5 602 M -( message' and `language tag'.) s -5 569 M -(10.3 Changes between versions 2 and 1) s -5 547 M -( o The SSH_FXP_RENAME message was added.) s -5 514 M -(10.4 Changes between versions 1 and 0) s -5 492 M -( o Implementation changes, no actual protocol changes.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 31]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 32 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(11. Trademark Issues) s -5 668 M -( "ssh" is a registered trademark of SSH Communications Security Corp) s -5 657 M -( in the United States and/or other countries.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 32]) s -_R -S -PStoPSsaved restore -%%Page: (32,33) 17 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 33 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(References) s -5 668 M -( [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and) s -5 657 M -( P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January) s -5 646 M -( 1999.) s -5 624 M -( [2] Alvestrand, H., "IETF Policy on Character Sets and Languages",) s -5 613 M -( BCP 18, RFC 2277, January 1998.) s -5 591 M -( [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,) s -5 580 M -( C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC) s -5 569 M -( 3010, December 2000.) s -5 547 M -( [4] Institute of Electrical and Electronics Engineers, "Information) s -5 536 M -( Technology - Portable Operating System Interface \(POSIX\) - Part) s -5 525 M -( 1: System Application Program Interface \(API\) [C Language]",) s -5 514 M -( IEEE Standard 1003.2, 1996.) s -5 492 M -( [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 481 M -( Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-) s -5 470 M -( architecture-13 \(work in progress\), September 2002.) s -5 448 M -( [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 437 M -( Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-) s -5 426 M -( transport-15 \(work in progress\), September 2002.) s -5 404 M -( [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 393 M -( Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16) s -5 382 M -( \(work in progress\), September 2002.) s -5 360 M -( [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s -5 349 M -( Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-) s -5 338 M -( userauth-16 \(work in progress\), September 2002.) s -5 305 M -(Authors' Addresses) s -5 283 M -( Joseph Galbraith) s -5 272 M -( VanDyke Software) s -5 261 M -( 4848 Tramway Ridge Blvd) s -5 250 M -( Suite 101) s -5 239 M -( Albuquerque, NM 87111) s -5 228 M -( US) s -5 206 M -( Phone: +1 505 332 5700) s -5 195 M -( EMail: galb-list@vandyke.com) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 33]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 34 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -( Tatu Ylonen) s -5 679 M -( SSH Communications Security Corp) s -5 668 M -( Fredrikinkatu 42) s -5 657 M -( HELSINKI FIN-00100) s -5 646 M -( Finland) s -5 624 M -( EMail: ylo@ssh.com) s -5 591 M -( Sami Lehtinen) s -5 580 M -( SSH Communications Security Corp) s -5 569 M -( Fredrikinkatu 42) s -5 558 M -( HELSINKI FIN-00100) s -5 547 M -( Finland) s -5 525 M -( EMail: sjl@ssh.com) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 34]) s -_R -S -PStoPSsaved restore -%%Page: (34,35) 18 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 35 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH File Transfer Protocol October 2002) s -5 690 M -(Full Copyright Statement) s -5 668 M -( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s -5 646 M -( This document and translations of it may be copied and furnished to) s -5 635 M -( others, and derivative works that comment on or otherwise explain it) s -5 624 M -( or assist in its implementation may be prepared, copied, published) s -5 613 M -( and distributed, in whole or in part, without restriction of any) s -5 602 M -( kind, provided that the above copyright notice and this paragraph are) s -5 591 M -( included on all such copies and derivative works. However, this) s -5 580 M -( document itself may not be modified in any way, such as by removing) s -5 569 M -( the copyright notice or references to the Internet Society or other) s -5 558 M -( Internet organizations, except as needed for the purpose of) s -5 547 M -( developing Internet standards in which case the procedures for) s -5 536 M -( copyrights defined in the Internet Standards process must be) s -5 525 M -( followed, or as required to translate it into languages other than) s -5 514 M -( English.) s -5 492 M -( The limited permissions granted above are perpetual and will not be) s -5 481 M -( revoked by the Internet Society or its successors or assigns.) s -5 459 M -( This document and the information contained herein is provided on an) s -5 448 M -( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s -5 437 M -( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s -5 426 M -( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s -5 415 M -( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s -5 404 M -( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s -5 382 M -(Acknowledgement) s -5 360 M -( Funding for the RFC Editor function is currently provided by the) s -5 349 M -( Internet Society.) s -5 129 M -(Galbraith, et al. Expires April 16, 2003 [Page 35]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 36 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -_R -S -PStoPSsaved restore -%%Trailer -%%Pages: 36 -%%DocumentNeededResources: font Courier-Bold Courier -%%EOF diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt deleted file mode 100644 index 83960ae976..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt +++ /dev/null @@ -1,1962 +0,0 @@ - - - -Secure Shell Working Group J. Galbraith -Internet-Draft VanDyke Software -Expires: April 16, 2003 T. Ylonen - S. Lehtinen - SSH Communications Security Corp - October 16, 2002 - - - SSH File Transfer Protocol - draft-ietf-secsh-filexfer-03.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that - other groups may also distribute working documents as Internet- - Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on April 16, 2003. - -Copyright Notice - - Copyright (C) The Internet Society (2002). All Rights Reserved. - -Abstract - - The SSH File Transfer Protocol provides secure file transfer - functionality over any reliable data stream. It is the standard file - transfer protocol for use with the SSH2 protocol. This document - describes the file transfer protocol and its interface to the SSH2 - protocol suite. - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 1] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -Table of Contents - - 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4 - 3. General Packet Format . . . . . . . . . . . . . . . . . . 5 - 4. Protocol Initialization . . . . . . . . . . . . . . . . . 7 - 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 7 - 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 7 - 4.3 Determining Server Newline Convention . . . . . . . . . . 8 - 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 9 - 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 9 - 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 - 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 - 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 10 - 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 11 - 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 11 - 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 - 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 12 - 6. Requests From the Client to the Server . . . . . . . . . . 13 - 6.1 Request Synchronization and Reordering . . . . . . . . . . 13 - 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 14 - 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 14 - 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 17 - 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 18 - 6.6 Creating and Deleting Directories . . . . . . . . . . . . 19 - 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 19 - 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 20 - 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 21 - 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 22 - 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 23 - 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 23 - 7. Responses from the Server to the Client . . . . . . . . . 24 - 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 28 - 9. Security Considerations . . . . . . . . . . . . . . . . . 29 - 10. Changes from previous protocol versions . . . . . . . . . 30 - 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 30 - 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 31 - 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 31 - 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 31 - 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 32 - References . . . . . . . . . . . . . . . . . . . . . . . . 33 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . 33 - Full Copyright Statement . . . . . . . . . . . . . . . . . 35 - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 2] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -1. Introduction - - This protocol provides secure file transfer (and more generally file - system access) functionality over a reliable data stream, such as a - channel in the SSH2 protocol [5]. - - This protocol is designed so that it could be used to implement a - secure remote file system service, as well as a secure file transfer - service. - - This protocol assumes that it runs over a secure channel, and that - the server has already authenticated the user at the client end, and - that the identity of the client user is externally available to the - server implementation. - - In general, this protocol follows a simple request-response model. - Each request and response contains a sequence number and multiple - requests may be pending simultaneously. There are a relatively large - number of different request messages, but a small number of possible - response messages. Each request has one or more response messages - that may be returned in result (e.g., a read either returns data or - reports error status). - - The packet format descriptions in this specification follow the - notation presented in the secsh architecture draft. [5] - - Even though this protocol is described in the context of the SSH2 - protocol, this protocol is general and independent of the rest of the - SSH2 protocol suite. It could be used in a number of different - applications, such as secure file transfer over TLS RFC 2246 [1] and - transfer of management information in VPN applications. - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 3] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -2. Use with the SSH Connection Protocol - - When used with the SSH2 Protocol suite, this protocol is intended to - be used from the SSH Connection Protocol [7] as a subsystem, as - described in section ``Starting a Shell or a Command''. The - subsystem name used with this protocol is "sftp". - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 4] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -3. General Packet Format - - All packets transmitted over the secure connection are of the - following format: - - uint32 length - byte type - byte[length - 1] data payload - - That is, they are just data preceded by 32-bit length and 8-bit type - fields. The `length' is the length of the data area, and does not - include the `length' field itself. The format and interpretation of - the data area depends on the packet type. - - All packet descriptions below only specify the packet type and the - data that goes into the data field. Thus, they should be prefixed by - the `length' and `type' fields. - - The maximum size of a packet is in practice determined by the client - (the maximum size of read or write requests that it sends, plus a few - bytes of packet overhead). All servers SHOULD support packets of at - least 34000 bytes (where the packet size refers to the full length, - including the header above). This should allow for reads and writes - of at most 32768 bytes. - - There is no limit on the number of outstanding (non-acknowledged) - requests that the client may send to the server. In practice this is - limited by the buffering available on the data stream and the queuing - performed by the server. If the server's queues are full, it should - not read any more data from the stream, and flow control will prevent - the client from sending more requests. Note, however, that while - there is no restriction on the protocol level, the client's API may - provide a limit in order to prevent infinite queuing of outgoing - requests at the client. - - The following values are defined for packet types. - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 5] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - #define SSH_FXP_INIT 1 - #define SSH_FXP_VERSION 2 - #define SSH_FXP_OPEN 3 - #define SSH_FXP_CLOSE 4 - #define SSH_FXP_READ 5 - #define SSH_FXP_WRITE 6 - #define SSH_FXP_LSTAT 7 - #define SSH_FXP_FSTAT 8 - #define SSH_FXP_SETSTAT 9 - #define SSH_FXP_FSETSTAT 10 - #define SSH_FXP_OPENDIR 11 - #define SSH_FXP_READDIR 12 - #define SSH_FXP_REMOVE 13 - #define SSH_FXP_MKDIR 14 - #define SSH_FXP_RMDIR 15 - #define SSH_FXP_REALPATH 16 - #define SSH_FXP_STAT 17 - #define SSH_FXP_RENAME 18 - #define SSH_FXP_READLINK 19 - #define SSH_FXP_SYMLINK 20 - - #define SSH_FXP_STATUS 101 - #define SSH_FXP_HANDLE 102 - #define SSH_FXP_DATA 103 - #define SSH_FXP_NAME 104 - #define SSH_FXP_ATTRS 105 - - #define SSH_FXP_EXTENDED 200 - #define SSH_FXP_EXTENDED_REPLY 201 - - RESERVED_FOR_EXTENSIONS 210-255 - - Additional packet types should only be defined if the protocol - version number (see Section ``Protocol Initialization'') is - incremented, and their use MUST be negotiated using the version - number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY - packets can be used to implement vendor-specific extensions. See - Section ``Vendor-Specific-Extensions'' for more details. - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 6] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -4. Protocol Initialization - - When the file transfer protocol starts, the client first sends a - SSH_FXP_INIT (including its version number) packet to the server. - The server responds with a SSH_FXP_VERSION packet, supplying the - lowest of its own and the client's version number. Both parties - should from then on adhere to particular version of the protocol. - - The version number of the protocol specified in this document is 4. - The version number should be incremented for each incompatible - revision of this protocol. - -4.1 Client Initialization - - The SSH_FXP_INIT packet (from client to server) has the following - data: - - uint32 version - - Version 3 of this protocol allowed clients to include extensions in - the SSH_FXP_INIT packet; however, this can cause interoperability - problems with version 1 and version 2 servers because the client must - send this packet before knowing the servers version. - - In this version of the protocol, clients MUST use the - SSH_FXP_EXTENDED packet to send extensions to the server after - version exchange has completed. Clients MUST NOT include extensions - in the version packet. This will prevent interoperability problems - with older servers - -4.2 Server Initialization - - The SSH_FXP_VERSION packet (from server to client) has the following - data: - - uint32 version - - - 'version' is the lower of the protocol version supported by the - server and the version number received from the client. - - The extension data may be empty, or may be a sequence of - - string extension_name - string extension_data - - pairs (both strings MUST always be present if one is, but the - `extension_data' string may be of zero length). If present, these - - - -Galbraith, et al. Expires April 16, 2003 [Page 7] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - strings indicate extensions to the baseline protocol. The - `extension_name' field(s) identify the name of the extension. The - name should be of the form "name@domain", where the domain is the DNS - domain name of the organization defining the extension. Additional - names that are not of this format may be defined later by the IETF. - Implementations MUST silently ignore any extensions whose name they - do not recognize. - -4.3 Determining Server Newline Convention - - In order to correctly process text files in a cross platform - compatible way, the newline convention must be converted from that of - the server to that of the client, or, during an upload, from that of - the client to that of the server. - - Versions 3 and prior of this protocol made no provisions for - processing text files. Many clients implemented some sort of - conversion algorithm, but without either a 'canonical' on the wire - format or knowledge of the servers newline convention, correct - conversion was not always possible. - - Starting with Version 4, the SSH_FXF_TEXT file open flag (Section - 6.3) makes it possible to request that the server translate a file to - a 'canonical' on the wire format. This format uses \r\n as the line - separator. - - Servers for systems using multiple newline characters (for example, - Mac OS X or VMS) or systems using counted records, MUST translate to - the canonical form. - - However, to ease the burden of implementation on servers that use a - single, simple separator sequence, the following extension allows the - canonical format to be changed. - - string "newline" - string new-canonical-separator (usually "\r" or "\n" or "\r\n") - - All clients MUST support this extension. - - When processing text files, clients SHOULD NOT translate any - character or sequence that is not an exact match of the servers - newline separator. - - In particular, if the newline sequence being used is the canonical - "\r\n" sequence, a lone \r or a lone \n SHOULD be written through - without change. - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 8] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -5. File Attributes - - A new compound data type is defined for encoding file attributes. - The same encoding is used both when returning file attributes from - the server and when sending file attributes to the server. When - sending it to the server, the flags field specifies which attributes - are included, and the server will use default values for the - remaining attributes (or will not modify the values of remaining - attributes). When receiving attributes from the server, the flags - specify which attributes are included in the returned data. The - server normally returns all attributes it knows about. - - uint32 flags - byte type always present - uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE - string owner present only if flag SSH_FILEXFER_ATTR_OWNERGROUP - string group present only if flag SSH_FILEXFER_ATTR_OWNERGROUP - uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS - uint32 atime present only if flag SSH_FILEXFER_ATTR_ACCESSTIME - uint32 createtime present only if flag SSH_FILEXFER_ATTR_CREATETIME - uint32 mtime present only if flag SSH_FILEXFER_ATTR_MODIFYTIME - string acl present only if flag SSH_FILEXFER_ATTR_ACL - uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED - string extended_type - string extended_data - ... more extended data (extended_type - extended_data pairs), - so that number of pairs equals extended_count - - -5.1 Flags - - The `flags' specify which of the fields are present. Those fields - for which the corresponding flag is not set are not present (not - included in the packet). New flags can only be added by incrementing - the protocol version number (or by using the extension mechanism - described below). - - The flags bits are defined to have the following values: - - #define SSH_FILEXFER_ATTR_SIZE 0x00000001 - #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004 - #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008 - #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010 - #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020 - #define SSH_FILEXFER_ATTR_ACL 0x00000040 - #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080 - #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000 - - - - -Galbraith, et al. Expires April 16, 2003 [Page 9] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - In previous versions of this protocol flags value 0x00000002 was - SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP - was given a new value in order to ease implementation burden. - 0x00000002 MUST NOT appear in the mask. Some future version of this - protocol may reuse flag 0x00000002. - -5.2 Type - - The type field is always present. The following types are defined: - - #define SSH_FILEXFER_TYPE_REGULAR 1 - #define SSH_FILEXFER_TYPE_DIRECTORY 2 - #define SSH_FILEXFER_TYPE_SYMLINK 3 - #define SSH_FILEXFER_TYPE_SPECIAL 4 - #define SSH_FILEXFER_TYPE_UNKNOWN 5 - - On a POSIX system, these values would be derived from the permission - field. - -5.3 Size - - The `size' field specifies the size of the file on disk, in bytes. - If it is present during file creation, it should be considered a hint - as to the files eventual size. - - Files opened with the SSH_FXF_TEXT flag may have a size that is - greater or less than the value of the size field. - -5.4 Owner and Group - - The `owner' and `group' fields are represented as UTF-8 strings; this - is the form used by NFS v4. See NFS version 4 Protocol. [3] The - following text is selected quotations from section 5.6. - - To avoid a representation that is tied to a particular underlying - implementation at the client or server, the use of UTF-8 strings has - been chosen. The string should be of the form user@dns_domain". - This will allow for a client and server that do not use the same - local representation the ability to translate to a common syntax that - can be interpreted by both. In the case where there is no - translation available to the client or server, the attribute value - must be constructed without the "@". Therefore, the absence of the @ - from the owner or owner_group attribute signifies that no translation - was available and the receiver of the attribute should not place any - special meaning with the attribute value. Even though the attribute - value can not be translated, it may still be useful. In the case of - a client, the attribute string may be used for local display of - ownership. - - - -Galbraith, et al. Expires April 16, 2003 [Page 10] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -5.5 Permissions - - The `permissions' field contains a bit mask of file permissions as - defined by POSIX [1]. - -5.6 Times - - The 'atime', 'createtime', and 'mtime' contain the access, creation, - and modification times of the files, respectively. They are - represented as seconds from Jan 1, 1970 in UTC. - -5.7 ACL - - The 'ACL' field contains an ACL similar to that defined in section - 5.9 of NFS version 4 Protocol [3]. - - uint32 ace-count - - repeated ace-count time: - uint32 ace-type - uint32 ace-flag - uint32 ace-mask - string who [UTF-8] - - ace-type is one of the following four values (taken from NFS Version - 4 Protocol [3]: - - const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; - const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; - const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; - const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; - - ace-flag is a combination of the following flag values. See NFS - Version 4 Protocol [3] section 5.9.2: - - const ACE4_FILE_INHERIT_ACE = 0x00000001; - const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; - const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; - const ACE4_INHERIT_ONLY_ACE = 0x00000008; - const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; - const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; - const ACE4_IDENTIFIER_GROUP = 0x00000040; - - ace-mask is any combination of the following flags (taken from NFS - Version 4 Protocol [3] section 5.9.3: - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 11] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - const ACE4_READ_DATA = 0x00000001; - const ACE4_LIST_DIRECTORY = 0x00000001; - const ACE4_WRITE_DATA = 0x00000002; - const ACE4_ADD_FILE = 0x00000002; - const ACE4_APPEND_DATA = 0x00000004; - const ACE4_ADD_SUBDIRECTORY = 0x00000004; - const ACE4_READ_NAMED_ATTRS = 0x00000008; - const ACE4_WRITE_NAMED_ATTRS = 0x00000010; - const ACE4_EXECUTE = 0x00000020; - const ACE4_DELETE_CHILD = 0x00000040; - const ACE4_READ_ATTRIBUTES = 0x00000080; - const ACE4_WRITE_ATTRIBUTES = 0x00000100; - const ACE4_DELETE = 0x00010000; - const ACE4_READ_ACL = 0x00020000; - const ACE4_WRITE_ACL = 0x00040000; - const ACE4_WRITE_OWNER = 0x00080000; - const ACE4_SYNCHRONIZE = 0x00100000; - - who is a UTF-8 string of the form described in 'Owner and Group' - (Section 5.4) - -5.8 Extended attributes - - The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension - mechanism for vendor-specific extensions. If the flag is specified, - then the `extended_count' field is present. It specifies the number - of extended_type-extended_data pairs that follow. Each of these - pairs specifies an extended attribute. For each of the attributes, - the extended_type field should be a string of the format - "name@domain", where "domain" is a valid, registered domain name and - "name" identifies the method. The IETF may later standardize certain - names that deviate from this format (e.g., that do not contain the - "@" sign). The interpretation of `extended_data' depends on the - type. Implementations SHOULD ignore extended data fields that they - do not understand. - - Additional fields can be added to the attributes by either defining - additional bits to the flags field to indicate their presence, or by - defining extended attributes for them. The extended attributes - mechanism is recommended for most purposes; additional flags bits - should only be defined by an IETF standards action that also - increments the protocol version number. The use of such new fields - MUST be negotiated by the version number in the protocol exchange. - It is a protocol error if a packet with unsupported protocol bits is - received. - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 12] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -6. Requests From the Client to the Server - - Requests from the client to the server represent the various file - system operations. Each request begins with an `id' field, which is - a 32-bit identifier identifying the request (selected by the client). - The same identifier will be returned in the response to the request. - One possible implementation is a monotonically increasing request - sequence number (modulo 2^32). - - Many operations in the protocol operate on open files. The - SSH_FXP_OPEN request can return a file handle (which is an opaque - variable-length string) which may be used to access the file later - (e.g. in a read operation). The client MUST NOT send requests the - server with bogus or closed handles. However, the server MUST - perform adequate checks on the handle in order to avoid security - risks due to fabricated handles. - - This design allows either stateful and stateless server - implementation, as well as an implementation which caches state - between requests but may also flush it. The contents of the file - handle string are entirely up to the server and its design. The - client should not modify or attempt to interpret the file handle - strings. - - The file handle strings MUST NOT be longer than 256 bytes. - -6.1 Request Synchronization and Reordering - - The protocol and implementations MUST process requests relating to - the same file in the order in which they are received. In other - words, if an application submits multiple requests to the server, the - results in the responses will be the same as if it had sent the - requests one at a time and waited for the response in each case. For - example, the server may process non-overlapping read/write requests - to the same file in parallel, but overlapping reads and writes cannot - be reordered or parallelized. However, there are no ordering - restrictions on the server for processing requests from two different - file transfer connections. The server may interleave and parallelize - them at will. - - There are no restrictions on the order in which responses to - outstanding requests are delivered to the client, except that the - server must ensure fairness in the sense that processing of no - request will be indefinitely delayed even if the client is sending - other requests so that there are multiple outstanding requests all - the time. - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 13] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -6.2 File Names - - This protocol represents file names as strings. File names are - assumed to use the slash ('/') character as a directory separator. - - File names starting with a slash are "absolute", and are relative to - the root of the file system. Names starting with any other character - are relative to the user's default directory (home directory). Note - that identifying the user is assumed to take place outside of this - protocol. - - Servers SHOULD interpret a path name component ".." as referring to - the parent directory, and "." as referring to the current directory. - If the server implementation limits access to certain parts of the - file system, it must be extra careful in parsing file names when - enforcing such restrictions. There have been numerous reported - security bugs where a ".." in a path name has allowed access outside - the intended area. - - An empty path name is valid, and it refers to the user's default - directory (usually the user's home directory). - - Otherwise, no syntax is defined for file names by this specification. - Clients should not make any other assumptions; however, they can - splice path name components returned by SSH_FXP_READDIR together - using a slash ('/') as the separator, and that will work as expected. - - In order to comply with IETF Policy on Character Sets and Languages - [2], all filenames are to be encoded in UTF-8. The shortest valid - UTF-8 encoding of the UNICODE data MUST be used. The server is - responsible for converting the UNICODE data to whatever canonical - form it requires. - - For example, if the server requires that precomposed characters - always be used, the server MUST NOT assume the filename as sent by - the client has this attribute, but must do this normalization itself. - - It is understood that the lack of well-defined semantics for file - names may cause interoperability problems between clients and servers - using radically different operating systems. However, this approach - is known to work acceptably with most systems, and alternative - approaches that e.g. treat file names as sequences of structured - components are quite complicated. - -6.3 Opening, Creating, and Closing Files - - Files are opened and created using the SSH_FXP_OPEN message, whose - data part is as follows: - - - -Galbraith, et al. Expires April 16, 2003 [Page 14] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - uint32 id - string filename [UTF-8] - uint32 pflags - ATTRS attrs - - The `id' field is the request identifier as for all requests. - - The `filename' field specifies the file name. See Section ``File - Names'' for more information. - - The `pflags' field is a bitmask. The following bits have been - defined. - - #define SSH_FXF_READ 0x00000001 - #define SSH_FXF_WRITE 0x00000002 - #define SSH_FXF_APPEND 0x00000004 - #define SSH_FXF_CREAT 0x00000008 - #define SSH_FXF_TRUNC 0x00000010 - #define SSH_FXF_EXCL 0x00000020 - #define SSH_FXF_TEXT 0x00000040 - - These have the following meanings: - - SSH_FXF_READ - Open the file for reading. - - SSH_FXF_WRITE - Open the file for writing. If both this and SSH_FXF_READ are - specified, the file is opened for both reading and writing. - - SSH_FXF_APPEND - Force all writes to append data at the end of the file. The - offset parameter to write will be ignored. - - SSH_FXF_CREAT - If this flag is specified, then a new file will be created if one - does not already exist (if O_TRUNC is specified, the new file will - be truncated to zero length if it previously exists). - - SSH_FXF_TRUNC - Forces an existing file with the same name to be truncated to zero - length when creating a file by specifying SSH_FXF_CREAT. - SSH_FXF_CREAT MUST also be specified if this flag is used. - - SSH_FXF_EXCL - Causes the request to fail if the named file already exists. - SSH_FXF_CREAT MUST also be specified if this flag is used. - - - - -Galbraith, et al. Expires April 16, 2003 [Page 15] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - SSH_FXF_TEXT - Indicates that the server should treat the file as text and - convert it to the canonical newline convention in use. (See - Determining Server Newline Convention. (Section 4.3) - - When a file is opened with the FXF_TEXT flag, the offset field in - both the read and write function are ignored. - - Servers MUST correctly process multiple parallel reads and writes - correctly in this mode. Naturally, it is permissible for them to - do this by serializing the requests. It would not be possible for - a client to reliably detect a server that does not implement - parallel writes in time to prevent damage. - - Clients SHOULD use the SSH_FXF_APPEND flag to append data to a - text file rather then using write with a calculated offset. - - To support seeks on text file the following SSH_FXP_EXTENDED - packet is defined. - - - - string "text-seek" - string file-handle - uint64 line-number - - line-number is the index of the line number to seek to, where byte - 0 in the file is line number 0, and the byte directly following - the first newline sequence in the file is line number 1 and so on. - - The response to a "text-seek" request is an SSH_FXP_STATUS - message. - - An attempt to seek past the end-of-file should result in a - SSH_FX_EOF status. - - Servers SHOULD support at least one "text-seek" in order to - support resume. However, a client MUST be prepared to receive - SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation. - The client can then try a fall-back strategy, if it has one. - - Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned - for read or write operations that are not sequential. - - The `attrs' field specifies the initial attributes for the file. - Default values will be used for those attributes that are not - specified. See Section ``File Attributes'' for more information. - - - - -Galbraith, et al. Expires April 16, 2003 [Page 16] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - The response to this message will be either SSH_FXP_HANDLE (if the - operation is successful) or SSH_FXP_STATUS (if the operation fails). - - A file is closed by using the SSH_FXP_CLOSE request. Its data field - has the following format: - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is a handle - previously returned in the response to SSH_FXP_OPEN or - SSH_FXP_OPENDIR. The handle becomes invalid immediately after this - request has been sent. - - The response to this request will be a SSH_FXP_STATUS message. One - should note that on some server platforms even a close can fail. - This can happen e.g. if the server operating system caches writes, - and an error occurs while flushing cached writes during the close. - -6.4 Reading and Writing - - Once a file has been opened, it can be read using the SSH_FXP_READ - message, which has the following format: - - uint32 id - string handle - uint64 offset - uint32 len - - where `id' is the request identifier, `handle' is an open file handle - returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative - to the beginning of the file from where to start reading, and `len' - is the maximum number of bytes to read. - - In response to this request, the server will read as many bytes as it - can from the file (up to `len'), and return them in a SSH_FXP_DATA - message. If an error occurs or EOF is encountered before reading any - data, the server will respond with SSH_FXP_STATUS. For normal disk - files, it is guaranteed that this will read the specified number of - bytes, or up to end of file. For e.g. device files this may return - fewer bytes than requested. - - Writing to a file is achieved using the SSH_FXP_WRITE message, which - has the following format: - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 17] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - uint32 id - string handle - uint64 offset - string data - - where `id' is a request identifier, `handle' is a file handle - returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the - beginning of the file where to start writing, and `data' is the data - to be written. - - The write will extend the file if writing beyond the end of the file. - It is legal to write way beyond the end of the file; the semantics - are to write zeroes from the end of the file to the specified offset - and then the data. On most operating systems, such writes do not - allocate disk space but instead leave "holes" in the file. - - The server responds to a write request with a SSH_FXP_STATUS message. - -6.5 Removing and Renaming Files - - Files can be removed using the SSH_FXP_REMOVE message. It has the - following format: - - uint32 id - string filename [UTF-8] - - where `id' is the request identifier and `filename' is the name of - the file to be removed. See Section ``File Names'' for more - information. This request cannot be used to remove directories. - - The server will respond to this request with a SSH_FXP_STATUS - message. - - Files (and directories) can be renamed using the SSH_FXP_RENAME - message. Its data is as follows: - - uint32 id - string oldpath [UTF-8] - string newpath [UTF-8] - - where `id' is the request identifier, `oldpath' is the name of an - existing file or directory, and `newpath' is the new name for the - file or directory. It is an error if there already exists a file - with the name specified by newpath. The server may also fail rename - requests in other situations, for example if `oldpath' and `newpath' - point to different file systems on the server. - - The server will respond to this request with a SSH_FXP_STATUS - - - -Galbraith, et al. Expires April 16, 2003 [Page 18] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - message. - -6.6 Creating and Deleting Directories - - New directories can be created using the SSH_FXP_MKDIR request. It - has the following format: - - uint32 id - string path [UTF-8] - ATTRS attrs - - where `id' is the request identifier. - - `path' specifies the directory to be created. See Section ``File - Names'' for more information on file names. - - `attrs' specifies the attributes that should be applied to it upon - creation. Attributes are discussed in more detail in Section ``File - Attributes''. - - The server will respond to this request with a SSH_FXP_STATUS - message. If a file or directory with the specified path already - exists, an error will be returned. - - Directories can be removed using the SSH_FXP_RMDIR request, which has - the following format: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier, and `path' specifies the - directory to be removed. See Section ``File Names'' for more - information on file names. - - The server responds to this request with a SSH_FXP_STATUS message. - Errors may be returned from this operation for various reasons, - including, but not limited to, the path does not exist, the path does - not refer to a directory object, the directory is not empty, or the - user has insufficient access or permission to perform the requested - operation. - -6.7 Scanning Directories - - The files in a directory can be listed using the SSH_FXP_OPENDIR and - SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one - or more file names with full file attributes for each file. The - client should call SSH_FXP_READDIR repeatedly until it has found the - file it is looking for or until the server responds with a - - - -Galbraith, et al. Expires April 16, 2003 [Page 19] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if - there are no more files in the directory). The client should then - close the handle using the SSH_FXP_CLOSE request. - - The SSH_FXP_OPENDIR opens a directory for reading. It has the - following format: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier and `path' is the path name of - the directory to be listed (without any trailing slash). See Section - ``File Names'' for more information on file names. This will return - an error if the path does not specify a directory or if the directory - is not readable. The server will respond to this request with either - a SSH_FXP_HANDLE or a SSH_FXP_STATUS message. - - Once the directory has been successfully opened, files (and - directories) contained in it can be listed using SSH_FXP_READDIR - requests. These are of the format - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is a handle - returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to - use an ordinary file handle returned by SSH_FXP_OPEN.) - - The server responds to this request with either a SSH_FXP_NAME or a - SSH_FXP_STATUS message. One or more names may be returned at a time. - Full status information is returned for each name in order to speed - up typical directory listings. - - If there are no more names available to be read, the server MUST - respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF. - - When the client no longer wishes to read more names from the - directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle - should be closed regardless of whether an error has occurred or not. - -6.8 Retrieving File Attributes - - Very often, file attributes are automatically returned by - SSH_FXP_READDIR. However, sometimes there is need to specifically - retrieve the attributes for a named file. This can be done using the - SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests. - - SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT - - - -Galbraith, et al. Expires April 16, 2003 [Page 20] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - follows symbolic links on the server, whereas SSH_FXP_LSTAT does not - follow symbolic links. Both have the same format: - - uint32 id - string path [UTF-8] - uint32 flags - - where `id' is the request identifier, and `path' specifies the file - system object for which status is to be returned. The server - responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS. - - The flags field specify the attribute flags in which the client has - particular interest. This is a hint to the server. For example, - because retrieving owner / group and acl information can be an - expensive operation under some operating systems, the server may - choose not to retrieve this information unless the client expresses a - specific interest in it. - - The client has no guarantee the server will provide all the fields - that it has expressed an interest in. - - SSH_FXP_FSTAT differs from the others in that it returns status - information for an open file (identified by the file handle). Its - format is as follows: - - uint32 id - string handle - uint32 flags - - where `id' is the request identifier and `handle' is a file handle - returned by SSH_FXP_OPEN. The server responds to this request with - SSH_FXP_ATTRS or SSH_FXP_STATUS. - -6.9 Setting File Attributes - - File attributes may be modified using the SSH_FXP_SETSTAT and - SSH_FXP_FSETSTAT requests. These requests are used for operations - such as changing the ownership, permissions or access times, as well - as for truncating a file. - - The SSH_FXP_SETSTAT request is of the following format: - - uint32 id - string path [UTF-8] - ATTRS attrs - - where `id' is the request identifier, `path' specifies the file - system object (e.g. file or directory) whose attributes are to be - - - -Galbraith, et al. Expires April 16, 2003 [Page 21] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - modified, and `attrs' specifies the modifications to be made to its - attributes. Attributes are discussed in more detail in Section - ``File Attributes''. - - An error will be returned if the specified file system object does - not exist or the user does not have sufficient rights to modify the - specified attributes. The server responds to this request with a - SSH_FXP_STATUS message. - - The SSH_FXP_FSETSTAT request modifies the attributes of a file which - is already open. It has the following format: - - uint32 id - string handle - ATTRS attrs - - where `id' is the request identifier, `handle' (MUST be returned by - SSH_FXP_OPEN) identifies the file whose attributes are to be - modified, and `attrs' specifies the modifications to be made to its - attributes. Attributes are discussed in more detail in Section - ``File Attributes''. The server will respond to this request with - SSH_FXP_STATUS. - -6.10 Dealing with Symbolic links - - The SSH_FXP_READLINK request may be used to read the target of a - symbolic link. It would have a data part as follows: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier and `path' specifies the path - name of the symlink to be read. - - The server will respond with a SSH_FXP_NAME packet containing only - one name and a dummy attributes value. The name in the returned - packet contains the target of the link. If an error occurs, the - server may respond with SSH_FXP_STATUS. - - The SSH_FXP_SYMLINK request will create a symbolic link on the - server. It is of the following format - - uint32 id - string linkpath [UTF-8] - string targetpath [UTF-8] - - where `id' is the request identifier, `linkpath' specifies the path - name of the symlink to be created and `targetpath' specifies the - - - -Galbraith, et al. Expires April 16, 2003 [Page 22] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - target of the symlink. The server shall respond with a - SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error - condition. - -6.11 Canonicalizing the Server-Side Path Name - - The SSH_FXP_REALPATH request can be used to have the server - canonicalize any given path name to an absolute path. This is useful - for converting path names containing ".." components or relative - pathnames without a leading slash into absolute paths. The format of - the request is as follows: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier and `path' specifies the path - name to be canonicalized. The server will respond with a - SSH_FXP_NAME packet containing the name in canonical form and a dummy - attributes value. If an error occurs, the server may also respond - with SSH_FXP_STATUS. - -6.11.1 Best practice for dealing with paths - - The client SHOULD treat the results of SSH_FXP_REALPATH as a - canonical absolute path, even if the path does not appear to be - absolute. A client that use REALPATH(".") and treats the result as - absolute, even if there is no leading slash, will continue to - function correctly, even when talking to a Windows NT or VMS style - system, where absolute paths may not begin with a slash. - - For example, if the client wishes to change directory up, and the - server has returned "c:/x/y/z" from REALPATH, the client SHOULD use - "c:/x/y/z/..". - - As a second example, if the client wishes to open the file "x.txt" in - the current directory, and server has returned "dka100:/x/y/z" as the - canonical path of the directory, the client SHOULD open "dka100:/x/y/ - z/x.txt" - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 23] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -7. Responses from the Server to the Client - - The server responds to the client using one of a few response - packets. All requests can return a SSH_FXP_STATUS response upon - failure. When the operation is successful, any of the responses may - be returned (depending on the operation). If no data needs to be - returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK - status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used - to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR - requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ, - SSH_FXP_NAME is used to return one or more file names from a - SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is - used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and - SSH_FXP_FSTAT requests. - - Exactly one response will be returned for each request. Each - response packet contains a request identifier which can be used to - match each response with the corresponding request. Note that it is - legal to have several requests outstanding simultaneously, and the - server is allowed to send responses to them in a different order from - the order in which the requests were sent (the result of their - execution, however, is guaranteed to be as if they had been processed - one at a time in the order in which the requests were sent). - - Response packets are of the same general format as request packets. - Each response packet begins with the request identifier. - - The format of the data portion of the SSH_FXP_STATUS response is as - follows: - - uint32 id - uint32 error/status code - string error message (ISO-10646 UTF-8 [RFC-2279]) - string language tag (as defined in [RFC-1766]) - - where `id' is the request identifier, and `error/status code' - indicates the result of the requested operation. The value SSH_FX_OK - indicates success, and all other values indicate failure. - - Currently, the following values are defined (other values may be - defined by future versions of this protocol): - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 24] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - #define SSH_FX_OK 0 - #define SSH_FX_EOF 1 - #define SSH_FX_NO_SUCH_FILE 2 - #define SSH_FX_PERMISSION_DENIED 3 - #define SSH_FX_FAILURE 4 - #define SSH_FX_BAD_MESSAGE 5 - #define SSH_FX_NO_CONNECTION 6 - #define SSH_FX_CONNECTION_LOST 7 - #define SSH_FX_OP_UNSUPPORTED 8 - #define SSH_FX_INVALID_HANDLE 9 - #define SSH_FX_NO_SUCH_PATH 10 - #define SSH_FX_FILE_ALREADY_EXISTS 11 - #define SSH_FX_WRITE_PROTECT 12 - - SSH_FX_OK - Indicates successful completion of the operation. - - SSH_FX_EOF - indicates end-of-file condition; for SSH_FX_READ it means that no - more data is available in the file, and for SSH_FX_READDIR it - indicates that no more files are contained in the directory. - - SSH_FX_NO_SUCH_FILE - is returned when a reference is made to a file which does not - exist. - - SSH_FX_PERMISSION_DENIED - is returned when the authenticated user does not have sufficient - permissions to perform the operation. - - SSH_FX_FAILURE - is a generic catch-all error message; it should be returned if an - error occurs for which there is no more specific error code - defined. - - SSH_FX_BAD_MESSAGE - may be returned if a badly formatted packet or protocol - incompatibility is detected. - - SSH_FX_NO_CONNECTION - is a pseudo-error which indicates that the client has no - connection to the server (it can only be generated locally by the - client, and MUST NOT be returned by servers). - - SSH_FX_CONNECTION_LOST - is a pseudo-error which indicates that the connection to the - server has been lost (it can only be generated locally by the - client, and MUST NOT be returned by servers). - - - -Galbraith, et al. Expires April 16, 2003 [Page 25] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - SSH_FX_OP_UNSUPPORTED - indicates that an attempt was made to perform an operation which - is not supported for the server (it may be generated locally by - the client if e.g. the version number exchange indicates that a - required feature is not supported by the server, or it may be - returned by the server if the server does not implement an - operation). - - SSH_FX_INVALID_HANDLE - The handle value was invalid. - - SSH_FX_NO_SUCH_PATH - The file path does not exist or is invalid. - - SSH_FX_FILE_ALREADY_EXISTS - The file already exists. - - SSH_FX_WRITE_PROTECT - The file is on read only media, or the media is write protected. - - The SSH_FXP_HANDLE response has the following format: - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is an arbitrary - string that identifies an open file or directory on the server. The - handle is opaque to the client; the client MUST NOT attempt to - interpret or modify it in any way. The length of the handle string - MUST NOT exceed 256 data bytes. - - The SSH_FXP_DATA response has the following format: - - uint32 id - string data - - where `id' is the request identifier, and `data' is an arbitrary byte - string containing the requested data. The data string may be at most - the number of bytes requested in a SSH_FXP_READ request, but may also - be shorter if end of file is reached or if the read is from something - other than a regular file. - - The SSH_FXP_NAME response has the following format: - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 26] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - uint32 id - uint32 count - repeats count times: - string filename [UTF-8] - ATTRS attrs - - where `id' is the request identifier, `count' is the number of names - returned in this response, and the remaining fields repeat `count' - times (so that all three fields are first included for the first - file, then for the second file, etc). In the repeated part, - `filename' is a file name being returned (for SSH_FXP_READDIR, it - will be a relative name within the directory, without any path - components; for SSH_FXP_REALPATH it will be an absolute path name), - and `attrs' is the attributes of the file as described in Section - ``File Attributes''. - - The SSH_FXP_ATTRS response has the following format: - - uint32 id - ATTRS attrs - - where `id' is the request identifier, and `attrs' is the returned - file attributes as described in Section ``File Attributes''. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 27] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -8. Vendor-Specific Extensions - - The SSH_FXP_EXTENDED request provides a generic extension mechanism - for adding vendor-specific commands. The request has the following - format: - - uint32 id - string extended-request - ... any request-specific data ... - - where `id' is the request identifier, and `extended-request' is a - string of the format "name@domain", where domain is an internet - domain name of the vendor defining the request. The rest of the - request is completely vendor-specific, and servers should only - attempt to interpret it if they recognize the `extended-request' - name. - - The server may respond to such requests using any of the response - packets defined in Section ``Responses from the Server to the - Client''. Additionally, the server may also respond with a - SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does - not recognize the `extended-request' name, then the server MUST - respond with SSH_FXP_STATUS with error/status set to - SSH_FX_OP_UNSUPPORTED. - - The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary - extension-specific data from the server to the client. It is of the - following format: - - uint32 id - ... any request-specific data ... - - There is a range of packet types reserved for use by extensions. In - order to avoid collision, extensions that turn on the use of - additional packet types should determine those numbers dynamically. - - The suggested way of doing this is have an extension request from the - client to the server that enables the extension; the extension - response from the server to the client would specify the actual type - values to use, in additional to any other data. - - Extension authors should be mindful of the limited range of packet - types available (there are only 45 values available) and avoid - requiring a new packet type where possible. - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 28] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -9. Security Considerations - - This protocol assumes that it is run over a secure channel and that - the endpoints of the channel have been authenticated. Thus, this - protocol assumes that it is externally protected from network-level - attacks. - - This protocol provides file system access to arbitrary files on the - server (only constrained by the server implementation). It is the - responsibility of the server implementation to enforce any access - controls that may be required to limit the access allowed for any - particular user (the user being authenticated externally to this - protocol, typically using the SSH User Authentication Protocol [8]. - - Care must be taken in the server implementation to check the validity - of received file handle strings. The server should not rely on them - directly; it MUST check the validity of each handle before relying on - it. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 29] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -10. Changes from previous protocol versions - - The SSH File Transfer Protocol has changed over time, before it's - standardization. The following is a description of the incompatible - changes between different versions. - -10.1 Changes between versions 4 and 3 - - Many of the changes between version 4 and version 3 are to the - attribute structure to make it more flexible for non-unix platforms. - - o Make all filenames UTF-8. - - o Added 'newline' extension. - - o Made file attribute owner and group strings so they can actually - be used on disparate systems. - - o Added createtime field, and added separate flags for atime, - createtime, and mtime so they can be set separately. - - o Split the file type out of the permissions field and into it's own - field (which is always present.) - - o Added acl attribute. - - o Added SSH_FXF_TEXT file open flag. - - o Added flags field to the get stat commands so that the client can - specifically request information the server might not normally - included for performance reasons. - - o Removed the long filename from the names structure-- it can now be - built from information available in the attrs structure. - - o Added reserved range of packet numbers for extensions. - - o Added several additional error codes. - - o Change the way version negotiate works slightly. Previously, if - the client version were higher than the server version, the server - was supposed to 'echo back' the clients version. The server now - sends it's own version and the lower of the two is considered to - be the one in use. - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 30] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -10.2 Changes between versions 3 and 2 - - o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added. - - o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were - added. - - o The SSH_FXP_STATUS message was changed to include fields `error - message' and `language tag'. - - -10.3 Changes between versions 2 and 1 - - o The SSH_FXP_RENAME message was added. - - -10.4 Changes between versions 1 and 0 - - o Implementation changes, no actual protocol changes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 31] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -11. Trademark Issues - - "ssh" is a registered trademark of SSH Communications Security Corp - in the United States and/or other countries. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 32] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -References - - [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and - P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January - 1999. - - [2] Alvestrand, H., "IETF Policy on Character Sets and Languages", - BCP 18, RFC 2277, January 1998. - - [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame, - C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC - 3010, December 2000. - - [4] Institute of Electrical and Electronics Engineers, "Information - Technology - Portable Operating System Interface (POSIX) - Part - 1: System Application Program Interface (API) [C Language]", - IEEE Standard 1003.2, 1996. - - [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh- - architecture-13 (work in progress), September 2002. - - [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh- - transport-15 (work in progress), September 2002. - - [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16 - (work in progress), September 2002. - - [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh- - userauth-16 (work in progress), September 2002. - - -Authors' Addresses - - Joseph Galbraith - VanDyke Software - 4848 Tramway Ridge Blvd - Suite 101 - Albuquerque, NM 87111 - US - - Phone: +1 505 332 5700 - EMail: galb-list@vandyke.com - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 33] - -Internet-Draft SSH File Transfer Protocol October 2002 - - - Tatu Ylonen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: ylo@ssh.com - - - Sami Lehtinen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: sjl@ssh.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 34] - -Internet-Draft SSH File Transfer Protocol October 2002 - - -Full Copyright Statement - - Copyright (C) The Internet Society (2002). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires April 16, 2003 [Page 35] - - diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt deleted file mode 100644 index 9f51883cd2..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt +++ /dev/null @@ -1,2130 +0,0 @@ - - - -Secure Shell Working Group J. Galbraith -Internet-Draft VanDyke Software -Expires: June 18, 2003 T. Ylonen - S. Lehtinen - SSH Communications Security Corp - December 18, 2002 - - - SSH File Transfer Protocol - draft-ietf-secsh-filexfer-04.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that - other groups may also distribute working documents as - Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on June 18, 2003. - -Copyright Notice - - Copyright (C) The Internet Society (2002). All Rights Reserved. - -Abstract - - The SSH File Transfer Protocol provides secure file transfer - functionality over any reliable data stream. It is the standard file - transfer protocol for use with the SSH2 protocol. This document - describes the file transfer protocol and its interface to the SSH2 - protocol suite. - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 1] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -Table of Contents - - 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4 - 3. General Packet Format . . . . . . . . . . . . . . . . . . 5 - 3.1 The use of stderr in the server . . . . . . . . . . . . . 6 - 4. Protocol Initialization . . . . . . . . . . . . . . . . . 8 - 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 8 - 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 8 - 4.3 Determining Server Newline Convention . . . . . . . . . . 9 - 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 10 - 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 10 - 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 - 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 - 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 11 - 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 12 - 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 12 - 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 - 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 14 - 6. Requests From the Client to the Server . . . . . . . . . . 15 - 6.1 Request Synchronization and Reordering . . . . . . . . . . 15 - 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 16 - 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 16 - 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 19 - 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 20 - 6.6 Creating and Deleting Directories . . . . . . . . . . . . 21 - 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 21 - 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 22 - 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 23 - 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 24 - 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 25 - 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 25 - 7. Responses from the Server to the Client . . . . . . . . . 26 - 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 30 - 9. Security Considerations . . . . . . . . . . . . . . . . . 31 - 10. Changes from previous protocol versions . . . . . . . . . 32 - 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 32 - 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 33 - 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 33 - 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 33 - 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 34 - References . . . . . . . . . . . . . . . . . . . . . . . . 35 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . 35 - Intellectual Property and Copyright Statements . . . . . . 37 - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 2] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -1. Introduction - - This protocol provides secure file transfer (and more generally file - system access) functionality over a reliable data stream, such as a - channel in the SSH2 protocol [5]. - - This protocol is designed so that it could be used to implement a - secure remote file system service, as well as a secure file transfer - service. - - This protocol assumes that it runs over a secure channel, and that - the server has already authenticated the user at the client end, and - that the identity of the client user is externally available to the - server implementation. - - In general, this protocol follows a simple request-response model. - Each request and response contains a sequence number and multiple - requests may be pending simultaneously. There are a relatively large - number of different request messages, but a small number of possible - response messages. Each request has one or more response messages - that may be returned in result (e.g., a read either returns data or - reports error status). - - The packet format descriptions in this specification follow the - notation presented in the secsh architecture draft. [5] - - Even though this protocol is described in the context of the SSH2 - protocol, this protocol is general and independent of the rest of the - SSH2 protocol suite. It could be used in a number of different - applications, such as secure file transfer over TLS RFC 2246 [1] and - transfer of management information in VPN applications. - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 3] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -2. Use with the SSH Connection Protocol - - When used with the SSH2 Protocol suite, this protocol is intended to - be used from the SSH Connection Protocol [7] as a subsystem, as - described in section ``Starting a Shell or a Command''. The - subsystem name used with this protocol is "sftp". - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 4] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -3. General Packet Format - - All packets transmitted over the secure connection are of the - following format: - - uint32 length - byte type - byte[length - 1] data payload - - That is, they are just data preceded by 32-bit length and 8-bit type - fields. The `length' is the length of the data area, and does not - include the `length' field itself. The format and interpretation of - the data area depends on the packet type. - - All packet descriptions below only specify the packet type and the - data that goes into the data field. Thus, they should be prefixed by - the `length' and `type' fields. - - The maximum size of a packet is in practice determined by the client - (the maximum size of read or write requests that it sends, plus a few - bytes of packet overhead). All servers SHOULD support packets of at - least 34000 bytes (where the packet size refers to the full length, - including the header above). This should allow for reads and writes - of at most 32768 bytes. - - There is no limit on the number of outstanding (non-acknowledged) - requests that the client may send to the server. In practice this is - limited by the buffering available on the data stream and the queuing - performed by the server. If the server's queues are full, it should - not read any more data from the stream, and flow control will prevent - the client from sending more requests. Note, however, that while - there is no restriction on the protocol level, the client's API may - provide a limit in order to prevent infinite queuing of outgoing - requests at the client. - - The following values are defined for packet types. - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 5] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - #define SSH_FXP_INIT 1 - #define SSH_FXP_VERSION 2 - #define SSH_FXP_OPEN 3 - #define SSH_FXP_CLOSE 4 - #define SSH_FXP_READ 5 - #define SSH_FXP_WRITE 6 - #define SSH_FXP_LSTAT 7 - #define SSH_FXP_FSTAT 8 - #define SSH_FXP_SETSTAT 9 - #define SSH_FXP_FSETSTAT 10 - #define SSH_FXP_OPENDIR 11 - #define SSH_FXP_READDIR 12 - #define SSH_FXP_REMOVE 13 - #define SSH_FXP_MKDIR 14 - #define SSH_FXP_RMDIR 15 - #define SSH_FXP_REALPATH 16 - #define SSH_FXP_STAT 17 - #define SSH_FXP_RENAME 18 - #define SSH_FXP_READLINK 19 - #define SSH_FXP_SYMLINK 20 - - #define SSH_FXP_STATUS 101 - #define SSH_FXP_HANDLE 102 - #define SSH_FXP_DATA 103 - #define SSH_FXP_NAME 104 - #define SSH_FXP_ATTRS 105 - - #define SSH_FXP_EXTENDED 200 - #define SSH_FXP_EXTENDED_REPLY 201 - - RESERVED_FOR_EXTENSIONS 210-255 - - Additional packet types should only be defined if the protocol - version number (see Section ``Protocol Initialization'') is - incremented, and their use MUST be negotiated using the version - number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY - packets can be used to implement vendor-specific extensions. See - Section ``Vendor-Specific-Extensions'' for more details. - -3.1 The use of stderr in the server - - Packets are sent and received on stdout and stdin. Data sent on - stderr by the server SHOULD be considered debug or supplemental error - information, and MAY be displayed to the user. - - For example, during initialization, there is no client request - active, so errors or warning information cannot be sent to the client - as part of the SFTP protocol at this early stage. However, the - - - -Galbraith, et al. Expires June 18, 2003 [Page 6] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - errors or warnings MAY be sent as stderr text. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 7] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -4. Protocol Initialization - - When the file transfer protocol starts, the client first sends a - SSH_FXP_INIT (including its version number) packet to the server. - The server responds with a SSH_FXP_VERSION packet, supplying the - lowest of its own and the client's version number. Both parties - should from then on adhere to particular version of the protocol. - - The version number of the protocol specified in this document is 4. - The version number should be incremented for each incompatible - revision of this protocol. - -4.1 Client Initialization - - The SSH_FXP_INIT packet (from client to server) has the following - data: - - uint32 version - - Version 3 of this protocol allowed clients to include extensions in - the SSH_FXP_INIT packet; however, this can cause interoperability - problems with version 1 and version 2 servers because the client must - send this packet before knowing the servers version. - - In this version of the protocol, clients MUST use the - SSH_FXP_EXTENDED packet to send extensions to the server after - version exchange has completed. Clients MUST NOT include extensions - in the version packet. This will prevent interoperability problems - with older servers - -4.2 Server Initialization - - The SSH_FXP_VERSION packet (from server to client) has the following - data: - - uint32 version - - - 'version' is the lower of the protocol version supported by the - server and the version number received from the client. - - The extension data may be empty, or may be a sequence of - - string extension_name - string extension_data - - pairs (both strings MUST always be present if one is, but the - `extension_data' string may be of zero length). If present, these - - - -Galbraith, et al. Expires June 18, 2003 [Page 8] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - strings indicate extensions to the baseline protocol. The - `extension_name' field(s) identify the name of the extension. The - name should be of the form "name@domain", where the domain is the DNS - domain name of the organization defining the extension. Additional - names that are not of this format may be defined later by the IETF. - Implementations MUST silently ignore any extensions whose name they - do not recognize. - -4.3 Determining Server Newline Convention - - In order to correctly process text files in a cross platform - compatible way, the newline convention must be converted from that of - the server to that of the client, or, during an upload, from that of - the client to that of the server. - - Versions 3 and prior of this protocol made no provisions for - processing text files. Many clients implemented some sort of - conversion algorithm, but without either a 'canonical' on the wire - format or knowledge of the servers newline convention, correct - conversion was not always possible. - - Starting with Version 4, the SSH_FXF_TEXT file open flag (Section - 6.3) makes it possible to request that the server translate a file to - a 'canonical' on the wire format. This format uses \r\n as the line - separator. - - Servers for systems using multiple newline characters (for example, - Mac OS X or VMS) or systems using counted records, MUST translate to - the canonical form. - - However, to ease the burden of implementation on servers that use a - single, simple separator sequence, the following extension allows the - canonical format to be changed. - - string "newline" - string new-canonical-separator (usually "\r" or "\n" or "\r\n") - - All clients MUST support this extension. - - When processing text files, clients SHOULD NOT translate any - character or sequence that is not an exact match of the servers - newline separator. - - In particular, if the newline sequence being used is the canonical - "\r\n" sequence, a lone \r or a lone \n SHOULD be written through - without change. - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 9] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -5. File Attributes - - A new compound data type is defined for encoding file attributes. - The same encoding is used both when returning file attributes from - the server and when sending file attributes to the server. When - sending it to the server, the flags field specifies which attributes - are included, and the server will use default values for the - remaining attributes (or will not modify the values of remaining - attributes). When receiving attributes from the server, the flags - specify which attributes are included in the returned data. The - server normally returns all attributes it knows about. - - uint32 flags - byte type always present - uint64 size present only if flag SIZE - string owner present only if flag OWNERGROUP - string group present only if flag OWNERGROUP - uint32 permissions present only if flag PERMISSIONS - uint64 atime present only if flag ACCESSTIME - uint32 atime_nseconds present only if flag SUBSECOND_TIMES - uint64 createtime present only if flag CREATETIME - uint32 createtime_nseconds present only if flag SUBSECOND_TIMES - uint64 mtime present only if flag MODIFYTIME - uint32 mtime_nseconds present only if flag SUBSECOND_TIMES - string acl present only if flag ACL - uint32 extended_count present only if flag EXTENDED - string extended_type - string extended_data - ... more extended data (extended_type - extended_data pairs), - so that number of pairs equals extended_count - - -5.1 Flags - - The `flags' specify which of the fields are present. Those fields - for which the corresponding flag is not set are not present (not - included in the packet). New flags can only be added by incrementing - the protocol version number (or by using the extension mechanism - described below). - - The flags bits are defined to have the following values: - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 10] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - #define SSH_FILEXFER_ATTR_SIZE 0x00000001 - #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000040 - #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008 - #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010 - #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020 - #define SSH_FILEXFER_ATTR_ACL 0x00000040 - #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080 - #define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x00000100 - #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000 - - In previous versions of this protocol flags value 0x00000002 was - SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP - was given a new value in order to ease implementation burden. - 0x00000002 MUST NOT appear in the mask. Some future version of this - protocol may reuse flag 0x00000002. - -5.2 Type - - The type field is always present. The following types are defined: - - #define SSH_FILEXFER_TYPE_REGULAR 1 - #define SSH_FILEXFER_TYPE_DIRECTORY 2 - #define SSH_FILEXFER_TYPE_SYMLINK 3 - #define SSH_FILEXFER_TYPE_SPECIAL 4 - #define SSH_FILEXFER_TYPE_UNKNOWN 5 - - On a POSIX system, these values would be derived from the permission - field. - -5.3 Size - - The `size' field specifies the size of the file on disk, in bytes. - If it is present during file creation, it should be considered a hint - as to the files eventual size. - - Files opened with the SSH_FXF_TEXT flag may have a size that is - greater or less than the value of the size field. - -5.4 Owner and Group - - The `owner' and `group' fields are represented as UTF-8 strings; this - is the form used by NFS v4. See NFS version 4 Protocol. [3] The - following text is selected quotations from section 5.6. - - To avoid a representation that is tied to a particular underlying - implementation at the client or server, the use of UTF-8 strings has - been chosen. The string should be of the form user@dns_domain". - This will allow for a client and server that do not use the same - - - -Galbraith, et al. Expires June 18, 2003 [Page 11] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - local representation the ability to translate to a common syntax that - can be interpreted by both. In the case where there is no - translation available to the client or server, the attribute value - must be constructed without the "@". Therefore, the absence of the @ - from the owner or owner_group attribute signifies that no translation - was available and the receiver of the attribute should not place any - special meaning with the attribute value. Even though the attribute - value can not be translated, it may still be useful. In the case of - a client, the attribute string may be used for local display of - ownership. - -5.5 Permissions - - The `permissions' field contains a bit mask of file permissions as - defined by POSIX [1]. - -5.6 Times - - The 'atime', 'createtime', and 'mtime' contain the access, creation, - and modification times of the files, respectively. They are - represented as seconds from Jan 1, 1970 in UTC. - - A negative value indicates number of seconds before Jan 1, 1970. In - both cases, if the SSH_FILEXFER_ATTR_SUBSECOND_TIMES flag is set, the - nseconds field is to be added to the seconds field for the final time - representation. For example, if the time to be represented is - one-half second before 0 hour January 1, 1970, the seconds field - would have a value of negative one (-1) and the nseconds fields would - have a value of one-half second (500000000). Values greater than - 999,999,999 for nseconds are considered invalid. - -5.7 ACL - - The 'ACL' field contains an ACL similar to that defined in section - 5.9 of NFS version 4 Protocol [3]. - - uint32 ace-count - - repeated ace-count time: - uint32 ace-type - uint32 ace-flag - uint32 ace-mask - string who [UTF-8] - - ace-type is one of the following four values (taken from NFS Version - 4 Protocol [3]: - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 12] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; - const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; - const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; - const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; - - ace-flag is a combination of the following flag values. See NFS - Version 4 Protocol [3] section 5.9.2: - - const ACE4_FILE_INHERIT_ACE = 0x00000001; - const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; - const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; - const ACE4_INHERIT_ONLY_ACE = 0x00000008; - const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; - const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; - const ACE4_IDENTIFIER_GROUP = 0x00000040; - - ace-mask is any combination of the following flags (taken from NFS - Version 4 Protocol [3] section 5.9.3: - - const ACE4_READ_DATA = 0x00000001; - const ACE4_LIST_DIRECTORY = 0x00000001; - const ACE4_WRITE_DATA = 0x00000002; - const ACE4_ADD_FILE = 0x00000002; - const ACE4_APPEND_DATA = 0x00000004; - const ACE4_ADD_SUBDIRECTORY = 0x00000004; - const ACE4_READ_NAMED_ATTRS = 0x00000008; - const ACE4_WRITE_NAMED_ATTRS = 0x00000010; - const ACE4_EXECUTE = 0x00000020; - const ACE4_DELETE_CHILD = 0x00000040; - const ACE4_READ_ATTRIBUTES = 0x00000080; - const ACE4_WRITE_ATTRIBUTES = 0x00000100; - const ACE4_DELETE = 0x00010000; - const ACE4_READ_ACL = 0x00020000; - const ACE4_WRITE_ACL = 0x00040000; - const ACE4_WRITE_OWNER = 0x00080000; - const ACE4_SYNCHRONIZE = 0x00100000; - - who is a UTF-8 string of the form described in 'Owner and Group' - (Section 5.4) - - Also, as per '5.9.4 ACE who' [3] there are several identifiers that - need to be understood universally. Some of these identifiers cannot - be understood when an client access the server, but have meaning when - a local process accesses the file. The ability to display and modify - these permissions is permitted over SFTP. - - OWNER The owner of the file. - - - - -Galbraith, et al. Expires June 18, 2003 [Page 13] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - GROUP The group associated with the file. - - EVERYONE The world. - - INTERACTIVE Accessed from an interactive terminal. - - NETWORK Accessed via the network. - - DIALUP Accessed as a dialup user to the server. - - BATCH Accessed from a batch job. - - ANONYMOUS Accessed without any authentication. - - AUTHENTICATED Any authenticated user (opposite of ANONYMOUS). - - SERVICE Access from a system service. - - To avoid conflict, these special identifiers are distinguish by an - appended "@" and should appear in the form "xxxx@" (note: no domain - name after the "@"). For example: ANONYMOUS@. - -5.8 Extended attributes - - The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension - mechanism for vendor-specific extensions. If the flag is specified, - then the `extended_count' field is present. It specifies the number - of extended_type-extended_data pairs that follow. Each of these - pairs specifies an extended attribute. For each of the attributes, - the extended_type field should be a string of the format - "name@domain", where "domain" is a valid, registered domain name and - "name" identifies the method. The IETF may later standardize certain - names that deviate from this format (e.g., that do not contain the - "@" sign). The interpretation of `extended_data' depends on the - type. Implementations SHOULD ignore extended data fields that they - do not understand. - - Additional fields can be added to the attributes by either defining - additional bits to the flags field to indicate their presence, or by - defining extended attributes for them. The extended attributes - mechanism is recommended for most purposes; additional flags bits - should only be defined by an IETF standards action that also - increments the protocol version number. The use of such new fields - MUST be negotiated by the version number in the protocol exchange. - It is a protocol error if a packet with unsupported protocol bits is - received. - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 14] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -6. Requests From the Client to the Server - - Requests from the client to the server represent the various file - system operations. Each request begins with an `id' field, which is - a 32-bit identifier identifying the request (selected by the client). - The same identifier will be returned in the response to the request. - One possible implementation is a monotonically increasing request - sequence number (modulo 2^32). - - Many operations in the protocol operate on open files. The - SSH_FXP_OPEN request can return a file handle (which is an opaque - variable-length string) which may be used to access the file later - (e.g. in a read operation). The client MUST NOT send requests the - server with bogus or closed handles. However, the server MUST - perform adequate checks on the handle in order to avoid security - risks due to fabricated handles. - - This design allows either stateful and stateless server - implementation, as well as an implementation which caches state - between requests but may also flush it. The contents of the file - handle string are entirely up to the server and its design. The - client should not modify or attempt to interpret the file handle - strings. - - The file handle strings MUST NOT be longer than 256 bytes. - -6.1 Request Synchronization and Reordering - - The protocol and implementations MUST process requests relating to - the same file in the order in which they are received. In other - words, if an application submits multiple requests to the server, the - results in the responses will be the same as if it had sent the - requests one at a time and waited for the response in each case. For - example, the server may process non-overlapping read/write requests - to the same file in parallel, but overlapping reads and writes cannot - be reordered or parallelized. However, there are no ordering - restrictions on the server for processing requests from two different - file transfer connections. The server may interleave and parallelize - them at will. - - There are no restrictions on the order in which responses to - outstanding requests are delivered to the client, except that the - server must ensure fairness in the sense that processing of no - request will be indefinitely delayed even if the client is sending - other requests so that there are multiple outstanding requests all - the time. - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 15] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -6.2 File Names - - This protocol represents file names as strings. File names are - assumed to use the slash ('/') character as a directory separator. - - File names starting with a slash are "absolute", and are relative to - the root of the file system. Names starting with any other character - are relative to the user's default directory (home directory). Note - that identifying the user is assumed to take place outside of this - protocol. - - Servers SHOULD interpret a path name component ".." as referring to - the parent directory, and "." as referring to the current directory. - If the server implementation limits access to certain parts of the - file system, it must be extra careful in parsing file names when - enforcing such restrictions. There have been numerous reported - security bugs where a ".." in a path name has allowed access outside - the intended area. - - An empty path name is valid, and it refers to the user's default - directory (usually the user's home directory). - - Otherwise, no syntax is defined for file names by this specification. - Clients should not make any other assumptions; however, they can - splice path name components returned by SSH_FXP_READDIR together - using a slash ('/') as the separator, and that will work as expected. - - In order to comply with IETF Policy on Character Sets and Languages - [2], all filenames are to be encoded in UTF-8. The shortest valid - UTF-8 encoding of the UNICODE data MUST be used. The server is - responsible for converting the UNICODE data to whatever canonical - form it requires. - - For example, if the server requires that precomposed characters - always be used, the server MUST NOT assume the filename as sent by - the client has this attribute, but must do this normalization itself. - - It is understood that the lack of well-defined semantics for file - names may cause interoperability problems between clients and servers - using radically different operating systems. However, this approach - is known to work acceptably with most systems, and alternative - approaches that e.g. treat file names as sequences of structured - components are quite complicated. - -6.3 Opening, Creating, and Closing Files - - Files are opened and created using the SSH_FXP_OPEN message, whose - data part is as follows: - - - -Galbraith, et al. Expires June 18, 2003 [Page 16] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - uint32 id - string filename [UTF-8] - uint32 pflags - ATTRS attrs - - The `id' field is the request identifier as for all requests. - - The `filename' field specifies the file name. See Section ``File - Names'' for more information. - - The `pflags' field is a bitmask. The following bits have been - defined. - - #define SSH_FXF_READ 0x00000001 - #define SSH_FXF_WRITE 0x00000002 - #define SSH_FXF_APPEND 0x00000004 - #define SSH_FXF_CREAT 0x00000008 - #define SSH_FXF_TRUNC 0x00000010 - #define SSH_FXF_EXCL 0x00000020 - #define SSH_FXF_TEXT 0x00000040 - - These have the following meanings: - - SSH_FXF_READ - Open the file for reading. - - SSH_FXF_WRITE - Open the file for writing. If both this and SSH_FXF_READ are - specified, the file is opened for both reading and writing. - - SSH_FXF_APPEND - Force all writes to append data at the end of the file. The - offset parameter to write will be ignored. - - SSH_FXF_CREAT - If this flag is specified, then a new file will be created if one - does not already exist (if O_TRUNC is specified, the new file will - be truncated to zero length if it previously exists). - - SSH_FXF_TRUNC - Forces an existing file with the same name to be truncated to zero - length when creating a file by specifying SSH_FXF_CREAT. - SSH_FXF_CREAT MUST also be specified if this flag is used. - - SSH_FXF_EXCL - Causes the request to fail if the named file already exists. - SSH_FXF_CREAT MUST also be specified if this flag is used. - - - - -Galbraith, et al. Expires June 18, 2003 [Page 17] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - SSH_FXF_TEXT - Indicates that the server should treat the file as text and - convert it to the canonical newline convention in use. (See - Determining Server Newline Convention. (Section 4.3) - - When a file is opened with the FXF_TEXT flag, the offset field in - both the read and write function are ignored. - - Servers MUST correctly process multiple parallel reads and writes - correctly in this mode. Naturally, it is permissible for them to - do this by serializing the requests. It would not be possible for - a client to reliably detect a server that does not implement - parallel writes in time to prevent damage. - - Clients SHOULD use the SSH_FXF_APPEND flag to append data to a - text file rather then using write with a calculated offset. - - To support seeks on text file the following SSH_FXP_EXTENDED - packet is defined. - - - - string "text-seek" - string file-handle - uint64 line-number - - line-number is the index of the line number to seek to, where byte - 0 in the file is line number 0, and the byte directly following - the first newline sequence in the file is line number 1 and so on. - - The response to a "text-seek" request is an SSH_FXP_STATUS - message. - - An attempt to seek past the end-of-file should result in a - SSH_FX_EOF status. - - Servers SHOULD support at least one "text-seek" in order to - support resume. However, a client MUST be prepared to receive - SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation. - The client can then try a fall-back strategy, if it has one. - - Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned - for read or write operations that are not sequential. - - The `attrs' field specifies the initial attributes for the file. - Default values will be used for those attributes that are not - specified. See Section ``File Attributes'' for more information. - - - - -Galbraith, et al. Expires June 18, 2003 [Page 18] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - The response to this message will be either SSH_FXP_HANDLE (if the - operation is successful) or SSH_FXP_STATUS (if the operation fails). - - A file is closed by using the SSH_FXP_CLOSE request. Its data field - has the following format: - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is a handle - previously returned in the response to SSH_FXP_OPEN or - SSH_FXP_OPENDIR. The handle becomes invalid immediately after this - request has been sent. - - The response to this request will be a SSH_FXP_STATUS message. One - should note that on some server platforms even a close can fail. - This can happen e.g. if the server operating system caches writes, - and an error occurs while flushing cached writes during the close. - -6.4 Reading and Writing - - Once a file has been opened, it can be read using the following - message: - - byte SSH_FXP_READ - uint32 id - string handle - uint64 offset - uint32 len - - where `id' is the request identifier, `handle' is an open file handle - returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative - to the beginning of the file from where to start reading, and `len' - is the maximum number of bytes to read. - - In response to this request, the server will read as many bytes as it - can from the file (up to `len'), and return them in a SSH_FXP_DATA - message. If an error occurs or EOF is encountered before reading any - data, the server will respond with SSH_FXP_STATUS. - - For normal disk files, it is normally guaranteed that this will read - the specified number of bytes, or up to end of file. However, if the - read length is very long, the server may truncate it if it doesn't - support packets of that length. See General Packet Format (Section - 3). - - For e.g. device files this may return fewer bytes than requested. - - - - -Galbraith, et al. Expires June 18, 2003 [Page 19] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - Writing to a file is achieved using the following message: - - byte SSH_FXP_WRITE - uint32 id - string handle - uint64 offset - string data - - where `id' is a request identifier, `handle' is a file handle - returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the - beginning of the file where to start writing, and `data' is the data - to be written. - - The write will extend the file if writing beyond the end of the file. - It is legal to write way beyond the end of the file; the semantics - are to write zeroes from the end of the file to the specified offset - and then the data. On most operating systems, such writes do not - allocate disk space but instead leave "holes" in the file. - - The server responds to a write request with a SSH_FXP_STATUS message. - -6.5 Removing and Renaming Files - - Files can be removed using the SSH_FXP_REMOVE message. It has the - following format: - - uint32 id - string filename [UTF-8] - - where `id' is the request identifier and `filename' is the name of - the file to be removed. See Section ``File Names'' for more - information. This request cannot be used to remove directories. - - The server will respond to this request with a SSH_FXP_STATUS - message. - - Files (and directories) can be renamed using the SSH_FXP_RENAME - message. Its data is as follows: - - uint32 id - string oldpath [UTF-8] - string newpath [UTF-8] - - where `id' is the request identifier, `oldpath' is the name of an - existing file or directory, and `newpath' is the new name for the - file or directory. It is an error if there already exists a file - with the name specified by newpath. The server may also fail rename - requests in other situations, for example if `oldpath' and `newpath' - - - -Galbraith, et al. Expires June 18, 2003 [Page 20] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - point to different file systems on the server. - - The server will respond to this request with a SSH_FXP_STATUS - message. - -6.6 Creating and Deleting Directories - - New directories can be created using the SSH_FXP_MKDIR request. It - has the following format: - - uint32 id - string path [UTF-8] - ATTRS attrs - - where `id' is the request identifier. - - `path' specifies the directory to be created. See Section ``File - Names'' for more information on file names. - - `attrs' specifies the attributes that should be applied to it upon - creation. Attributes are discussed in more detail in Section ``File - Attributes''. - - The server will respond to this request with a SSH_FXP_STATUS - message. If a file or directory with the specified path already - exists, an error will be returned. - - Directories can be removed using the SSH_FXP_RMDIR request, which has - the following format: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier, and `path' specifies the - directory to be removed. See Section ``File Names'' for more - information on file names. - - The server responds to this request with a SSH_FXP_STATUS message. - Errors may be returned from this operation for various reasons, - including, but not limited to, the path does not exist, the path does - not refer to a directory object, the directory is not empty, or the - user has insufficient access or permission to perform the requested - operation. - -6.7 Scanning Directories - - The files in a directory can be listed using the SSH_FXP_OPENDIR and - SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one - - - -Galbraith, et al. Expires June 18, 2003 [Page 21] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - or more file names with full file attributes for each file. The - client should call SSH_FXP_READDIR repeatedly until it has found the - file it is looking for or until the server responds with a - SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if - there are no more files in the directory). The client should then - close the handle using the SSH_FXP_CLOSE request. - - The SSH_FXP_OPENDIR opens a directory for reading. It has the - following format: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier and `path' is the path name of - the directory to be listed (without any trailing slash). See Section - ``File Names'' for more information on file names. This will return - an error if the path does not specify a directory or if the directory - is not readable. The server will respond to this request with either - a SSH_FXP_HANDLE or a SSH_FXP_STATUS message. - - Once the directory has been successfully opened, files (and - directories) contained in it can be listed using SSH_FXP_READDIR - requests. These are of the format - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is a handle - returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to - use an ordinary file handle returned by SSH_FXP_OPEN.) - - The server responds to this request with either a SSH_FXP_NAME or a - SSH_FXP_STATUS message. One or more names may be returned at a time. - Full status information is returned for each name in order to speed - up typical directory listings. - - If there are no more names available to be read, the server MUST - respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF. - - When the client no longer wishes to read more names from the - directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle - should be closed regardless of whether an error has occurred or not. - -6.8 Retrieving File Attributes - - Very often, file attributes are automatically returned by - SSH_FXP_READDIR. However, sometimes there is need to specifically - retrieve the attributes for a named file. This can be done using the - - - -Galbraith, et al. Expires June 18, 2003 [Page 22] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests. - - SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT - follows symbolic links on the server, whereas SSH_FXP_LSTAT does not - follow symbolic links. Both have the same format: - - uint32 id - string path [UTF-8] - uint32 flags - - where `id' is the request identifier, and `path' specifies the file - system object for which status is to be returned. The server - responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS. - - The flags field specify the attribute flags in which the client has - particular interest. This is a hint to the server. For example, - because retrieving owner / group and acl information can be an - expensive operation under some operating systems, the server may - choose not to retrieve this information unless the client expresses a - specific interest in it. - - The client has no guarantee the server will provide all the fields - that it has expressed an interest in. - - SSH_FXP_FSTAT differs from the others in that it returns status - information for an open file (identified by the file handle). Its - format is as follows: - - uint32 id - string handle - uint32 flags - - where `id' is the request identifier and `handle' is a file handle - returned by SSH_FXP_OPEN. The server responds to this request with - SSH_FXP_ATTRS or SSH_FXP_STATUS. - -6.9 Setting File Attributes - - File attributes may be modified using the SSH_FXP_SETSTAT and - SSH_FXP_FSETSTAT requests. These requests are used for operations - such as changing the ownership, permissions or access times, as well - as for truncating a file. - - The SSH_FXP_SETSTAT request is of the following format: - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 23] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - uint32 id - string path [UTF-8] - ATTRS attrs - - where `id' is the request identifier, `path' specifies the file - system object (e.g. file or directory) whose attributes are to be - modified, and `attrs' specifies the modifications to be made to its - attributes. Attributes are discussed in more detail in Section - ``File Attributes''. - - An error will be returned if the specified file system object does - not exist or the user does not have sufficient rights to modify the - specified attributes. The server responds to this request with a - SSH_FXP_STATUS message. - - The SSH_FXP_FSETSTAT request modifies the attributes of a file which - is already open. It has the following format: - - uint32 id - string handle - ATTRS attrs - - where `id' is the request identifier, `handle' (MUST be returned by - SSH_FXP_OPEN) identifies the file whose attributes are to be - modified, and `attrs' specifies the modifications to be made to its - attributes. Attributes are discussed in more detail in Section - ``File Attributes''. The server will respond to this request with - SSH_FXP_STATUS. - -6.10 Dealing with Symbolic links - - The SSH_FXP_READLINK request may be used to read the target of a - symbolic link. It would have a data part as follows: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier and `path' specifies the path - name of the symlink to be read. - - The server will respond with a SSH_FXP_NAME packet containing only - one name and a dummy attributes value. The name in the returned - packet contains the target of the link. If an error occurs, the - server may respond with SSH_FXP_STATUS. - - The SSH_FXP_SYMLINK request will create a symbolic link on the - server. It is of the following format - - - - -Galbraith, et al. Expires June 18, 2003 [Page 24] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - uint32 id - string linkpath [UTF-8] - string targetpath [UTF-8] - - where `id' is the request identifier, `linkpath' specifies the path - name of the symlink to be created and `targetpath' specifies the - target of the symlink. The server shall respond with a - SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error - condition. - -6.11 Canonicalizing the Server-Side Path Name - - The SSH_FXP_REALPATH request can be used to have the server - canonicalize any given path name to an absolute path. This is useful - for converting path names containing ".." components or relative - pathnames without a leading slash into absolute paths. The format of - the request is as follows: - - uint32 id - string path [UTF-8] - - where `id' is the request identifier and `path' specifies the path - name to be canonicalized. The server will respond with a - SSH_FXP_NAME packet containing the name in canonical form and a dummy - attributes value. If an error occurs, the server may also respond - with SSH_FXP_STATUS. - -6.11.1 Best practice for dealing with paths - - The client SHOULD treat the results of SSH_FXP_REALPATH as a - canonical absolute path, even if the path does not appear to be - absolute. A client that use REALPATH(".") and treats the result as - absolute, even if there is no leading slash, will continue to - function correctly, even when talking to a Windows NT or VMS style - system, where absolute paths may not begin with a slash. - - For example, if the client wishes to change directory up, and the - server has returned "c:/x/y/z" from REALPATH, the client SHOULD use - "c:/x/y/z/..". - - As a second example, if the client wishes to open the file "x.txt" in - the current directory, and server has returned "dka100:/x/y/z" as the - canonical path of the directory, the client SHOULD open "dka100:/x/y/ - z/x.txt" - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 25] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -7. Responses from the Server to the Client - - The server responds to the client using one of a few response - packets. All requests can return a SSH_FXP_STATUS response upon - failure. When the operation is successful, any of the responses may - be returned (depending on the operation). If no data needs to be - returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK - status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used - to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR - requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ, - SSH_FXP_NAME is used to return one or more file names from a - SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is - used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and - SSH_FXP_FSTAT requests. - - Exactly one response will be returned for each request. Each - response packet contains a request identifier which can be used to - match each response with the corresponding request. Note that it is - legal to have several requests outstanding simultaneously, and the - server is allowed to send responses to them in a different order from - the order in which the requests were sent (the result of their - execution, however, is guaranteed to be as if they had been processed - one at a time in the order in which the requests were sent). - - Response packets are of the same general format as request packets. - Each response packet begins with the request identifier. - - The format of the data portion of the SSH_FXP_STATUS response is as - follows: - - uint32 id - uint32 error/status code - string error message (ISO-10646 UTF-8 [RFC-2279]) - string language tag (as defined in [RFC-1766]) - - where `id' is the request identifier, and `error/status code' - indicates the result of the requested operation. The value SSH_FX_OK - indicates success, and all other values indicate failure. - - Currently, the following values are defined (other values may be - defined by future versions of this protocol): - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 26] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - #define SSH_FX_OK 0 - #define SSH_FX_EOF 1 - #define SSH_FX_NO_SUCH_FILE 2 - #define SSH_FX_PERMISSION_DENIED 3 - #define SSH_FX_FAILURE 4 - #define SSH_FX_BAD_MESSAGE 5 - #define SSH_FX_NO_CONNECTION 6 - #define SSH_FX_CONNECTION_LOST 7 - #define SSH_FX_OP_UNSUPPORTED 8 - #define SSH_FX_INVALID_HANDLE 9 - #define SSH_FX_NO_SUCH_PATH 10 - #define SSH_FX_FILE_ALREADY_EXISTS 11 - #define SSH_FX_WRITE_PROTECT 12 - #define SSH_FX_NO_MEDIA 13 - - SSH_FX_OK - Indicates successful completion of the operation. - - SSH_FX_EOF - indicates end-of-file condition; for SSH_FX_READ it means that no - more data is available in the file, and for SSH_FX_READDIR it - indicates that no more files are contained in the directory. - - SSH_FX_NO_SUCH_FILE - is returned when a reference is made to a file which does not - exist. - - SSH_FX_PERMISSION_DENIED - is returned when the authenticated user does not have sufficient - permissions to perform the operation. - - SSH_FX_FAILURE - is a generic catch-all error message; it should be returned if an - error occurs for which there is no more specific error code - defined. - - SSH_FX_BAD_MESSAGE - may be returned if a badly formatted packet or protocol - incompatibility is detected. - - SSH_FX_NO_CONNECTION - is a pseudo-error which indicates that the client has no - connection to the server (it can only be generated locally by the - client, and MUST NOT be returned by servers). - - SSH_FX_CONNECTION_LOST - is a pseudo-error which indicates that the connection to the - server has been lost (it can only be generated locally by the - - - -Galbraith, et al. Expires June 18, 2003 [Page 27] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - client, and MUST NOT be returned by servers). - - SSH_FX_OP_UNSUPPORTED - indicates that an attempt was made to perform an operation which - is not supported for the server (it may be generated locally by - the client if e.g. the version number exchange indicates that a - required feature is not supported by the server, or it may be - returned by the server if the server does not implement an - operation). - - SSH_FX_INVALID_HANDLE - The handle value was invalid. - - SSH_FX_NO_SUCH_PATH - The file path does not exist or is invalid. - - SSH_FX_FILE_ALREADY_EXISTS - The file already exists. - - SSH_FX_WRITE_PROTECT - The file is on read only media, or the media is write protected. - - SSH_FX_NO_MEDIA - The requested operation can not be completed because there is no - media available in the drive. - - The SSH_FXP_HANDLE response has the following format: - - uint32 id - string handle - - where `id' is the request identifier, and `handle' is an arbitrary - string that identifies an open file or directory on the server. The - handle is opaque to the client; the client MUST NOT attempt to - interpret or modify it in any way. The length of the handle string - MUST NOT exceed 256 data bytes. - - The SSH_FXP_DATA response has the following format: - - uint32 id - string data - - where `id' is the request identifier, and `data' is an arbitrary byte - string containing the requested data. The data string may be at most - the number of bytes requested in a SSH_FXP_READ request, but may also - be shorter if end of file is reached or if the read is from something - other than a regular file. - - - - -Galbraith, et al. Expires June 18, 2003 [Page 28] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - The SSH_FXP_NAME response has the following format: - - uint32 id - uint32 count - repeats count times: - string filename [UTF-8] - ATTRS attrs - - where `id' is the request identifier, `count' is the number of names - returned in this response, and the remaining fields repeat `count' - times (so that all three fields are first included for the first - file, then for the second file, etc). In the repeated part, - `filename' is a file name being returned (for SSH_FXP_READDIR, it - will be a relative name within the directory, without any path - components; for SSH_FXP_REALPATH it will be an absolute path name), - and `attrs' is the attributes of the file as described in Section - ``File Attributes''. - - The SSH_FXP_ATTRS response has the following format: - - uint32 id - ATTRS attrs - - where `id' is the request identifier, and `attrs' is the returned - file attributes as described in Section ``File Attributes''. - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 29] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -8. Vendor-Specific Extensions - - The SSH_FXP_EXTENDED request provides a generic extension mechanism - for adding vendor-specific commands. The request has the following - format: - - uint32 id - string extended-request - ... any request-specific data ... - - where `id' is the request identifier, and `extended-request' is a - string of the format "name@domain", where domain is an internet - domain name of the vendor defining the request. The rest of the - request is completely vendor-specific, and servers should only - attempt to interpret it if they recognize the `extended-request' - name. - - The server may respond to such requests using any of the response - packets defined in Section ``Responses from the Server to the - Client''. Additionally, the server may also respond with a - SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does - not recognize the `extended-request' name, then the server MUST - respond with SSH_FXP_STATUS with error/status set to - SSH_FX_OP_UNSUPPORTED. - - The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary - extension-specific data from the server to the client. It is of the - following format: - - uint32 id - ... any request-specific data ... - - There is a range of packet types reserved for use by extensions. In - order to avoid collision, extensions that turn on the use of - additional packet types should determine those numbers dynamically. - - The suggested way of doing this is have an extension request from the - client to the server that enables the extension; the extension - response from the server to the client would specify the actual type - values to use, in additional to any other data. - - Extension authors should be mindful of the limited range of packet - types available (there are only 45 values available) and avoid - requiring a new packet type where possible. - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 30] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -9. Security Considerations - - This protocol assumes that it is run over a secure channel and that - the endpoints of the channel have been authenticated. Thus, this - protocol assumes that it is externally protected from network-level - attacks. - - This protocol provides file system access to arbitrary files on the - server (only constrained by the server implementation). It is the - responsibility of the server implementation to enforce any access - controls that may be required to limit the access allowed for any - particular user (the user being authenticated externally to this - protocol, typically using the SSH User Authentication Protocol [8]. - - Care must be taken in the server implementation to check the validity - of received file handle strings. The server should not rely on them - directly; it MUST check the validity of each handle before relying on - it. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 31] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -10. Changes from previous protocol versions - - The SSH File Transfer Protocol has changed over time, before it's - standardization. The following is a description of the incompatible - changes between different versions. - -10.1 Changes between versions 4 and 3 - - Many of the changes between version 4 and version 3 are to the - attribute structure to make it more flexible for non-unix platforms. - - o Clarify the use of stderr by the server. - - o Clarify handling of very large read requests by the server. - - o Make all filenames UTF-8. - - o Added 'newline' extension. - - o Made time fields 64 bit, and optionally have nanosecond resultion. - - o Made file attribute owner and group strings so they can actually - be used on disparate systems. - - o Added createtime field, and added separate flags for atime, - createtime, and mtime so they can be set separately. - - o Split the file type out of the permissions field and into it's own - field (which is always present.) - - o Added acl attribute. - - o Added SSH_FXF_TEXT file open flag. - - o Added flags field to the get stat commands so that the client can - specifically request information the server might not normally - included for performance reasons. - - o Removed the long filename from the names structure-- it can now be - built from information available in the attrs structure. - - o Added reserved range of packet numbers for extensions. - - o Added several additional error codes. - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 32] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -10.2 Changes between versions 3 and 2 - - o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added. - - o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were - added. - - o The SSH_FXP_STATUS message was changed to include fields `error - message' and `language tag'. - - -10.3 Changes between versions 2 and 1 - - o The SSH_FXP_RENAME message was added. - - -10.4 Changes between versions 1 and 0 - - o Implementation changes, no actual protocol changes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 33] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -11. Trademark Issues - - "ssh" is a registered trademark of SSH Communications Security Corp - in the United States and/or other countries. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 34] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -References - - [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and - P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January - 1999. - - [2] Alvestrand, H., "IETF Policy on Character Sets and Languages", - BCP 18, RFC 2277, January 1998. - - [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame, - C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC - 3010, December 2000. - - [4] Institute of Electrical and Electronics Engineers, "Information - Technology - Portable Operating System Interface (POSIX) - Part - 1: System Application Program Interface (API) [C Language]", - IEEE Standard 1003.2, 1996. - - [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Protocol Architecture", - draft-ietf-secsh-architecture-13 (work in progress), September - 2002. - - [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Protocol Transport Protocol", - draft-ietf-secsh-transport-15 (work in progress), September - 2002. - - [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16 - (work in progress), September 2002. - - [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S. - Lehtinen, "SSH Authentication Protocol", - draft-ietf-secsh-userauth-16 (work in progress), September 2002. - - -Authors' Addresses - - Joseph Galbraith - VanDyke Software - 4848 Tramway Ridge Blvd - Suite 101 - Albuquerque, NM 87111 - US - - Phone: +1 505 332 5700 - EMail: galb-list@vandyke.com - - - -Galbraith, et al. Expires June 18, 2003 [Page 35] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - Tatu Ylonen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: ylo@ssh.com - - - Sami Lehtinen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: sjl@ssh.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 36] - -Internet-Draft SSH File Transfer Protocol December 2002 - - -Intellectual Property Statement - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementors or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - -Full Copyright Statement - - Copyright (C) The Internet Society (2002). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assignees. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - - - -Galbraith, et al. Expires June 18, 2003 [Page 37] - -Internet-Draft SSH File Transfer Protocol December 2002 - - - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Galbraith, et al. Expires June 18, 2003 [Page 38] - - diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps deleted file mode 100644 index d692285b4e..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps +++ /dev/null @@ -1,3205 +0,0 @@ -%!PS-Adobe-3.0 -%%BoundingBox: 75 0 595 747 -%%Title: Enscript Output -%%For: Magnus Thoang -%%Creator: GNU enscript 1.6.1 -%%CreationDate: Fri Oct 31 13:35:14 2003 -%%Orientation: Portrait -%%Pages: 15 0 -%%DocumentMedia: A4 595 842 0 () () -%%DocumentNeededResources: (atend) -%%EndComments -%%BeginProlog -%%BeginProcSet: PStoPS 1 15 -userdict begin -[/showpage/erasepage/copypage]{dup where{pop dup load - type/operatortype eq{1 array cvx dup 0 3 index cvx put - bind def}{pop}ifelse}{pop}ifelse}forall -[/letter/legal/executivepage/a4/a4small/b5/com10envelope - /monarchenvelope/c5envelope/dlenvelope/lettersmall/note - /folio/quarto/a5]{dup where{dup wcheck{exch{}put} - {pop{}def}ifelse}{pop}ifelse}forall -/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put} - {pop def}ifelse}{def}ifelse -/PStoPSmatrix matrix currentmatrix def -/PStoPSxform matrix def/PStoPSclip{clippath}def -/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def -/initmatrix{matrix defaultmatrix setmatrix}bind def -/initclip[{matrix currentmatrix PStoPSmatrix setmatrix - [{currentpoint}stopped{$error/newerror false put{newpath}} - {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse] - {[/newpath cvx{/moveto cvx}{/lineto cvx} - {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop} - stopped{$error/errorname get/invalidaccess eq{cleartomark - $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop - /initclip dup load dup type dup/operatortype eq{pop exch pop} - {dup/arraytype eq exch/packedarraytype eq or - {dup xcheck{exch pop aload pop}{pop cvx}ifelse} - {pop cvx}ifelse}ifelse - {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def -/initgraphics{initmatrix newpath initclip 1 setlinewidth - 0 setlinecap 0 setlinejoin []0 setdash 0 setgray - 10 setmiterlimit}bind def -end -%%EndProcSet -%%BeginResource: procset Enscript-Prolog 1.6 1 -% -% Procedures. -% - -/_S { % save current state - /_s save def -} def -/_R { % restore from saved state - _s restore -} def - -/S { % showpage protecting gstate - gsave - showpage - grestore -} bind def - -/MF { % fontname newfontname -> - make a new encoded font - /newfontname exch def - /fontname exch def - - /fontdict fontname findfont def - /newfont fontdict maxlength dict def - - fontdict { - exch - dup /FID eq { - % skip FID pair - pop pop - } { - % copy to the new font dictionary - exch newfont 3 1 roll put - } ifelse - } forall - - newfont /FontName newfontname put - - % insert only valid encoding vectors - encoding_vector length 256 eq { - newfont /Encoding encoding_vector put - } if - - newfontname newfont definefont pop -} def - -/SF { % fontname width height -> - set a new font - /height exch def - /width exch def - - findfont - [width 0 0 height 0 0] makefont setfont -} def - -/SUF { % fontname width height -> - set a new user font - /height exch def - /width exch def - - /F-gs-user-font MF - /F-gs-user-font width height SF -} def - -/M {moveto} bind def -/s {show} bind def - -/Box { % x y w h -> - define box path - /d_h exch def /d_w exch def /d_y exch def /d_x exch def - d_x d_y moveto - d_w 0 rlineto - 0 d_h rlineto - d_w neg 0 rlineto - closepath -} def - -/bgs { % x y height blskip gray str -> - show string with bg color - /str exch def - /gray exch def - /blskip exch def - /height exch def - /y exch def - /x exch def - - gsave - x y blskip sub str stringwidth pop height Box - gray setgray - fill - grestore - x y M str s -} def - -% Highlight bars. -/highlight_bars { % nlines lineheight output_y_margin gray -> - - gsave - setgray - /ymarg exch def - /lineheight exch def - /nlines exch def - - % This 2 is just a magic number to sync highlight lines to text. - 0 d_header_y ymarg sub 2 sub translate - - /cw d_output_w cols div def - /nrows d_output_h ymarg 2 mul sub lineheight div cvi def - - % for each column - 0 1 cols 1 sub { - cw mul /xp exch def - - % for each rows - 0 1 nrows 1 sub { - /rn exch def - rn lineheight mul neg /yp exch def - rn nlines idiv 2 mod 0 eq { - % Draw highlight bar. 4 is just a magic indentation. - xp 4 add yp cw 8 sub lineheight neg Box fill - } if - } for - } for - - grestore -} def - -% Line highlight bar. -/line_highlight { % x y width height gray -> - - gsave - /gray exch def - Box gray setgray fill - grestore -} def - -% Column separator lines. -/column_lines { - gsave - .1 setlinewidth - 0 d_footer_h translate - /cw d_output_w cols div def - 1 1 cols 1 sub { - cw mul 0 moveto - 0 d_output_h rlineto stroke - } for - grestore -} def - -% Column borders. -/column_borders { - gsave - .1 setlinewidth - 0 d_footer_h moveto - 0 d_output_h rlineto - d_output_w 0 rlineto - 0 d_output_h neg rlineto - closepath stroke - grestore -} def - -% Do the actual underlay drawing -/draw_underlay { - ul_style 0 eq { - ul_str true charpath stroke - } { - ul_str show - } ifelse -} def - -% Underlay -/underlay { % - -> - - gsave - 0 d_page_h translate - d_page_h neg d_page_w atan rotate - - ul_gray setgray - ul_font setfont - /dw d_page_h dup mul d_page_w dup mul add sqrt def - ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto - draw_underlay - grestore -} def - -/user_underlay { % - -> - - gsave - ul_x ul_y translate - ul_angle rotate - ul_gray setgray - ul_font setfont - 0 0 ul_h_ptsize 2 div sub moveto - draw_underlay - grestore -} def - -% Page prefeed -/page_prefeed { % bool -> - - statusdict /prefeed known { - statusdict exch /prefeed exch put - } { - pop - } ifelse -} def - -% Wrapped line markers -/wrapped_line_mark { % x y charwith charheight type -> - - /type exch def - /h exch def - /w exch def - /y exch def - /x exch def - - type 2 eq { - % Black boxes (like TeX does) - gsave - 0 setlinewidth - x w 4 div add y M - 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto - closepath fill - grestore - } { - type 3 eq { - % Small arrows - gsave - .2 setlinewidth - x w 2 div add y h 2 div add M - w 4 div 0 rlineto - x w 4 div add y lineto stroke - - x w 4 div add w 8 div add y h 4 div add M - x w 4 div add y lineto - w 4 div h 8 div rlineto stroke - grestore - } { - % do nothing - } ifelse - } ifelse -} def - -% EPSF import. - -/BeginEPSF { - /b4_Inc_state save def % Save state for cleanup - /dict_count countdictstack def % Count objects on dict stack - /op_count count 1 sub def % Count objects on operand stack - userdict begin - /showpage { } def - 0 setgray 0 setlinecap - 1 setlinewidth 0 setlinejoin - 10 setmiterlimit [ ] 0 setdash newpath - /languagelevel where { - pop languagelevel - 1 ne { - false setstrokeadjust false setoverprint - } if - } if -} bind def - -/EndEPSF { - count op_count sub { pos } repeat % Clean up stacks - countdictstack dict_count sub { end } repeat - b4_Inc_state restore -} bind def - -% Check PostScript language level. -/languagelevel where { - pop /gs_languagelevel languagelevel def -} { - /gs_languagelevel 1 def -} ifelse -%%EndResource -%%BeginResource: procset Enscript-Encoding-88591 1.6 1 -/encoding_vector [ -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclam /quotedbl /numbersign -/dollar /percent /ampersand /quoteright -/parenleft /parenright /asterisk /plus -/comma /hyphen /period /slash -/zero /one /two /three -/four /five /six /seven -/eight /nine /colon /semicolon -/less /equal /greater /question -/at /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 /bracketleft -/backslash /bracketright /asciicircum /underscore -/quoteleft /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 /braceleft -/bar /braceright /tilde /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclamdown /cent /sterling -/currency /yen /brokenbar /section -/dieresis /copyright /ordfeminine /guillemotleft -/logicalnot /hyphen /registered /macron -/degree /plusminus /twosuperior /threesuperior -/acute /mu /paragraph /bullet -/cedilla /onesuperior /ordmasculine /guillemotright -/onequarter /onehalf /threequarters /questiondown -/Agrave /Aacute /Acircumflex /Atilde -/Adieresis /Aring /AE /Ccedilla -/Egrave /Eacute /Ecircumflex /Edieresis -/Igrave /Iacute /Icircumflex /Idieresis -/Eth /Ntilde /Ograve /Oacute -/Ocircumflex /Otilde /Odieresis /multiply -/Oslash /Ugrave /Uacute /Ucircumflex -/Udieresis /Yacute /Thorn /germandbls -/agrave /aacute /acircumflex /atilde -/adieresis /aring /ae /ccedilla -/egrave /eacute /ecircumflex /edieresis -/igrave /iacute /icircumflex /idieresis -/eth /ntilde /ograve /oacute -/ocircumflex /otilde /odieresis /divide -/oslash /ugrave /uacute /ucircumflex -/udieresis /yacute /thorn /ydieresis -] def -%%EndResource -%%EndProlog -%%BeginSetup -%%IncludeResource: font Courier-Bold -%%IncludeResource: font Courier -/HFpt_w 10 def -/HFpt_h 10 def -/Courier-Bold /HF-gs-font MF -/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def -/Courier /F-gs-font MF -/F-gs-font 10 10 SF -/#copies 1 def -/d_page_w 520 def -/d_page_h 747 def -/d_header_x 0 def -/d_header_y 747 def -/d_header_w 520 def -/d_header_h 0 def -/d_footer_x 0 def -/d_footer_y 0 def -/d_footer_w 520 def -/d_footer_h 0 def -/d_output_w 520 def -/d_output_h 747 def -/cols 1 def -userdict/PStoPSxform PStoPSmatrix matrix currentmatrix - matrix invertmatrix matrix concatmatrix - matrix invertmatrix put -%%EndSetup -%%Page: (0,1) 1 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 1 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 701 M -(Network Working Group T. Ylonen) s -5 690 M -(Internet-Draft SSH Communications Security Corp) s -5 679 M -(Expires: March 31, 2004 D. Moffat, Editor, Ed.) s -5 668 M -( Sun Microsystems, Inc) s -5 657 M -( Oct 2003) s -5 624 M -( SSH Transport Layer Protocol) s -5 613 M -( draft-ietf-secsh-transport-17.txt) s -5 591 M -(Status of this Memo) s -5 569 M -( This document is an Internet-Draft and is in full conformance with) s -5 558 M -( all provisions of Section 10 of RFC2026.) s -5 536 M -( Internet-Drafts are working documents of the Internet Engineering) s -5 525 M -( Task Force \(IETF\), its areas, and its working groups. Note that other) s -5 514 M -( groups may also distribute working documents as Internet-Drafts.) s -5 492 M -( Internet-Drafts are draft documents valid for a maximum of six months) s -5 481 M -( and may be updated, replaced, or obsoleted by other documents at any) s -5 470 M -( time. It is inappropriate to use Internet-Drafts as reference) s -5 459 M -( material or to cite them other than as "work in progress.") s -5 437 M -( The list of current Internet-Drafts can be accessed at http://) s -5 426 M -( www.ietf.org/ietf/1id-abstracts.txt.) s -5 404 M -( The list of Internet-Draft Shadow Directories can be accessed at) s -5 393 M -( http://www.ietf.org/shadow.html.) s -5 371 M -( This Internet-Draft will expire on March 31, 2004.) s -5 349 M -(Copyright Notice) s -5 327 M -( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s -5 305 M -(Abstract) s -5 283 M -( SSH is a protocol for secure remote login and other secure network) s -5 272 M -( services over an insecure network.) s -5 250 M -( This document describes the SSH transport layer protocol which) s -5 239 M -( typically runs on top of TCP/IP. The protocol can be used as a basis) s -5 228 M -( for a number of secure network services. It provides strong) s -5 217 M -( encryption, server authentication, and integrity protection. It may) s -5 206 M -( also provide compression.) s -5 184 M -( Key exchange method, public key algorithm, symmetric encryption) s -5 173 M -( algorithm, message authentication algorithm, and hash algorithm are) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 2 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( all negotiated.) s -5 668 M -( This document also describes the Diffie-Hellman key exchange method) s -5 657 M -( and the minimal set of algorithms that are needed to implement the) s -5 646 M -( SSH transport layer protocol.) s -5 624 M -(Table of Contents) s -5 602 M -( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 591 M -( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 580 M -( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s -5 569 M -( 4. Connection Setup . . . . . . . . . . . . . . . . . . . . . . 3) s -5 558 M -( 4.1 Use over TCP/IP . . . . . . . . . . . . . . . . . . . . . . 4) s -5 547 M -( 4.2 Protocol Version Exchange . . . . . . . . . . . . . . . . . 4) s -5 536 M -( 4.3 Compatibility With Old SSH Versions . . . . . . . . . . . . 4) s -5 525 M -( 4.3.1 Old Client, New Server . . . . . . . . . . . . . . . . . . . 5) s -5 514 M -( 4.3.2 New Client, Old Server . . . . . . . . . . . . . . . . . . . 5) s -5 503 M -( 5. Binary Packet Protocol . . . . . . . . . . . . . . . . . . . 5) s -5 492 M -( 5.1 Maximum Packet Length . . . . . . . . . . . . . . . . . . . 6) s -5 481 M -( 5.2 Compression . . . . . . . . . . . . . . . . . . . . . . . . 7) s -5 470 M -( 5.3 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . 7) s -5 459 M -( 5.4 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 9) s -5 448 M -( 5.5 Key Exchange Methods . . . . . . . . . . . . . . . . . . . . 10) s -5 437 M -( 5.6 Public Key Algorithms . . . . . . . . . . . . . . . . . . . 11) s -5 426 M -( 6. Key Exchange . . . . . . . . . . . . . . . . . . . . . . . . 13) s -5 415 M -( 6.1 Algorithm Negotiation . . . . . . . . . . . . . . . . . . . 13) s -5 404 M -( 6.2 Output from Key Exchange . . . . . . . . . . . . . . . . . . 16) s -5 393 M -( 6.3 Taking Keys Into Use . . . . . . . . . . . . . . . . . . . . 17) s -5 382 M -( 7. Diffie-Hellman Key Exchange . . . . . . . . . . . . . . . . 18) s -5 371 M -( 7.1 diffie-hellman-group1-sha1 . . . . . . . . . . . . . . . . . 19) s -5 360 M -( 8. Key Re-Exchange . . . . . . . . . . . . . . . . . . . . . . 20) s -5 349 M -( 9. Service Request . . . . . . . . . . . . . . . . . . . . . . 21) s -5 338 M -( 10. Additional Messages . . . . . . . . . . . . . . . . . . . . 21) s -5 327 M -( 10.1 Disconnection Message . . . . . . . . . . . . . . . . . . . 22) s -5 316 M -( 10.2 Ignored Data Message . . . . . . . . . . . . . . . . . . . . 22) s -5 305 M -( 10.3 Debug Message . . . . . . . . . . . . . . . . . . . . . . . 23) s -5 294 M -( 10.4 Reserved Messages . . . . . . . . . . . . . . . . . . . . . 23) s -5 283 M -( 11. Summary of Message Numbers . . . . . . . . . . . . . . . . . 23) s -5 272 M -( 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 24) s -5 261 M -( 13. Security Considerations . . . . . . . . . . . . . . . . . . 24) s -5 250 M -( 14. Intellectual Property . . . . . . . . . . . . . . . . . . . 24) s -5 239 M -( 15. Additional Information . . . . . . . . . . . . . . . . . . . 24) s -5 228 M -( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 26) s -5 217 M -( Normative . . . . . . . . . . . . . . . . . . . . . . . . . 25) s -5 206 M -( Informative . . . . . . . . . . . . . . . . . . . . . . . . 25) s -5 195 M -( A. Contibutors . . . . . . . . . . . . . . . . . . . . . . . . 27) s -5 184 M -( Intellectual Property and Copyright Statements . . . . . . . 28) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]) s -_R -S -PStoPSsaved restore -%%Page: (2,3) 2 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 3 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -(1. Contributors) s -5 668 M -( The major original contributors of this document were: Tatu Ylonen,) s -5 657 M -( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s -5 646 M -( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s -5 635 M -( Jyvaskyla\)) s -5 613 M -( The document editor is: Darren.Moffat@Sun.COM. Comments on this) s -5 602 M -( internet draft should be sent to the IETF SECSH working group,) s -5 591 M -( details at: http://ietf.org/html.charters/secsh-charter.html) s -5 569 M -(2. Introduction) s -5 547 M -( The SSH transport layer is a secure low level transport protocol. It) s -5 536 M -( provides strong encryption, cryptographic host authentication, and) s -5 525 M -( integrity protection.) s -5 503 M -( Authentication in this protocol level is host-based; this protocol) s -5 492 M -( does not perform user authentication. A higher level protocol for) s -5 481 M -( user authentication can be designed on top of this protocol.) s -5 459 M -( The protocol has been designed to be simple, flexible, to allow) s -5 448 M -( parameter negotiation, and to minimize the number of round-trips.) s -5 437 M -( Key exchange method, public key algorithm, symmetric encryption) s -5 426 M -( algorithm, message authentication algorithm, and hash algorithm are) s -5 415 M -( all negotiated. It is expected that in most environments, only 2) s -5 404 M -( round-trips will be needed for full key exchange, server) s -5 393 M -( authentication, service request, and acceptance notification of) s -5 382 M -( service request. The worst case is 3 round-trips.) s -5 360 M -(3. Conventions Used in This Document) s -5 338 M -( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s -5 327 M -( and "MAY" that appear in this document are to be interpreted as) s -5 316 M -( described in [RFC2119].) s -5 294 M -( The used data types and terminology are specified in the architecture) s -5 283 M -( document [SSH-ARCH].) s -5 261 M -( The architecture document also discusses the algorithm naming) s -5 250 M -( conventions that MUST be used with the SSH protocols.) s -5 228 M -(4. Connection Setup) s -5 206 M -( SSH works over any 8-bit clean, binary-transparent transport. The) s -5 195 M -( underlying transport SHOULD protect against transmission errors as) s -5 184 M -( such errors cause the SSH connection to terminate.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 4 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( The client initiates the connection.) s -5 668 M -(4.1 Use over TCP/IP) s -5 646 M -( When used over TCP/IP, the server normally listens for connections on) s -5 635 M -( port 22. This port number has been registered with the IANA, and has) s -5 624 M -( been officially assigned for SSH.) s -5 602 M -(4.2 Protocol Version Exchange) s -5 580 M -( When the connection has been established, both sides MUST send an) s -5 569 M -( identification string of the form "SSH-protoversion-softwareversion) s -5 558 M -( comments", followed by carriage return and newline characters \(ASCII) s -5 547 M -( 13 and 10, respectively\). Both sides MUST be able to process) s -5 536 M -( identification strings without carriage return character. No null) s -5 525 M -( character is sent. The maximum length of the string is 255) s -5 514 M -( characters, including the carriage return and newline.) s -5 492 M -( The part of the identification string preceding carriage return and) s -5 481 M -( newline is used in the Diffie-Hellman key exchange \(see Section) s -5 470 M -( Section 7\).) s -5 448 M -( The server MAY send other lines of data before sending the version) s -5 437 M -( string. Each line SHOULD be terminated by a carriage return and) s -5 426 M -( newline. Such lines MUST NOT begin with "SSH-", and SHOULD be) s -5 415 M -( encoded in ISO-10646 UTF-8 [RFC2279] \(language is not specified\).) s -5 404 M -( Clients MUST be able to process such lines; they MAY be silently) s -5 393 M -( ignored, or MAY be displayed to the client user; if they are) s -5 382 M -( displayed, control character filtering discussed in [SSH-ARCH] SHOULD) s -5 371 M -( be used. The primary use of this feature is to allow TCP-wrappers to) s -5 360 M -( display an error message before disconnecting.) s -5 338 M -( Version strings MUST consist of printable US-ASCII characters, not) s -5 327 M -( including whitespaces or a minus sign \(-\). The version string is) s -5 316 M -( primarily used to trigger compatibility extensions and to indicate) s -5 305 M -( the capabilities of an implementation. The comment string should) s -5 294 M -( contain additional information that might be useful in solving user) s -5 283 M -( problems.) s -5 261 M -( The protocol version described in this document is 2.0.) s -5 239 M -( Key exchange will begin immediately after sending this identifier.) s -5 228 M -( All packets following the identification string SHALL use the binary) s -5 217 M -( packet protocol, to be described below.) s -5 195 M -(4.3 Compatibility With Old SSH Versions) s -5 173 M -( During the transition period, it is important to be able to work in a) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]) s -_R -S -PStoPSsaved restore -%%Page: (4,5) 3 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 5 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( way that is compatible with the installed SSH clients and servers) s -5 679 M -( that use an older version of the protocol. Information in this) s -5 668 M -( section is only relevant for implementations supporting compatibility) s -5 657 M -( with SSH versions 1.x. There is no standards track or informational) s -5 646 M -( draft available that defines the SSH 1.x protocol. The only known) s -5 635 M -( documentation of the 1.x protocol is contained in README files that) s -5 624 M -( are shipped along with the source code.) s -5 602 M -(4.3.1 Old Client, New Server) s -5 580 M -( Server implementations MAY support a configurable "compatibility") s -5 569 M -( flag that enables compatibility with old versions. When this flag is) s -5 558 M -( on, the server SHOULD identify its protocol version as "1.99".) s -5 547 M -( Clients using protocol 2.0 MUST be able to identify this as identical) s -5 536 M -( to "2.0". In this mode the server SHOULD NOT send the carriage) s -5 525 M -( return character \(ASCII 13\) after the version identification string.) s -5 503 M -( In the compatibility mode the server SHOULD NOT send any further data) s -5 492 M -( after its initialization string until it has received an) s -5 481 M -( identification string from the client. The server can then determine) s -5 470 M -( whether the client is using an old protocol, and can revert to the) s -5 459 M -( old protocol if required. In the compatibility mode, the server MUST) s -5 448 M -( NOT send additional data before the version string.) s -5 426 M -( When compatibility with old clients is not needed, the server MAY) s -5 415 M -( send its initial key exchange data immediately after the) s -5 404 M -( identification string.) s -5 382 M -(4.3.2 New Client, Old Server) s -5 360 M -( Since the new client MAY immediately send additional data after its) s -5 349 M -( identification string \(before receiving server's identification\), the) s -5 338 M -( old protocol may already have been corrupted when the client learns) s -5 327 M -( that the server is old. When this happens, the client SHOULD close) s -5 316 M -( the connection to the server, and reconnect using the old protocol.) s -5 294 M -(5. Binary Packet Protocol) s -5 272 M -( Each packet is in the following format:) s -5 250 M -( uint32 packet_length) s -5 239 M -( byte padding_length) s -5 228 M -( byte[n1] payload; n1 = packet_length - padding_length - 1) s -5 217 M -( byte[n2] random padding; n2 = padding_length) s -5 206 M -( byte[m] mac \(message authentication code\); m = mac_length) s -5 184 M -( packet_length) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 6 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( The length of the packet \(bytes\), not including MAC or the) s -5 679 M -( packet_length field itself.) s -5 657 M -( padding_length) s -5 646 M -( Length of padding \(bytes\).) s -5 624 M -( payload) s -5 613 M -( The useful contents of the packet. If compression has been) s -5 602 M -( negotiated, this field is compressed. Initially, compression) s -5 591 M -( MUST be "none".) s -5 569 M -( random padding) s -5 558 M -( Arbitrary-length padding, such that the total length of) s -5 547 M -( \(packet_length || padding_length || payload || padding\) is a) s -5 536 M -( multiple of the cipher block size or 8, whichever is larger.) s -5 525 M -( There MUST be at least four bytes of padding. The padding) s -5 514 M -( SHOULD consist of random bytes. The maximum amount of padding) s -5 503 M -( is 255 bytes.) s -5 481 M -( mac) s -5 470 M -( Message authentication code. If message authentication has) s -5 459 M -( been negotiated, this field contains the MAC bytes. Initially,) s -5 448 M -( the MAC algorithm MUST be "none".) s -5 415 M -( Note that length of the concatenation of packet length, padding) s -5 404 M -( length, payload, and padding MUST be a multiple of the cipher block) s -5 393 M -( size or 8, whichever is larger. This constraint MUST be enforced) s -5 382 M -( even when using stream ciphers. Note that the packet length field is) s -5 371 M -( also encrypted, and processing it requires special care when sending) s -5 360 M -( or receiving packets.) s -5 338 M -( The minimum size of a packet is 16 \(or the cipher block size,) s -5 327 M -( whichever is larger\) bytes \(plus MAC\); implementations SHOULD decrypt) s -5 316 M -( the length after receiving the first 8 \(or cipher block size,) s -5 305 M -( whichever is larger\) bytes of a packet.) s -5 283 M -(5.1 Maximum Packet Length) s -5 261 M -( All implementations MUST be able to process packets with uncompressed) s -5 250 M -( payload length of 32768 bytes or less and total packet size of 35000) s -5 239 M -( bytes or less \(including length, padding length, payload, padding,) s -5 228 M -( and MAC.\). The maximum of 35000 bytes is an arbitrary chosen value) s -5 217 M -( larger than uncompressed size. Implementations SHOULD support longer) s -5 206 M -( packets, where they might be needed, e.g. if an implementation wants) s -5 195 M -( to send a very large number of certificates. Such packets MAY be) s -5 184 M -( sent if the version string indicates that the other party is able to) s -5 173 M -( process them. However, implementations SHOULD check that the packet) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]) s -_R -S -PStoPSsaved restore -%%Page: (6,7) 4 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 7 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( length is reasonable for the implementation to avoid) s -5 679 M -( denial-of-service and/or buffer overflow attacks.) s -5 657 M -(5.2 Compression) s -5 635 M -( If compression has been negotiated, the payload field \(and only it\)) s -5 624 M -( will be compressed using the negotiated algorithm. The length field) s -5 613 M -( and MAC will be computed from the compressed payload. Encryption will) s -5 602 M -( be done after compression.) s -5 580 M -( Compression MAY be stateful, depending on the method. Compression) s -5 569 M -( MUST be independent for each direction, and implementations MUST) s -5 558 M -( allow independently choosing the algorithm for each direction.) s -5 536 M -( The following compression methods are currently defined:) s -5 514 M -( none REQUIRED no compression) s -5 503 M -( zlib OPTIONAL ZLIB \(LZ77\) compression) s -5 481 M -( The "zlib" compression is described in [RFC1950] and in [RFC1951].) s -5 470 M -( The compression context is initialized after each key exchange, and) s -5 459 M -( is passed from one packet to the next with only a partial flush being) s -5 448 M -( performed at the end of each packet. A partial flush means that the) s -5 437 M -( current compressed block is ended and all data will be output. If the) s -5 426 M -( current block is not a stored block, one or more empty blocks are) s -5 415 M -( added after the current block to ensure that there are at least 8) s -5 404 M -( bits counting from the start of the end-of-block code of the current) s -5 393 M -( block to the end of the packet payload.) s -5 371 M -( Additional methods may be defined as specified in [SSH-ARCH].) s -5 349 M -(5.3 Encryption) s -5 327 M -( An encryption algorithm and a key will be negotiated during the key) s -5 316 M -( exchange. When encryption is in effect, the packet length, padding) s -5 305 M -( length, payload and padding fields of each packet MUST be encrypted) s -5 294 M -( with the given algorithm.) s -5 272 M -( The encrypted data in all packets sent in one direction SHOULD be) s -5 261 M -( considered a single data stream. For example, initialization vectors) s -5 250 M -( SHOULD be passed from the end of one packet to the beginning of the) s -5 239 M -( next packet. All ciphers SHOULD use keys with an effective key length) s -5 228 M -( of 128 bits or more.) s -5 206 M -( The ciphers in each direction MUST run independently of each other,) s -5 195 M -( and implementations MUST allow independently choosing the algorithm) s -5 184 M -( for each direction \(if multiple algorithms are allowed by local) s -5 173 M -( policy\).) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 8 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( The following ciphers are currently defined:) s -5 668 M -( 3des-cbc REQUIRED three-key 3DES in CBC mode) s -5 657 M -( blowfish-cbc OPTIONALi Blowfish in CBC mode) s -5 646 M -( twofish256-cbc OPTIONAL Twofish in CBC mode,) s -5 635 M -( with 256-bit key) s -5 624 M -( twofish-cbc OPTIONAL alias for "twofish256-cbc" \(this) s -5 613 M -( is being retained for) s -5 602 M -( historical reasons\)) s -5 591 M -( twofish192-cbc OPTIONAL Twofish with 192-bit key) s -5 580 M -( twofish128-cbc OPTIONAL Twofish with 128-bit key) s -5 569 M -( aes256-cbc OPTIONAL AES \(Rijndael\) in CBC mode,) s -5 558 M -( with 256-bit key) s -5 547 M -( aes192-cbc OPTIONAL AES with 192-bit key) s -5 536 M -( aes128-cbc RECOMMENDED AES with 128-bit key) s -5 525 M -( serpent256-cbc OPTIONAL Serpent in CBC mode, with) s -5 514 M -( 256-bit key) s -5 503 M -( serpent192-cbc OPTIONAL Serpent with 192-bit key) s -5 492 M -( serpent128-cbc OPTIONAL Serpent with 128-bit key) s -5 481 M -( arcfour OPTIONAL the ARCFOUR stream cipher) s -5 470 M -( idea-cbc OPTIONAL IDEA in CBC mode) s -5 459 M -( cast128-cbc OPTIONAL CAST-128 in CBC mode) s -5 448 M -( none OPTIONAL no encryption; NOT RECOMMENDED) s -5 426 M -( The "3des-cbc" cipher is three-key triple-DES) s -5 415 M -( \(encrypt-decrypt-encrypt\), where the first 8 bytes of the key are) s -5 404 M -( used for the first encryption, the next 8 bytes for the decryption,) s -5 393 M -( and the following 8 bytes for the final encryption. This requires 24) s -5 382 M -( bytes of key data \(of which 168 bits are actually used\). To) s -5 371 M -( implement CBC mode, outer chaining MUST be used \(i.e., there is only) s -5 360 M -( one initialization vector\). This is a block cipher with 8 byte) s -5 349 M -( blocks. This algorithm is defined in [FIPS-46-3]) s -5 327 M -( The "blowfish-cbc" cipher is Blowfish in CBC mode, with 128 bit keys) s -5 316 M -( [SCHNEIER]. This is a block cipher with 8 byte blocks.) s -5 294 M -( The "twofish-cbc" or "twofish256-cbc" cipher is Twofish in CBC mode,) s -5 283 M -( with 256 bit keys as described [TWOFISH]. This is a block cipher with) s -5 272 M -( 16 byte blocks.) s -5 250 M -( The "twofish192-cbc" cipher. Same as above but with 192-bit key.) s -5 228 M -( The "twofish128-cbc" cipher. Same as above but with 128-bit key.) s -5 206 M -( The "aes256-cbc" cipher is AES \(Advanced Encryption Standard\)) s -5 195 M -( [FIPS-197], formerly Rijndael, in CBC mode. This version uses 256-bit) s -5 184 M -( key.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]) s -_R -S -PStoPSsaved restore -%%Page: (8,9) 5 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 9 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( The "aes192-cbc" cipher. Same as above but with 192-bit key.) s -5 668 M -( The "aes128-cbc" cipher. Same as above but with 128-bit key.) s -5 646 M -( The "serpent256-cbc" cipher in CBC mode, with 256-bit key as) s -5 635 M -( described in the Serpent AES submission.) s -5 613 M -( The "serpent192-cbc" cipher. Same as above but with 192-bit key.) s -5 591 M -( The "serpent128-cbc" cipher. Same as above but with 128-bit key.) s -5 569 M -( The "arcfour" is the Arcfour stream cipher with 128 bit keys. The) s -5 558 M -( Arcfour cipher is believed to be compatible with the RC4 cipher) s -5 547 M -( [SCHNEIER]. RC4 is a registered trademark of RSA Data Security Inc.) s -5 536 M -( Arcfour \(and RC4\) has problems with weak keys, and should be used) s -5 525 M -( with caution.) s -5 503 M -( The "idea-cbc" cipher is the IDEA cipher in CBC mode [SCHNEIER].) s -5 481 M -( The "cast128-cbc" cipher is the CAST-128 cipher in CBC mode) s -5 470 M -( [RFC2144].) s -5 448 M -( The "none" algorithm specifies that no encryption is to be done.) s -5 437 M -( Note that this method provides no confidentiality protection, and it) s -5 426 M -( is not recommended. Some functionality \(e.g. password) s -5 415 M -( authentication\) may be disabled for security reasons if this cipher) s -5 404 M -( is chosen.) s -5 382 M -( Additional methods may be defined as specified in [SSH-ARCH].) s -5 360 M -(5.4 Data Integrity) s -5 338 M -( Data integrity is protected by including with each packet a message) s -5 327 M -( authentication code \(MAC\) that is computed from a shared secret,) s -5 316 M -( packet sequence number, and the contents of the packet.) s -5 294 M -( The message authentication algorithm and key are negotiated during) s -5 283 M -( key exchange. Initially, no MAC will be in effect, and its length) s -5 272 M -( MUST be zero. After key exchange, the selected MAC will be computed) s -5 261 M -( before encryption from the concatenation of packet data:) s -5 239 M -( mac = MAC\(key, sequence_number || unencrypted_packet\)) s -5 217 M -( where unencrypted_packet is the entire packet without MAC \(the length) s -5 206 M -( fields, payload and padding\), and sequence_number is an implicit) s -5 195 M -( packet sequence number represented as uint32. The sequence number is) s -5 184 M -( initialized to zero for the first packet, and is incremented after) s -5 173 M -( every packet \(regardless of whether encryption or MAC is in use\). It) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 10 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( is never reset, even if keys/algorithms are renegotiated later. It) s -5 679 M -( wraps around to zero after every 2^32 packets. The packet sequence) s -5 668 M -( number itself is not included in the packet sent over the wire.) s -5 646 M -( The MAC algorithms for each direction MUST run independently, and) s -5 635 M -( implementations MUST allow choosing the algorithm independently for) s -5 624 M -( both directions.) s -5 602 M -( The MAC bytes resulting from the MAC algorithm MUST be transmitted) s -5 591 M -( without encryption as the last part of the packet. The number of MAC) s -5 580 M -( bytes depends on the algorithm chosen.) s -5 558 M -( The following MAC algorithms are currently defined:) s -5 536 M -( hmac-sha1 REQUIRED HMAC-SHA1 \(digest length = key) s -5 525 M -( length = 20\)) s -5 514 M -( hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 \(digest) s -5 503 M -( length = 12, key length = 20\)) s -5 492 M -( hmac-md5 OPTIONAL HMAC-MD5 \(digest length = key) s -5 481 M -( length = 16\)) s -5 470 M -( hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 \(digest) s -5 459 M -( length = 12, key length = 16\)) s -5 448 M -( none OPTIONAL no MAC; NOT RECOMMENDED) s -5 426 M -( Figure 1) s -5 404 M -( The "hmac-*" algorithms are described in [RFC2104] The "*-n" MACs use) s -5 393 M -( only the first n bits of the resulting value.) s -5 371 M -( The hash algorithms are described in [SCHNEIER].) s -5 349 M -( Additional methods may be defined as specified in [SSH-ARCH].) s -5 327 M -(5.5 Key Exchange Methods) s -5 305 M -( The key exchange method specifies how one-time session keys are) s -5 294 M -( generated for encryption and for authentication, and how the server) s -5 283 M -( authentication is done.) s -5 261 M -( Only one REQUIRED key exchange method has been defined:) s -5 239 M -( diffie-hellman-group1-sha1 REQUIRED) s -5 217 M -( This method is described later in this document.) s -5 195 M -( Additional methods may be defined as specified in [SSH-ARCH].) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]) s -_R -S -PStoPSsaved restore -%%Page: (10,11) 6 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 11 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -(5.6 Public Key Algorithms) s -5 668 M -( This protocol has been designed to be able to operate with almost any) s -5 657 M -( public key format, encoding, and algorithm \(signature and/or) s -5 646 M -( encryption\).) s -5 624 M -( There are several aspects that define a public key type:) s -5 613 M -( o Key format: how is the key encoded and how are certificates) s -5 602 M -( represented. The key blobs in this protocol MAY contain) s -5 591 M -( certificates in addition to keys.) s -5 580 M -( o Signature and/or encryption algorithms. Some key types may not) s -5 569 M -( support both signing and encryption. Key usage may also be) s -5 558 M -( restricted by policy statements in e.g. certificates. In this) s -5 547 M -( case, different key types SHOULD be defined for the different) s -5 536 M -( policy alternatives.) s -5 525 M -( o Encoding of signatures and/or encrypted data. This includes but is) s -5 514 M -( not limited to padding, byte order, and data formats.) s -5 492 M -( The following public key and/or certificate formats are currently defined:) s -5 470 M -( ssh-dss REQUIRED sign Raw DSS Key) s -5 459 M -( ssh-rsa RECOMMENDED sign Raw RSA Key) s -5 448 M -( x509v3-sign-rsa OPTIONAL sign X.509 certificates \(RSA key\)) s -5 437 M -( x509v3-sign-dss OPTIONAL sign X.509 certificates \(DSS key\)) s -5 426 M -( spki-sign-rsa OPTIONAL sign SPKI certificates \(RSA key\)) s -5 415 M -( spki-sign-dss OPTIONAL sign SPKI certificates \(DSS key\)) s -5 404 M -( pgp-sign-rsa OPTIONAL sign OpenPGP certificates \(RSA key\)) s -5 393 M -( pgp-sign-dss OPTIONAL sign OpenPGP certificates \(DSS key\)) s -5 371 M -( Additional key types may be defined as specified in [SSH-ARCH].) s -5 349 M -( The key type MUST always be explicitly known \(from algorithm) s -5 338 M -( negotiation or some other source\). It is not normally included in) s -5 327 M -( the key blob.) s -5 305 M -( Certificates and public keys are encoded as follows:) s -5 283 M -( string certificate or public key format identifier) s -5 272 M -( byte[n] key/certificate data) s -5 250 M -( The certificate part may have be a zero length string, but a public) s -5 239 M -( key is required. This is the public key that will be used for) s -5 228 M -( authentication; the certificate sequence contained in the certificate) s -5 217 M -( blob can be used to provide authorization.) s -5 195 M -( Public key / certifcate formats that do not explicitly specify a) s -5 184 M -( signature format identifier MUST use the public key / certificate) s -5 173 M -( format identifier as the signature identifier.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 12 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( Signatures are encoded as follows:) s -5 679 M -( string signature format identifier \(as specified by the) s -5 668 M -( public key / cert format\)) s -5 657 M -( byte[n] signature blob in format specific encoding.) s -5 624 M -( The "ssh-dss" key format has the following specific encoding:) s -5 602 M -( string "ssh-dss") s -5 591 M -( mpint p) s -5 580 M -( mpint q) s -5 569 M -( mpint g) s -5 558 M -( mpint y) s -5 536 M -( Here the p, q, g, and y parameters form the signature key blob.) s -5 514 M -( Signing and verifying using this key format is done according to the) s -5 503 M -( Digital Signature Standard [FIPS-186] using the SHA-1 hash. A) s -5 492 M -( description can also be found in [SCHNEIER].) s -5 470 M -( The resulting signature is encoded as follows:) s -5 448 M -( string "ssh-dss") s -5 437 M -( string dss_signature_blob) s -5 415 M -( dss_signature_blob is encoded as a string containing r followed by s) s -5 404 M -( \(which are 160 bits long integers, without lengths or padding,) s -5 393 M -( unsigned and in network byte order\).) s -5 371 M -( The "ssh-rsa" key format has the following specific encoding:) s -5 349 M -( string "ssh-rsa") s -5 338 M -( mpint e) s -5 327 M -( mpint n) s -5 305 M -( Here the e and n parameters form the signature key blob.) s -5 283 M -( Signing and verifying using this key format is done according to) s -5 272 M -( [SCHNEIER] and [PKCS1] using the SHA-1 hash.) s -5 250 M -( The resulting signature is encoded as follows:) s -5 228 M -( string "ssh-rsa") s -5 217 M -( string rsa_signature_blob) s -5 195 M -( rsa_signature_blob is encoded as a string containing s \(which is an) s -5 184 M -( integer, without lengths or padding, unsigned and in network byte) s -5 173 M -( order\).) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]) s -_R -S -PStoPSsaved restore -%%Page: (12,13) 7 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 13 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( The "spki-sign-rsa" method indicates that the certificate blob) s -5 679 M -( contains a sequence of SPKI certificates. The format of SPKI) s -5 668 M -( certificates is described in [RFC2693]. This method indicates that) s -5 657 M -( the key \(or one of the keys in the certificate\) is an RSA-key.) s -5 635 M -( The "spki-sign-dss". As above, but indicates that the key \(or one of) s -5 624 M -( the keys in the certificate\) is a DSS-key.) s -5 602 M -( The "pgp-sign-rsa" method indicates the certificates, the public key,) s -5 591 M -( and the signature are in OpenPGP compatible binary format) s -5 580 M -( \([RFC2440]\). This method indicates that the key is an RSA-key.) s -5 558 M -( The "pgp-sign-dss". As above, but indicates that the key is a) s -5 547 M -( DSS-key.) s -5 525 M -(6. Key Exchange) s -5 503 M -( Key exchange begins by each side sending lists of supported) s -5 492 M -( algorithms. Each side has a preferred algorithm in each category, and) s -5 481 M -( it is assumed that most implementations at any given time will use) s -5 470 M -( the same preferred algorithm. Each side MAY guess which algorithm) s -5 459 M -( the other side is using, and MAY send an initial key exchange packet) s -5 448 M -( according to the algorithm if appropriate for the preferred method.) s -5 426 M -( Guess is considered wrong, if:) s -5 415 M -( o the kex algorithm and/or the host key algorithm is guessed wrong) s -5 404 M -( \(server and client have different preferred algorithm\), or) s -5 393 M -( o if any of the other algorithms cannot be agreed upon \(the) s -5 382 M -( procedure is defined below in Section Section 6.1\).) s -5 360 M -( Otherwise, the guess is considered to be right and the optimistically) s -5 349 M -( sent packet MUST be handled as the first key exchange packet.) s -5 327 M -( However, if the guess was wrong, and a packet was optimistically sent) s -5 316 M -( by one or both parties, such packets MUST be ignored \(even if the) s -5 305 M -( error in the guess would not affect the contents of the initial) s -5 294 M -( packet\(s\)\), and the appropriate side MUST send the correct initial) s -5 283 M -( packet.) s -5 261 M -( Server authentication in the key exchange MAY be implicit. After a) s -5 250 M -( key exchange with implicit server authentication, the client MUST) s -5 239 M -( wait for response to its service request message before sending any) s -5 228 M -( further data.) s -5 206 M -(6.1 Algorithm Negotiation) s -5 184 M -( Key exchange begins by each side sending the following packet:) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 14 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( byte SSH_MSG_KEXINIT) s -5 679 M -( byte[16] cookie \(random bytes\)) s -5 668 M -( string kex_algorithms) s -5 657 M -( string server_host_key_algorithms) s -5 646 M -( string encryption_algorithms_client_to_server) s -5 635 M -( string encryption_algorithms_server_to_client) s -5 624 M -( string mac_algorithms_client_to_server) s -5 613 M -( string mac_algorithms_server_to_client) s -5 602 M -( string compression_algorithms_client_to_server) s -5 591 M -( string compression_algorithms_server_to_client) s -5 580 M -( string languages_client_to_server) s -5 569 M -( string languages_server_to_client) s -5 558 M -( boolean first_kex_packet_follows) s -5 547 M -( uint32 0 \(reserved for future extension\)) s -5 525 M -( Each of the algorithm strings MUST be a comma-separated list of) s -5 514 M -( algorithm names \(see ''Algorithm Naming'' in [SSH-ARCH]\). Each) s -5 503 M -( supported \(allowed\) algorithm MUST be listed in order of preference.) s -5 481 M -( The first algorithm in each list MUST be the preferred \(guessed\)) s -5 470 M -( algorithm. Each string MUST contain at least one algorithm name.) s -5 437 M -( cookie) s -5 426 M -( The cookie MUST be a random value generated by the sender. Its) s -5 415 M -( purpose is to make it impossible for either side to fully) s -5 404 M -( determine the keys and the session identifier.) s -5 382 M -( kex_algorithms) s -5 371 M -( Key exchange algorithms were defined above. The first) s -5 360 M -( algorithm MUST be the preferred \(and guessed\) algorithm. If) s -5 349 M -( both sides make the same guess, that algorithm MUST be used.) s -5 338 M -( Otherwise, the following algorithm MUST be used to choose a key) s -5 327 M -( exchange method: iterate over client's kex algorithms, one at a) s -5 316 M -( time. Choose the first algorithm that satisfies the following) s -5 305 M -( conditions:) s -5 294 M -( + the server also supports the algorithm,) s -5 283 M -( + if the algorithm requires an encryption-capable host key,) s -5 272 M -( there is an encryption-capable algorithm on the server's) s -5 261 M -( server_host_key_algorithms that is also supported by the) s -5 250 M -( client, and) s -5 239 M -( + if the algorithm requires a signature-capable host key,) s -5 228 M -( there is a signature-capable algorithm on the server's) s -5 217 M -( server_host_key_algorithms that is also supported by the) s -5 206 M -( client.) s -5 195 M -( + If no algorithm satisfying all these conditions can be) s -5 184 M -( found, the connection fails, and both sides MUST disconnect.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]) s -_R -S -PStoPSsaved restore -%%Page: (14,15) 8 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 15 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( server_host_key_algorithms) s -5 679 M -( List of the algorithms supported for the server host key. The) s -5 668 M -( server lists the algorithms for which it has host keys; the) s -5 657 M -( client lists the algorithms that it is willing to accept.) s -5 646 M -( \(There MAY be multiple host keys for a host, possibly with) s -5 635 M -( different algorithms.\)) s -5 613 M -( Some host keys may not support both signatures and encryption) s -5 602 M -( \(this can be determined from the algorithm\), and thus not all) s -5 591 M -( host keys are valid for all key exchange methods.) s -5 569 M -( Algorithm selection depends on whether the chosen key exchange) s -5 558 M -( algorithm requires a signature or encryption capable host key.) s -5 547 M -( It MUST be possible to determine this from the public key) s -5 536 M -( algorithm name. The first algorithm on the client's list that) s -5 525 M -( satisfies the requirements and is also supported by the server) s -5 514 M -( MUST be chosen. If there is no such algorithm, both sides MUST) s -5 503 M -( disconnect.) s -5 481 M -( encryption_algorithms) s -5 470 M -( Lists the acceptable symmetric encryption algorithms in order) s -5 459 M -( of preference. The chosen encryption algorithm to each) s -5 448 M -( direction MUST be the first algorithm on the client's list) s -5 437 M -( that is also on the server's list. If there is no such) s -5 426 M -( algorithm, both sides MUST disconnect.) s -5 404 M -( Note that "none" must be explicitly listed if it is to be) s -5 393 M -( acceptable. The defined algorithm names are listed in Section) s -5 382 M -( Section 5.3.) s -5 360 M -( mac_algorithms) s -5 349 M -( Lists the acceptable MAC algorithms in order of preference.) s -5 338 M -( The chosen MAC algorithm MUST be the first algorithm on the) s -5 327 M -( client's list that is also on the server's list. If there is) s -5 316 M -( no such algorithm, both sides MUST disconnect.) s -5 294 M -( Note that "none" must be explicitly listed if it is to be) s -5 283 M -( acceptable. The MAC algorithm names are listed in Section) s -5 272 M -( Figure 1.) s -5 250 M -( compression_algorithms) s -5 239 M -( Lists the acceptable compression algorithms in order of) s -5 228 M -( preference. The chosen compression algorithm MUST be the first) s -5 217 M -( algorithm on the client's list that is also on the server's) s -5 206 M -( list. If there is no such algorithm, both sides MUST) s -5 195 M -( disconnect.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 16 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( Note that "none" must be explicitly listed if it is to be) s -5 679 M -( acceptable. The compression algorithm names are listed in) s -5 668 M -( Section Section 5.2.) s -5 646 M -( languages) s -5 635 M -( This is a comma-separated list of language tags in order of) s -5 624 M -( preference [RFC3066]. Both parties MAY ignore this list. If) s -5 613 M -( there are no language preferences, this list SHOULD be empty.) s -5 602 M -( Language tags SHOULD NOT be present unless they are known to be) s -5 591 M -( needed by the sending party.) s -5 569 M -( first_kex_packet_follows) s -5 558 M -( Indicates whether a guessed key exchange packet follows. If a) s -5 547 M -( guessed packet will be sent, this MUST be TRUE. If no guessed) s -5 536 M -( packet will be sent, this MUST be FALSE.) s -5 514 M -( After receiving the SSH_MSG_KEXINIT packet from the other side,) s -5 503 M -( each party will know whether their guess was right. If the) s -5 492 M -( other party's guess was wrong, and this field was TRUE, the) s -5 481 M -( next packet MUST be silently ignored, and both sides MUST then) s -5 470 M -( act as determined by the negotiated key exchange method. If) s -5 459 M -( the guess was right, key exchange MUST continue using the) s -5 448 M -( guessed packet.) s -5 426 M -( After the KEXINIT packet exchange, the key exchange algorithm is run.) s -5 415 M -( It may involve several packet exchanges, as specified by the key) s -5 404 M -( exchange method.) s -5 382 M -(6.2 Output from Key Exchange) s -5 360 M -( The key exchange produces two values: a shared secret K, and an) s -5 349 M -( exchange hash H. Encryption and authentication keys are derived from) s -5 338 M -( these. The exchange hash H from the first key exchange is) s -5 327 M -( additionally used as the session identifier, which is a unique) s -5 316 M -( identifier for this connection. It is used by authentication methods) s -5 305 M -( as a part of the data that is signed as a proof of possession of a) s -5 294 M -( private key. Once computed, the session identifier is not changed,) s -5 283 M -( even if keys are later re-exchanged.) s -5 250 M -( Each key exchange method specifies a hash function that is used in) s -5 239 M -( the key exchange. The same hash algorithm MUST be used in key) s -5 228 M -( derivation. Here, we'll call it HASH.) s -5 195 M -( Encryption keys MUST be computed as HASH of a known value and K as) s -5 184 M -( follows:) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]) s -_R -S -PStoPSsaved restore -%%Page: (16,17) 9 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 17 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( o Initial IV client to server: HASH\(K || H || "A" || session_id\)) s -5 679 M -( \(Here K is encoded as mpint and "A" as byte and session_id as raw) s -5 668 M -( data."A" means the single character A, ASCII 65\).) s -5 657 M -( o Initial IV server to client: HASH\(K || H || "B" || session_id\)) s -5 646 M -( o Encryption key client to server: HASH\(K || H || "C" || session_id\)) s -5 635 M -( o Encryption key server to client: HASH\(K || H || "D" || session_id\)) s -5 624 M -( o Integrity key client to server: HASH\(K || H || "E" || session_id\)) s -5 613 M -( o Integrity key server to client: HASH\(K || H || "F" || session_id\)) s -5 591 M -( Key data MUST be taken from the beginning of the hash output. 128) s -5 580 M -( bits \(16 bytes\) MUST be used for algorithms with variable-length) s -5 569 M -( keys. The only variable key length algorithm defined in this document) s -5 558 M -( is arcfour\). For other algorithms, as many bytes as are needed are) s -5 547 M -( taken from the beginning of the hash value. If the key length needed) s -5 536 M -( is longer than the output of the HASH, the key is extended by) s -5 525 M -( computing HASH of the concatenation of K and H and the entire key so) s -5 514 M -( far, and appending the resulting bytes \(as many as HASH generates\) to) s -5 503 M -( the key. This process is repeated until enough key material is) s -5 492 M -( available; the key is taken from the beginning of this value. In) s -5 481 M -( other words:) s -5 459 M -( K1 = HASH\(K || H || X || session_id\) \(X is e.g. "A"\)) s -5 448 M -( K2 = HASH\(K || H || K1\)) s -5 437 M -( K3 = HASH\(K || H || K1 || K2\)) s -5 426 M -( ...) s -5 415 M -( key = K1 || K2 || K3 || ...) s -5 393 M -( This process will lose entropy if the amount of entropy in K is) s -5 382 M -( larger than the internal state size of HASH.) s -5 360 M -(6.3 Taking Keys Into Use) s -5 338 M -( Key exchange ends by each side sending an SSH_MSG_NEWKEYS message.) s -5 327 M -( This message is sent with the old keys and algorithms. All messages) s -5 316 M -( sent after this message MUST use the new keys and algorithms.) s -5 283 M -( When this message is received, the new keys and algorithms MUST be) s -5 272 M -( taken into use for receiving.) s -5 239 M -( This message is the only valid message after key exchange, in) s -5 228 M -( addition to SSH_MSG_DEBUG, SSH_MSG_DISCONNECT and SSH_MSG_IGNORE) s -5 217 M -( messages. The purpose of this message is to ensure that a party is) s -5 206 M -( able to respond with a disconnect message that the other party can) s -5 195 M -( understand if something goes wrong with the key exchange.) s -5 184 M -( Implementations MUST NOT accept any other messages after key exchange) s -5 173 M -( before receiving SSH_MSG_NEWKEYS.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 18 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( byte SSH_MSG_NEWKEYS) s -5 657 M -(7. Diffie-Hellman Key Exchange) s -5 635 M -( The Diffie-Hellman key exchange provides a shared secret that can not) s -5 624 M -( be determined by either party alone. The key exchange is combined) s -5 613 M -( with a signature with the host key to provide host authentication.) s -5 580 M -( In the following description \(C is the client, S is the server; p is) s -5 569 M -( a large safe prime, g is a generator for a subgroup of GF\(p\), and q) s -5 558 M -( is the order of the subgroup; V_S is S's version string; V_C is C's) s -5 547 M -( version string; K_S is S's public host key; I_C is C's KEXINIT) s -5 536 M -( message and I_S S's KEXINIT message which have been exchanged before) s -5 525 M -( this part begins\):) s -5 492 M -( 1. C generates a random number x \(1 < x < q\) and computes e = g^x) s -5 481 M -( mod p. C sends "e" to S.) s -5 459 M -( 2. S generates a random number y \(0 < y < q\) and computes f = g^y) s -5 448 M -( mod p. S receives "e". It computes K = e^y mod p, H = hash\(V_C) s -5 437 M -( || V_S || I_C || I_S || K_S || e || f || K\) \(these elements are) s -5 426 M -( encoded according to their types; see below\), and signature s on) s -5 415 M -( H with its private host key. S sends "K_S || f || s" to C. The) s -5 404 M -( signing operation may involve a second hashing operation.) s -5 382 M -( 3. C verifies that K_S really is the host key for S \(e.g. using) s -5 371 M -( certificates or a local database\). C is also allowed to accept) s -5 360 M -( the key without verification; however, doing so will render the) s -5 349 M -( protocol insecure against active attacks \(but may be desirable) s -5 338 M -( for practical reasons in the short term in many environments\). C) s -5 327 M -( then computes K = f^x mod p, H = hash\(V_C || V_S || I_C || I_S ||) s -5 316 M -( K_S || e || f || K\), and verifies the signature s on H.) s -5 294 M -( Either side MUST NOT send or accept e or f values that are not in the) s -5 283 M -( range [1, p-1]. If this condition is violated, the key exchange) s -5 272 M -( fails.) s -5 239 M -( This is implemented with the following messages. The hash algorithm) s -5 228 M -( for computing the exchange hash is defined by the method name, and is) s -5 217 M -( called HASH. The public key algorithm for signing is negotiated with) s -5 206 M -( the KEXINIT messages.) s -5 184 M -( First, the client sends the following:) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]) s -_R -S -PStoPSsaved restore -%%Page: (18,19) 10 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 19 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( byte SSH_MSG_KEXDH_INIT) s -5 679 M -( mpint e) s -5 646 M -( The server responds with the following:) s -5 624 M -( byte SSH_MSG_KEXDH_REPLY) s -5 613 M -( string server public host key and certificates \(K_S\)) s -5 602 M -( mpint f) s -5 591 M -( string signature of H) s -5 569 M -( The hash H is computed as the HASH hash of the concatenation of the) s -5 558 M -( following:) s -5 536 M -( string V_C, the client's version string \(CR and NL excluded\)) s -5 525 M -( string V_S, the server's version string \(CR and NL excluded\)) s -5 514 M -( string I_C, the payload of the client's SSH_MSG_KEXINIT) s -5 503 M -( string I_S, the payload of the server's SSH_MSG_KEXINIT) s -5 492 M -( string K_S, the host key) s -5 481 M -( mpint e, exchange value sent by the client) s -5 470 M -( mpint f, exchange value sent by the server) s -5 459 M -( mpint K, the shared secret) s -5 437 M -( This value is called the exchange hash, and it is used to) s -5 426 M -( authenticate the key exchange. The exchange hash SHOULD be kept) s -5 415 M -( secret.) s -5 382 M -( The signature algorithm MUST be applied over H, not the original) s -5 371 M -( data. Most signature algorithms include hashing and additional) s -5 360 M -( padding. For example, "ssh-dss" specifies SHA-1 hashing; in that) s -5 349 M -( case, the data is first hashed with HASH to compute H, and H is then) s -5 338 M -( hashed with SHA-1 as part of the signing operation.) s -5 316 M -(7.1 diffie-hellman-group1-sha1) s -5 294 M -( The "diffie-hellman-group1-sha1" method specifies Diffie-Hellman key) s -5 283 M -( exchange with SHA-1 as HASH, and Oakley group 14 [RFC3526] \(2048-bit) s -5 272 M -( MODP Group\). It is included below in hexadecimal and decimal.) s -5 250 M -( The prime p is equal to 2^1024 - 2^960 - 1 + 2^64 * floor\( 2^894 Pi +) s -5 239 M -( 129093 \). Its hexadecimal value is:) s -5 217 M -( FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1) s -5 206 M -( 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD) s -5 195 M -( EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245) s -5 184 M -( E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED) s -5 173 M -( EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 20 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( FFFFFFFF FFFFFFFF.) s -5 668 M -( In decimal, this value is:) s -5 646 M -( 179769313486231590770839156793787453197860296048756011706444) s -5 635 M -( 423684197180216158519368947833795864925541502180565485980503) s -5 624 M -( 646440548199239100050792877003355816639229553136239076508735) s -5 613 M -( 759914822574862575007425302077447712589550957937778424442426) s -5 602 M -( 617334727629299387668709205606050270810842907692932019128194) s -5 591 M -( 467627007.) s -5 569 M -( The generator used with this prime is g = 2. The group order q is \(p) s -5 558 M -( - 1\) / 2.) s -5 536 M -(8. Key Re-Exchange) s -5 514 M -( Key re-exchange is started by sending an SSH_MSG_KEXINIT packet when) s -5 503 M -( not already doing a key exchange \(as described in Section Section) s -5 492 M -( 6.1\). When this message is received, a party MUST respond with its) s -5 481 M -( own SSH_MSG_KEXINIT message except when the received SSH_MSG_KEXINIT) s -5 470 M -( already was a reply. Either party MAY initiate the re-exchange, but) s -5 459 M -( roles MUST NOT be changed \(i.e., the server remains the server, and) s -5 448 M -( the client remains the client\).) s -5 415 M -( Key re-exchange is performed using whatever encryption was in effect) s -5 404 M -( when the exchange was started. Encryption, compression, and MAC) s -5 393 M -( methods are not changed before a new SSH_MSG_NEWKEYS is sent after) s -5 382 M -( the key exchange \(as in the initial key exchange\). Re-exchange is) s -5 371 M -( processed identically to the initial key exchange, except for the) s -5 360 M -( session identifier that will remain unchanged. It is permissible to) s -5 349 M -( change some or all of the algorithms during the re-exchange. Host) s -5 338 M -( keys can also change. All keys and initialization vectors are) s -5 327 M -( recomputed after the exchange. Compression and encryption contexts) s -5 316 M -( are reset.) s -5 283 M -( It is recommended that the keys are changed after each gigabyte of) s -5 272 M -( transmitted data or after each hour of connection time, whichever) s -5 261 M -( comes sooner. However, since the re-exchange is a public key) s -5 250 M -( operation, it requires a fair amount of processing power and should) s -5 239 M -( not be performed too often.) s -5 206 M -( More application data may be sent after the SSH_MSG_NEWKEYS packet) s -5 195 M -( has been sent; key exchange does not affect the protocols that lie) s -5 184 M -( above the SSH transport layer.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]) s -_R -S -PStoPSsaved restore -%%Page: (20,21) 11 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 21 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -(9. Service Request) s -5 668 M -( After the key exchange, the client requests a service. The service is) s -5 657 M -( identified by a name. The format of names and procedures for defining) s -5 646 M -( new names are defined in [SSH-ARCH].) s -5 613 M -( Currently, the following names have been reserved:) s -5 591 M -( ssh-userauth) s -5 580 M -( ssh-connection) s -5 558 M -( Similar local naming policy is applied to the service names, as is) s -5 547 M -( applied to the algorithm names; a local service should use the) s -5 536 M -( "servicename@domain" syntax.) s -5 514 M -( byte SSH_MSG_SERVICE_REQUEST) s -5 503 M -( string service name) s -5 481 M -( If the server rejects the service request, it SHOULD send an) s -5 470 M -( appropriate SSH_MSG_DISCONNECT message and MUST disconnect.) s -5 437 M -( When the service starts, it may have access to the session identifier) s -5 426 M -( generated during the key exchange.) s -5 393 M -( If the server supports the service \(and permits the client to use) s -5 382 M -( it\), it MUST respond with the following:) s -5 360 M -( byte SSH_MSG_SERVICE_ACCEPT) s -5 349 M -( string service name) s -5 327 M -( Message numbers used by services should be in the area reserved for) s -5 316 M -( them \(see Section 6 in [SSH-ARCH]\). The transport level will) s -5 305 M -( continue to process its own messages.) s -5 272 M -( Note that after a key exchange with implicit server authentication,) s -5 261 M -( the client MUST wait for response to its service request message) s -5 250 M -( before sending any further data.) s -5 228 M -(10. Additional Messages) s -5 206 M -( Either party may send any of the following messages at any time.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 22 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -(10.1 Disconnection Message) s -5 668 M -( byte SSH_MSG_DISCONNECT) s -5 657 M -( uint32 reason code) s -5 646 M -( string description [RFC2279]) s -5 635 M -( string language tag [RFC3066]) s -5 613 M -( This message causes immediate termination of the connection. All) s -5 602 M -( implementations MUST be able to process this message; they SHOULD be) s -5 591 M -( able to send this message.) s -5 569 M -( The sender MUST NOT send or receive any data after this message, and) s -5 558 M -( the recipient MUST NOT accept any data after receiving this message.) s -5 547 M -( The description field gives a more specific explanation in a) s -5 536 M -( human-readable form. The error code gives the reason in a more) s -5 525 M -( machine-readable format \(suitable for localization\), and can have the) s -5 514 M -( following values:) s -5 492 M -( #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1) s -5 481 M -( #define SSH_DISCONNECT_PROTOCOL_ERROR 2) s -5 470 M -( #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3) s -5 459 M -( #define SSH_DISCONNECT_RESERVED 4) s -5 448 M -( #define SSH_DISCONNECT_MAC_ERROR 5) s -5 437 M -( #define SSH_DISCONNECT_COMPRESSION_ERROR 6) s -5 426 M -( #define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7) s -5 415 M -( #define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8) s -5 404 M -( #define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9) s -5 393 M -( #define SSH_DISCONNECT_CONNECTION_LOST 10) s -5 382 M -( #define SSH_DISCONNECT_BY_APPLICATION 11) s -5 371 M -( #define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12) s -5 360 M -( #define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13) s -5 349 M -( #define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14) s -5 338 M -( #define SSH_DISCONNECT_ILLEGAL_USER_NAME 15) s -5 316 M -( If the description string is displayed, control character filtering) s -5 305 M -( discussed in [SSH-ARCH] should be used to avoid attacks by sending) s -5 294 M -( terminal control characters.) s -5 272 M -(10.2 Ignored Data Message) s -5 250 M -( byte SSH_MSG_IGNORE) s -5 239 M -( string data) s -5 217 M -( All implementations MUST understand \(and ignore\) this message at any) s -5 206 M -( time \(after receiving the protocol version\). No implementation is) s -5 195 M -( required to send them. This message can be used as an additional) s -5 184 M -( protection measure against advanced traffic analysis techniques.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]) s -_R -S -PStoPSsaved restore -%%Page: (22,23) 12 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 23 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -(10.3 Debug Message) s -5 668 M -( byte SSH_MSG_DEBUG) s -5 657 M -( boolean always_display) s -5 646 M -( string message [RFC2279]) s -5 635 M -( string language tag [RFC3066]) s -5 613 M -( All implementations MUST understand this message, but they are) s -5 602 M -( allowed to ignore it. This message is used to pass the other side) s -5 591 M -( information that may help debugging. If always_display is TRUE, the) s -5 580 M -( message SHOULD be displayed. Otherwise, it SHOULD NOT be displayed) s -5 569 M -( unless debugging information has been explicitly requested by the) s -5 558 M -( user.) s -5 525 M -( The message doesn't need to contain a newline. It is, however,) s -5 514 M -( allowed to consist of multiple lines separated by CRLF \(Carriage) s -5 503 M -( Return - Line Feed\) pairs.) s -5 470 M -( If the message string is displayed, terminal control character) s -5 459 M -( filtering discussed in [SSH-ARCH] should be used to avoid attacks by) s -5 448 M -( sending terminal control characters.) s -5 426 M -(10.4 Reserved Messages) s -5 404 M -( An implementation MUST respond to all unrecognized messages with an) s -5 393 M -( SSH_MSG_UNIMPLEMENTED message in the order in which the messages were) s -5 382 M -( received. Such messages MUST be otherwise ignored. Later protocol) s -5 371 M -( versions may define other meanings for these message types.) s -5 349 M -( byte SSH_MSG_UNIMPLEMENTED) s -5 338 M -( uint32 packet sequence number of rejected message) s -5 305 M -(11. Summary of Message Numbers) s -5 283 M -( The following message numbers have been defined in this protocol:) s -5 261 M -( #define SSH_MSG_DISCONNECT 1) s -5 250 M -( #define SSH_MSG_IGNORE 2) s -5 239 M -( #define SSH_MSG_UNIMPLEMENTED 3) s -5 228 M -( #define SSH_MSG_DEBUG 4) s -5 217 M -( #define SSH_MSG_SERVICE_REQUEST 5) s -5 206 M -( #define SSH_MSG_SERVICE_ACCEPT 6) s -5 184 M -( #define SSH_MSG_KEXINIT 20) s -5 173 M -( #define SSH_MSG_NEWKEYS 21) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 23]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 24 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( /* Numbers 30-49 used for kex packets.) s -5 679 M -( Different kex methods may reuse message numbers in) s -5 668 M -( this range. */) s -5 646 M -( #define SSH_MSG_KEXDH_INIT 30) s -5 635 M -( #define SSH_MSG_KEXDH_REPLY 31) s -5 602 M -(12. IANA Considerations) s -5 580 M -( This document is part of a set, the IANA considerations for the SSH) s -5 569 M -( protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],) s -5 558 M -( [SSH-CONNECT] are detailed in [SSH-NUMBERS].) s -5 536 M -(13. Security Considerations) s -5 514 M -( This protocol provides a secure encrypted channel over an insecure) s -5 503 M -( network. It performs server host authentication, key exchange,) s -5 492 M -( encryption, and integrity protection. It also derives a unique) s -5 481 M -( session id that may be used by higher-level protocols.) s -5 459 M -( Full security considerations for this protocol are provided in) s -5 448 M -( Section 8 of [SSH-ARCH]) s -5 426 M -(14. Intellectual Property) s -5 404 M -( The IETF takes no position regarding the validity or scope of any) s -5 393 M -( intellectual property or other rights that might be claimed to) s -5 382 M -( pertain to the implementation or use of the technology described in) s -5 371 M -( this document or the extent to which any license under such rights) s -5 360 M -( might or might not be available; neither does it represent that it) s -5 349 M -( has made any effort to identify any such rights. Information on the) s -5 338 M -( IETF's procedures with respect to rights in standards-track and) s -5 327 M -( standards-related documentation can be found in BCP-11. Copies of) s -5 316 M -( claims of rights made available for publication and any assurances of) s -5 305 M -( licenses to be made available, or the result of an attempt made to) s -5 294 M -( obtain a general license or permission for the use of such) s -5 283 M -( proprietary rights by implementers or users of this specification can) s -5 272 M -( be obtained from the IETF Secretariat.) s -5 250 M -( The IETF has been notified of intellectual property rights claimed in) s -5 239 M -( regard to some or all of the specification contained in this) s -5 228 M -( document. For more information consult the online list of claimed) s -5 217 M -( rights.) s -5 195 M -(15. Additional Information) s -5 173 M -( The current document editor is: Darren.Moffat@Sun.COM. Comments on) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 24]) s -_R -S -PStoPSsaved restore -%%Page: (24,25) 13 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 25 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( this internet draft should be sent to the IETF SECSH working group,) s -5 679 M -( details at: http://ietf.org/html.charters/secsh-charter.html) s -5 657 M -(Normative) s -5 635 M -( [SSH-ARCH]) s -5 624 M -( Ylonen, T., "SSH Protocol Architecture", I-D) s -5 613 M -( draft-ietf-architecture-15.txt, Oct 2003.) s -5 591 M -( [SSH-TRANS]) s -5 580 M -( Ylonen, T., "SSH Transport Layer Protocol", I-D) s -5 569 M -( draft-ietf-transport-17.txt, Oct 2003.) s -5 547 M -( [SSH-USERAUTH]) s -5 536 M -( Ylonen, T., "SSH Authentication Protocol", I-D) s -5 525 M -( draft-ietf-userauth-18.txt, Oct 2003.) s -5 503 M -( [SSH-CONNECT]) s -5 492 M -( Ylonen, T., "SSH Connection Protocol", I-D) s -5 481 M -( draft-ietf-connect-18.txt, Oct 2003.) s -5 459 M -( [SSH-NUMBERS]) s -5 448 M -( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s -5 437 M -( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s -5 426 M -( 2003.) s -5 404 M -( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s -5 393 M -( Requirement Levels", BCP 14, RFC 2119, March 1997.) s -5 371 M -(Informative) s -5 349 M -( [FIPS-186]) s -5 338 M -( Federal Information Processing Standards Publication,) s -5 327 M -( "FIPS PUB 186, Digital Signature Standard", May 1994.) s -5 305 M -( [FIPS-197]) s -5 294 M -( NIST, "FIPS PUB 197 Advanced Encryption Standard \(AES\)",) s -5 283 M -( November 2001.) s -5 261 M -( [FIPS-46-3]) s -5 250 M -( U.S. Dept. of Commerce, "FIPS PUB 46-3, Data Encryption) s -5 239 M -( Standard \(DES\)", October 1999.) s -5 217 M -( [RFC2459] Housley, R., Ford, W., Polk, T. and D. Solo, "Internet) s -5 206 M -( X.509 Public Key Infrastructure Certificate and CRL) s -5 195 M -( Profile", RFC 2459, January 1999.) s -5 173 M -( [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 25]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 26 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( STD 13, RFC 1034, November 1987.) s -5 668 M -( [RFC3066] Alvestrand, H., "Tags for the Identification of) s -5 657 M -( Languages", BCP 47, RFC 3066, January 2001.) s -5 635 M -( [RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data Format) s -5 624 M -( Specification version 3.3", RFC 1950, May 1996.) s -5 602 M -( [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification) s -5 591 M -( version 1.3", RFC 1951, May 1996.) s -5 569 M -( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s -5 558 M -( 10646", RFC 2279, January 1998.) s -5 536 M -( [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:) s -5 525 M -( Keyed-Hashing for Message Authentication", RFC 2104,) s -5 514 M -( February 1997.) s -5 492 M -( [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144,) s -5 481 M -( May 1997.) s -5 459 M -( [RFC2440] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer,) s -5 448 M -( "OpenPGP Message Format", RFC 2440, November 1998.) s -5 426 M -( [RFC2693] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas,) s -5 415 M -( B. and T. Ylonen, "SPKI Certificate Theory", RFC 2693,) s -5 404 M -( September 1999.) s -5 382 M -( [RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential \(MODP\)) s -5 371 M -( Diffie-Hellman groups for Internet Key Exchange \(IKE\)",) s -5 360 M -( RFC 3526, May 2003.) s -5 338 M -( [SCHNEIER]) s -5 327 M -( Schneier, B., "Applied Cryptography Second Edition:) s -5 316 M -( protocols algorithms and source in code in C", 1996.) s -5 294 M -( [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A) s -5 283 M -( 128-Bit Block Cipher, 1st Edition", March 1999.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 26]) s -_R -S -PStoPSsaved restore -%%Page: (26,27) 14 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 27 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -(Authors' Addresses) s -5 668 M -( Tatu Ylonen) s -5 657 M -( SSH Communications Security Corp) s -5 646 M -( Fredrikinkatu 42) s -5 635 M -( HELSINKI FIN-00100) s -5 624 M -( Finland) s -5 602 M -( EMail: ylo@ssh.com) s -5 569 M -( Darren J. Moffat \(editor\)) s -5 558 M -( Sun Microsystems, Inc) s -5 547 M -( 17 Network Circle) s -5 536 M -( Menlo Park 95025) s -5 525 M -( USA) s -5 503 M -( EMail: Darren.Moffat@Sun.COM) s -5 481 M -(Appendix A. Contibutors) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 27]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 28 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -(Intellectual Property Statement) s -5 668 M -( The IETF takes no position regarding the validity or scope of any) s -5 657 M -( intellectual property or other rights that might be claimed to) s -5 646 M -( pertain to the implementation or use of the technology described in) s -5 635 M -( this document or the extent to which any license under such rights) s -5 624 M -( might or might not be available; neither does it represent that it) s -5 613 M -( has made any effort to identify any such rights. Information on the) s -5 602 M -( IETF's procedures with respect to rights in standards-track and) s -5 591 M -( standards-related documentation can be found in BCP-11. Copies of) s -5 580 M -( claims of rights made available for publication and any assurances of) s -5 569 M -( licenses to be made available, or the result of an attempt made to) s -5 558 M -( obtain a general license or permission for the use of such) s -5 547 M -( proprietary rights by implementors or users of this specification can) s -5 536 M -( be obtained from the IETF Secretariat.) s -5 514 M -( The IETF invites any interested party to bring to its attention any) s -5 503 M -( copyrights, patents or patent applications, or other proprietary) s -5 492 M -( rights which may cover technology that may be required to practice) s -5 481 M -( this standard. Please address the information to the IETF Executive) s -5 470 M -( Director.) s -5 448 M -( The IETF has been notified of intellectual property rights claimed in) s -5 437 M -( regard to some or all of the specification contained in this) s -5 426 M -( document. For more information consult the online list of claimed) s -5 415 M -( rights.) s -5 382 M -(Full Copyright Statement) s -5 360 M -( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s -5 338 M -( This document and translations of it may be copied and furnished to) s -5 327 M -( others, and derivative works that comment on or otherwise explain it) s -5 316 M -( or assist in its implementation may be prepared, copied, published) s -5 305 M -( and distributed, in whole or in part, without restriction of any) s -5 294 M -( kind, provided that the above copyright notice and this paragraph are) s -5 283 M -( included on all such copies and derivative works. However, this) s -5 272 M -( document itself may not be modified in any way, such as by removing) s -5 261 M -( the copyright notice or references to the Internet Society or other) s -5 250 M -( Internet organizations, except as needed for the purpose of) s -5 239 M -( developing Internet standards in which case the procedures for) s -5 228 M -( copyrights defined in the Internet Standards process must be) s -5 217 M -( followed, or as required to translate it into languages other than) s -5 206 M -( English.) s -5 184 M -( The limited permissions granted above are perpetual and will not be) s -5 173 M -( revoked by the Internet Society or its successors or assignees.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 28]) s -_R -S -PStoPSsaved restore -%%Page: (28,29) 15 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 29 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Transport Layer Protocol Oct 2003) s -5 690 M -( This document and the information contained herein is provided on an) s -5 679 M -( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s -5 668 M -( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s -5 657 M -( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s -5 646 M -( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s -5 635 M -( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s -5 602 M -(Acknowledgment) s -5 580 M -( Funding for the RFC Editor function is currently provided by the) s -5 569 M -( Internet Society.) s -5 129 M -(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 29]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -showpage -PStoPSsaved restore -%%Trailer -%%Pages: 29 -%%DocumentNeededResources: font Courier-Bold Courier -%%EOF diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt deleted file mode 100644 index 9073ea52b2..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt +++ /dev/null @@ -1,1624 +0,0 @@ - - - -Network Working Group T. Ylonen -Internet-Draft SSH Communications Security Corp -Expires: March 31, 2004 D. Moffat, Editor, Ed. - Sun Microsystems, Inc - Oct 2003 - - - SSH Transport Layer Protocol - draft-ietf-secsh-transport-17.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on March 31, 2004. - -Copyright Notice - - Copyright (C) The Internet Society (2003). All Rights Reserved. - -Abstract - - SSH is a protocol for secure remote login and other secure network - services over an insecure network. - - This document describes the SSH transport layer protocol which - typically runs on top of TCP/IP. The protocol can be used as a basis - for a number of secure network services. It provides strong - encryption, server authentication, and integrity protection. It may - also provide compression. - - Key exchange method, public key algorithm, symmetric encryption - algorithm, message authentication algorithm, and hash algorithm are - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - all negotiated. - - This document also describes the Diffie-Hellman key exchange method - and the minimal set of algorithms that are needed to implement the - SSH transport layer protocol. - -Table of Contents - - 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 - 3. Conventions Used in This Document . . . . . . . . . . . . . 3 - 4. Connection Setup . . . . . . . . . . . . . . . . . . . . . . 3 - 4.1 Use over TCP/IP . . . . . . . . . . . . . . . . . . . . . . 4 - 4.2 Protocol Version Exchange . . . . . . . . . . . . . . . . . 4 - 4.3 Compatibility With Old SSH Versions . . . . . . . . . . . . 4 - 4.3.1 Old Client, New Server . . . . . . . . . . . . . . . . . . . 5 - 4.3.2 New Client, Old Server . . . . . . . . . . . . . . . . . . . 5 - 5. Binary Packet Protocol . . . . . . . . . . . . . . . . . . . 5 - 5.1 Maximum Packet Length . . . . . . . . . . . . . . . . . . . 6 - 5.2 Compression . . . . . . . . . . . . . . . . . . . . . . . . 7 - 5.3 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . 7 - 5.4 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 9 - 5.5 Key Exchange Methods . . . . . . . . . . . . . . . . . . . . 10 - 5.6 Public Key Algorithms . . . . . . . . . . . . . . . . . . . 11 - 6. Key Exchange . . . . . . . . . . . . . . . . . . . . . . . . 13 - 6.1 Algorithm Negotiation . . . . . . . . . . . . . . . . . . . 13 - 6.2 Output from Key Exchange . . . . . . . . . . . . . . . . . . 16 - 6.3 Taking Keys Into Use . . . . . . . . . . . . . . . . . . . . 17 - 7. Diffie-Hellman Key Exchange . . . . . . . . . . . . . . . . 18 - 7.1 diffie-hellman-group1-sha1 . . . . . . . . . . . . . . . . . 19 - 8. Key Re-Exchange . . . . . . . . . . . . . . . . . . . . . . 20 - 9. Service Request . . . . . . . . . . . . . . . . . . . . . . 21 - 10. Additional Messages . . . . . . . . . . . . . . . . . . . . 21 - 10.1 Disconnection Message . . . . . . . . . . . . . . . . . . . 22 - 10.2 Ignored Data Message . . . . . . . . . . . . . . . . . . . . 22 - 10.3 Debug Message . . . . . . . . . . . . . . . . . . . . . . . 23 - 10.4 Reserved Messages . . . . . . . . . . . . . . . . . . . . . 23 - 11. Summary of Message Numbers . . . . . . . . . . . . . . . . . 23 - 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 24 - 13. Security Considerations . . . . . . . . . . . . . . . . . . 24 - 14. Intellectual Property . . . . . . . . . . . . . . . . . . . 24 - 15. Additional Information . . . . . . . . . . . . . . . . . . . 24 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 26 - Normative . . . . . . . . . . . . . . . . . . . . . . . . . 25 - Informative . . . . . . . . . . . . . . . . . . . . . . . . 25 - A. Contibutors . . . . . . . . . . . . . . . . . . . . . . . . 27 - Intellectual Property and Copyright Statements . . . . . . . 28 - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - -1. Contributors - - The major original contributors of this document were: Tatu Ylonen, - Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications - Security Corp), and Markku-Juhani O. Saarinen (University of - Jyvaskyla) - - The document editor is: Darren.Moffat@Sun.COM. Comments on this - internet draft should be sent to the IETF SECSH working group, - details at: http://ietf.org/html.charters/secsh-charter.html - -2. Introduction - - The SSH transport layer is a secure low level transport protocol. It - provides strong encryption, cryptographic host authentication, and - integrity protection. - - Authentication in this protocol level is host-based; this protocol - does not perform user authentication. A higher level protocol for - user authentication can be designed on top of this protocol. - - The protocol has been designed to be simple, flexible, to allow - parameter negotiation, and to minimize the number of round-trips. - Key exchange method, public key algorithm, symmetric encryption - algorithm, message authentication algorithm, and hash algorithm are - all negotiated. It is expected that in most environments, only 2 - round-trips will be needed for full key exchange, server - authentication, service request, and acceptance notification of - service request. The worst case is 3 round-trips. - -3. Conventions Used in This Document - - The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", - and "MAY" that appear in this document are to be interpreted as - described in [RFC2119]. - - The used data types and terminology are specified in the architecture - document [SSH-ARCH]. - - The architecture document also discusses the algorithm naming - conventions that MUST be used with the SSH protocols. - -4. Connection Setup - - SSH works over any 8-bit clean, binary-transparent transport. The - underlying transport SHOULD protect against transmission errors as - such errors cause the SSH connection to terminate. - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - The client initiates the connection. - -4.1 Use over TCP/IP - - When used over TCP/IP, the server normally listens for connections on - port 22. This port number has been registered with the IANA, and has - been officially assigned for SSH. - -4.2 Protocol Version Exchange - - When the connection has been established, both sides MUST send an - identification string of the form "SSH-protoversion-softwareversion - comments", followed by carriage return and newline characters (ASCII - 13 and 10, respectively). Both sides MUST be able to process - identification strings without carriage return character. No null - character is sent. The maximum length of the string is 255 - characters, including the carriage return and newline. - - The part of the identification string preceding carriage return and - newline is used in the Diffie-Hellman key exchange (see Section - Section 7). - - The server MAY send other lines of data before sending the version - string. Each line SHOULD be terminated by a carriage return and - newline. Such lines MUST NOT begin with "SSH-", and SHOULD be - encoded in ISO-10646 UTF-8 [RFC2279] (language is not specified). - Clients MUST be able to process such lines; they MAY be silently - ignored, or MAY be displayed to the client user; if they are - displayed, control character filtering discussed in [SSH-ARCH] SHOULD - be used. The primary use of this feature is to allow TCP-wrappers to - display an error message before disconnecting. - - Version strings MUST consist of printable US-ASCII characters, not - including whitespaces or a minus sign (-). The version string is - primarily used to trigger compatibility extensions and to indicate - the capabilities of an implementation. The comment string should - contain additional information that might be useful in solving user - problems. - - The protocol version described in this document is 2.0. - - Key exchange will begin immediately after sending this identifier. - All packets following the identification string SHALL use the binary - packet protocol, to be described below. - -4.3 Compatibility With Old SSH Versions - - During the transition period, it is important to be able to work in a - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - way that is compatible with the installed SSH clients and servers - that use an older version of the protocol. Information in this - section is only relevant for implementations supporting compatibility - with SSH versions 1.x. There is no standards track or informational - draft available that defines the SSH 1.x protocol. The only known - documentation of the 1.x protocol is contained in README files that - are shipped along with the source code. - -4.3.1 Old Client, New Server - - Server implementations MAY support a configurable "compatibility" - flag that enables compatibility with old versions. When this flag is - on, the server SHOULD identify its protocol version as "1.99". - Clients using protocol 2.0 MUST be able to identify this as identical - to "2.0". In this mode the server SHOULD NOT send the carriage - return character (ASCII 13) after the version identification string. - - In the compatibility mode the server SHOULD NOT send any further data - after its initialization string until it has received an - identification string from the client. The server can then determine - whether the client is using an old protocol, and can revert to the - old protocol if required. In the compatibility mode, the server MUST - NOT send additional data before the version string. - - When compatibility with old clients is not needed, the server MAY - send its initial key exchange data immediately after the - identification string. - -4.3.2 New Client, Old Server - - Since the new client MAY immediately send additional data after its - identification string (before receiving server's identification), the - old protocol may already have been corrupted when the client learns - that the server is old. When this happens, the client SHOULD close - the connection to the server, and reconnect using the old protocol. - -5. Binary Packet Protocol - - Each packet is in the following format: - - uint32 packet_length - byte padding_length - byte[n1] payload; n1 = packet_length - padding_length - 1 - byte[n2] random padding; n2 = padding_length - byte[m] mac (message authentication code); m = mac_length - - packet_length - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - The length of the packet (bytes), not including MAC or the - packet_length field itself. - - padding_length - Length of padding (bytes). - - payload - The useful contents of the packet. If compression has been - negotiated, this field is compressed. Initially, compression - MUST be "none". - - random padding - Arbitrary-length padding, such that the total length of - (packet_length || padding_length || payload || padding) is a - multiple of the cipher block size or 8, whichever is larger. - There MUST be at least four bytes of padding. The padding - SHOULD consist of random bytes. The maximum amount of padding - is 255 bytes. - - mac - Message authentication code. If message authentication has - been negotiated, this field contains the MAC bytes. Initially, - the MAC algorithm MUST be "none". - - - Note that length of the concatenation of packet length, padding - length, payload, and padding MUST be a multiple of the cipher block - size or 8, whichever is larger. This constraint MUST be enforced - even when using stream ciphers. Note that the packet length field is - also encrypted, and processing it requires special care when sending - or receiving packets. - - The minimum size of a packet is 16 (or the cipher block size, - whichever is larger) bytes (plus MAC); implementations SHOULD decrypt - the length after receiving the first 8 (or cipher block size, - whichever is larger) bytes of a packet. - -5.1 Maximum Packet Length - - All implementations MUST be able to process packets with uncompressed - payload length of 32768 bytes or less and total packet size of 35000 - bytes or less (including length, padding length, payload, padding, - and MAC.). The maximum of 35000 bytes is an arbitrary chosen value - larger than uncompressed size. Implementations SHOULD support longer - packets, where they might be needed, e.g. if an implementation wants - to send a very large number of certificates. Such packets MAY be - sent if the version string indicates that the other party is able to - process them. However, implementations SHOULD check that the packet - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - length is reasonable for the implementation to avoid - denial-of-service and/or buffer overflow attacks. - -5.2 Compression - - If compression has been negotiated, the payload field (and only it) - will be compressed using the negotiated algorithm. The length field - and MAC will be computed from the compressed payload. Encryption will - be done after compression. - - Compression MAY be stateful, depending on the method. Compression - MUST be independent for each direction, and implementations MUST - allow independently choosing the algorithm for each direction. - - The following compression methods are currently defined: - - none REQUIRED no compression - zlib OPTIONAL ZLIB (LZ77) compression - - The "zlib" compression is described in [RFC1950] and in [RFC1951]. - The compression context is initialized after each key exchange, and - is passed from one packet to the next with only a partial flush being - performed at the end of each packet. A partial flush means that the - current compressed block is ended and all data will be output. If the - current block is not a stored block, one or more empty blocks are - added after the current block to ensure that there are at least 8 - bits counting from the start of the end-of-block code of the current - block to the end of the packet payload. - - Additional methods may be defined as specified in [SSH-ARCH]. - -5.3 Encryption - - An encryption algorithm and a key will be negotiated during the key - exchange. When encryption is in effect, the packet length, padding - length, payload and padding fields of each packet MUST be encrypted - with the given algorithm. - - The encrypted data in all packets sent in one direction SHOULD be - considered a single data stream. For example, initialization vectors - SHOULD be passed from the end of one packet to the beginning of the - next packet. All ciphers SHOULD use keys with an effective key length - of 128 bits or more. - - The ciphers in each direction MUST run independently of each other, - and implementations MUST allow independently choosing the algorithm - for each direction (if multiple algorithms are allowed by local - policy). - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - The following ciphers are currently defined: - - 3des-cbc REQUIRED three-key 3DES in CBC mode - blowfish-cbc OPTIONALi Blowfish in CBC mode - twofish256-cbc OPTIONAL Twofish in CBC mode, - with 256-bit key - twofish-cbc OPTIONAL alias for "twofish256-cbc" (this - is being retained for - historical reasons) - twofish192-cbc OPTIONAL Twofish with 192-bit key - twofish128-cbc OPTIONAL Twofish with 128-bit key - aes256-cbc OPTIONAL AES (Rijndael) in CBC mode, - with 256-bit key - aes192-cbc OPTIONAL AES with 192-bit key - aes128-cbc RECOMMENDED AES with 128-bit key - serpent256-cbc OPTIONAL Serpent in CBC mode, with - 256-bit key - serpent192-cbc OPTIONAL Serpent with 192-bit key - serpent128-cbc OPTIONAL Serpent with 128-bit key - arcfour OPTIONAL the ARCFOUR stream cipher - idea-cbc OPTIONAL IDEA in CBC mode - cast128-cbc OPTIONAL CAST-128 in CBC mode - none OPTIONAL no encryption; NOT RECOMMENDED - - The "3des-cbc" cipher is three-key triple-DES - (encrypt-decrypt-encrypt), where the first 8 bytes of the key are - used for the first encryption, the next 8 bytes for the decryption, - and the following 8 bytes for the final encryption. This requires 24 - bytes of key data (of which 168 bits are actually used). To - implement CBC mode, outer chaining MUST be used (i.e., there is only - one initialization vector). This is a block cipher with 8 byte - blocks. This algorithm is defined in [FIPS-46-3] - - The "blowfish-cbc" cipher is Blowfish in CBC mode, with 128 bit keys - [SCHNEIER]. This is a block cipher with 8 byte blocks. - - The "twofish-cbc" or "twofish256-cbc" cipher is Twofish in CBC mode, - with 256 bit keys as described [TWOFISH]. This is a block cipher with - 16 byte blocks. - - The "twofish192-cbc" cipher. Same as above but with 192-bit key. - - The "twofish128-cbc" cipher. Same as above but with 128-bit key. - - The "aes256-cbc" cipher is AES (Advanced Encryption Standard) - [FIPS-197], formerly Rijndael, in CBC mode. This version uses 256-bit - key. - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - The "aes192-cbc" cipher. Same as above but with 192-bit key. - - The "aes128-cbc" cipher. Same as above but with 128-bit key. - - The "serpent256-cbc" cipher in CBC mode, with 256-bit key as - described in the Serpent AES submission. - - The "serpent192-cbc" cipher. Same as above but with 192-bit key. - - The "serpent128-cbc" cipher. Same as above but with 128-bit key. - - The "arcfour" is the Arcfour stream cipher with 128 bit keys. The - Arcfour cipher is believed to be compatible with the RC4 cipher - [SCHNEIER]. RC4 is a registered trademark of RSA Data Security Inc. - Arcfour (and RC4) has problems with weak keys, and should be used - with caution. - - The "idea-cbc" cipher is the IDEA cipher in CBC mode [SCHNEIER]. - - The "cast128-cbc" cipher is the CAST-128 cipher in CBC mode - [RFC2144]. - - The "none" algorithm specifies that no encryption is to be done. - Note that this method provides no confidentiality protection, and it - is not recommended. Some functionality (e.g. password - authentication) may be disabled for security reasons if this cipher - is chosen. - - Additional methods may be defined as specified in [SSH-ARCH]. - -5.4 Data Integrity - - Data integrity is protected by including with each packet a message - authentication code (MAC) that is computed from a shared secret, - packet sequence number, and the contents of the packet. - - The message authentication algorithm and key are negotiated during - key exchange. Initially, no MAC will be in effect, and its length - MUST be zero. After key exchange, the selected MAC will be computed - before encryption from the concatenation of packet data: - - mac = MAC(key, sequence_number || unencrypted_packet) - - where unencrypted_packet is the entire packet without MAC (the length - fields, payload and padding), and sequence_number is an implicit - packet sequence number represented as uint32. The sequence number is - initialized to zero for the first packet, and is incremented after - every packet (regardless of whether encryption or MAC is in use). It - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - is never reset, even if keys/algorithms are renegotiated later. It - wraps around to zero after every 2^32 packets. The packet sequence - number itself is not included in the packet sent over the wire. - - The MAC algorithms for each direction MUST run independently, and - implementations MUST allow choosing the algorithm independently for - both directions. - - The MAC bytes resulting from the MAC algorithm MUST be transmitted - without encryption as the last part of the packet. The number of MAC - bytes depends on the algorithm chosen. - - The following MAC algorithms are currently defined: - - hmac-sha1 REQUIRED HMAC-SHA1 (digest length = key - length = 20) - hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest - length = 12, key length = 20) - hmac-md5 OPTIONAL HMAC-MD5 (digest length = key - length = 16) - hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest - length = 12, key length = 16) - none OPTIONAL no MAC; NOT RECOMMENDED - - Figure 1 - - The "hmac-*" algorithms are described in [RFC2104] The "*-n" MACs use - only the first n bits of the resulting value. - - The hash algorithms are described in [SCHNEIER]. - - Additional methods may be defined as specified in [SSH-ARCH]. - -5.5 Key Exchange Methods - - The key exchange method specifies how one-time session keys are - generated for encryption and for authentication, and how the server - authentication is done. - - Only one REQUIRED key exchange method has been defined: - - diffie-hellman-group1-sha1 REQUIRED - - This method is described later in this document. - - Additional methods may be defined as specified in [SSH-ARCH]. - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - -5.6 Public Key Algorithms - - This protocol has been designed to be able to operate with almost any - public key format, encoding, and algorithm (signature and/or - encryption). - - There are several aspects that define a public key type: - o Key format: how is the key encoded and how are certificates - represented. The key blobs in this protocol MAY contain - certificates in addition to keys. - o Signature and/or encryption algorithms. Some key types may not - support both signing and encryption. Key usage may also be - restricted by policy statements in e.g. certificates. In this - case, different key types SHOULD be defined for the different - policy alternatives. - o Encoding of signatures and/or encrypted data. This includes but is - not limited to padding, byte order, and data formats. - - The following public key and/or certificate formats are currently defined: - - ssh-dss REQUIRED sign Raw DSS Key - ssh-rsa RECOMMENDED sign Raw RSA Key - x509v3-sign-rsa OPTIONAL sign X.509 certificates (RSA key) - x509v3-sign-dss OPTIONAL sign X.509 certificates (DSS key) - spki-sign-rsa OPTIONAL sign SPKI certificates (RSA key) - spki-sign-dss OPTIONAL sign SPKI certificates (DSS key) - pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key) - pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key) - - Additional key types may be defined as specified in [SSH-ARCH]. - - The key type MUST always be explicitly known (from algorithm - negotiation or some other source). It is not normally included in - the key blob. - - Certificates and public keys are encoded as follows: - - string certificate or public key format identifier - byte[n] key/certificate data - - The certificate part may have be a zero length string, but a public - key is required. This is the public key that will be used for - authentication; the certificate sequence contained in the certificate - blob can be used to provide authorization. - - Public key / certifcate formats that do not explicitly specify a - signature format identifier MUST use the public key / certificate - format identifier as the signature identifier. - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - Signatures are encoded as follows: - string signature format identifier (as specified by the - public key / cert format) - byte[n] signature blob in format specific encoding. - - - The "ssh-dss" key format has the following specific encoding: - - string "ssh-dss" - mpint p - mpint q - mpint g - mpint y - - Here the p, q, g, and y parameters form the signature key blob. - - Signing and verifying using this key format is done according to the - Digital Signature Standard [FIPS-186] using the SHA-1 hash. A - description can also be found in [SCHNEIER]. - - The resulting signature is encoded as follows: - - string "ssh-dss" - string dss_signature_blob - - dss_signature_blob is encoded as a string containing r followed by s - (which are 160 bits long integers, without lengths or padding, - unsigned and in network byte order). - - The "ssh-rsa" key format has the following specific encoding: - - string "ssh-rsa" - mpint e - mpint n - - Here the e and n parameters form the signature key blob. - - Signing and verifying using this key format is done according to - [SCHNEIER] and [PKCS1] using the SHA-1 hash. - - The resulting signature is encoded as follows: - - string "ssh-rsa" - string rsa_signature_blob - - rsa_signature_blob is encoded as a string containing s (which is an - integer, without lengths or padding, unsigned and in network byte - order). - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - The "spki-sign-rsa" method indicates that the certificate blob - contains a sequence of SPKI certificates. The format of SPKI - certificates is described in [RFC2693]. This method indicates that - the key (or one of the keys in the certificate) is an RSA-key. - - The "spki-sign-dss". As above, but indicates that the key (or one of - the keys in the certificate) is a DSS-key. - - The "pgp-sign-rsa" method indicates the certificates, the public key, - and the signature are in OpenPGP compatible binary format - ([RFC2440]). This method indicates that the key is an RSA-key. - - The "pgp-sign-dss". As above, but indicates that the key is a - DSS-key. - -6. Key Exchange - - Key exchange begins by each side sending lists of supported - algorithms. Each side has a preferred algorithm in each category, and - it is assumed that most implementations at any given time will use - the same preferred algorithm. Each side MAY guess which algorithm - the other side is using, and MAY send an initial key exchange packet - according to the algorithm if appropriate for the preferred method. - - Guess is considered wrong, if: - o the kex algorithm and/or the host key algorithm is guessed wrong - (server and client have different preferred algorithm), or - o if any of the other algorithms cannot be agreed upon (the - procedure is defined below in Section Section 6.1). - - Otherwise, the guess is considered to be right and the optimistically - sent packet MUST be handled as the first key exchange packet. - - However, if the guess was wrong, and a packet was optimistically sent - by one or both parties, such packets MUST be ignored (even if the - error in the guess would not affect the contents of the initial - packet(s)), and the appropriate side MUST send the correct initial - packet. - - Server authentication in the key exchange MAY be implicit. After a - key exchange with implicit server authentication, the client MUST - wait for response to its service request message before sending any - further data. - -6.1 Algorithm Negotiation - - Key exchange begins by each side sending the following packet: - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - byte SSH_MSG_KEXINIT - byte[16] cookie (random bytes) - string kex_algorithms - string server_host_key_algorithms - string encryption_algorithms_client_to_server - string encryption_algorithms_server_to_client - string mac_algorithms_client_to_server - string mac_algorithms_server_to_client - string compression_algorithms_client_to_server - string compression_algorithms_server_to_client - string languages_client_to_server - string languages_server_to_client - boolean first_kex_packet_follows - uint32 0 (reserved for future extension) - - Each of the algorithm strings MUST be a comma-separated list of - algorithm names (see ''Algorithm Naming'' in [SSH-ARCH]). Each - supported (allowed) algorithm MUST be listed in order of preference. - - The first algorithm in each list MUST be the preferred (guessed) - algorithm. Each string MUST contain at least one algorithm name. - - - cookie - The cookie MUST be a random value generated by the sender. Its - purpose is to make it impossible for either side to fully - determine the keys and the session identifier. - - kex_algorithms - Key exchange algorithms were defined above. The first - algorithm MUST be the preferred (and guessed) algorithm. If - both sides make the same guess, that algorithm MUST be used. - Otherwise, the following algorithm MUST be used to choose a key - exchange method: iterate over client's kex algorithms, one at a - time. Choose the first algorithm that satisfies the following - conditions: - + the server also supports the algorithm, - + if the algorithm requires an encryption-capable host key, - there is an encryption-capable algorithm on the server's - server_host_key_algorithms that is also supported by the - client, and - + if the algorithm requires a signature-capable host key, - there is a signature-capable algorithm on the server's - server_host_key_algorithms that is also supported by the - client. - + If no algorithm satisfying all these conditions can be - found, the connection fails, and both sides MUST disconnect. - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - server_host_key_algorithms - List of the algorithms supported for the server host key. The - server lists the algorithms for which it has host keys; the - client lists the algorithms that it is willing to accept. - (There MAY be multiple host keys for a host, possibly with - different algorithms.) - - Some host keys may not support both signatures and encryption - (this can be determined from the algorithm), and thus not all - host keys are valid for all key exchange methods. - - Algorithm selection depends on whether the chosen key exchange - algorithm requires a signature or encryption capable host key. - It MUST be possible to determine this from the public key - algorithm name. The first algorithm on the client's list that - satisfies the requirements and is also supported by the server - MUST be chosen. If there is no such algorithm, both sides MUST - disconnect. - - encryption_algorithms - Lists the acceptable symmetric encryption algorithms in order - of preference. The chosen encryption algorithm to each - direction MUST be the first algorithm on the client's list - that is also on the server's list. If there is no such - algorithm, both sides MUST disconnect. - - Note that "none" must be explicitly listed if it is to be - acceptable. The defined algorithm names are listed in Section - Section 5.3. - - mac_algorithms - Lists the acceptable MAC algorithms in order of preference. - The chosen MAC algorithm MUST be the first algorithm on the - client's list that is also on the server's list. If there is - no such algorithm, both sides MUST disconnect. - - Note that "none" must be explicitly listed if it is to be - acceptable. The MAC algorithm names are listed in Section - Figure 1. - - compression_algorithms - Lists the acceptable compression algorithms in order of - preference. The chosen compression algorithm MUST be the first - algorithm on the client's list that is also on the server's - list. If there is no such algorithm, both sides MUST - disconnect. - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - Note that "none" must be explicitly listed if it is to be - acceptable. The compression algorithm names are listed in - Section Section 5.2. - - languages - This is a comma-separated list of language tags in order of - preference [RFC3066]. Both parties MAY ignore this list. If - there are no language preferences, this list SHOULD be empty. - Language tags SHOULD NOT be present unless they are known to be - needed by the sending party. - - first_kex_packet_follows - Indicates whether a guessed key exchange packet follows. If a - guessed packet will be sent, this MUST be TRUE. If no guessed - packet will be sent, this MUST be FALSE. - - After receiving the SSH_MSG_KEXINIT packet from the other side, - each party will know whether their guess was right. If the - other party's guess was wrong, and this field was TRUE, the - next packet MUST be silently ignored, and both sides MUST then - act as determined by the negotiated key exchange method. If - the guess was right, key exchange MUST continue using the - guessed packet. - - After the KEXINIT packet exchange, the key exchange algorithm is run. - It may involve several packet exchanges, as specified by the key - exchange method. - -6.2 Output from Key Exchange - - The key exchange produces two values: a shared secret K, and an - exchange hash H. Encryption and authentication keys are derived from - these. The exchange hash H from the first key exchange is - additionally used as the session identifier, which is a unique - identifier for this connection. It is used by authentication methods - as a part of the data that is signed as a proof of possession of a - private key. Once computed, the session identifier is not changed, - even if keys are later re-exchanged. - - - Each key exchange method specifies a hash function that is used in - the key exchange. The same hash algorithm MUST be used in key - derivation. Here, we'll call it HASH. - - - Encryption keys MUST be computed as HASH of a known value and K as - follows: - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - o Initial IV client to server: HASH(K || H || "A" || session_id) - (Here K is encoded as mpint and "A" as byte and session_id as raw - data."A" means the single character A, ASCII 65). - o Initial IV server to client: HASH(K || H || "B" || session_id) - o Encryption key client to server: HASH(K || H || "C" || session_id) - o Encryption key server to client: HASH(K || H || "D" || session_id) - o Integrity key client to server: HASH(K || H || "E" || session_id) - o Integrity key server to client: HASH(K || H || "F" || session_id) - - Key data MUST be taken from the beginning of the hash output. 128 - bits (16 bytes) MUST be used for algorithms with variable-length - keys. The only variable key length algorithm defined in this document - is arcfour). For other algorithms, as many bytes as are needed are - taken from the beginning of the hash value. If the key length needed - is longer than the output of the HASH, the key is extended by - computing HASH of the concatenation of K and H and the entire key so - far, and appending the resulting bytes (as many as HASH generates) to - the key. This process is repeated until enough key material is - available; the key is taken from the beginning of this value. In - other words: - - K1 = HASH(K || H || X || session_id) (X is e.g. "A") - K2 = HASH(K || H || K1) - K3 = HASH(K || H || K1 || K2) - ... - key = K1 || K2 || K3 || ... - - This process will lose entropy if the amount of entropy in K is - larger than the internal state size of HASH. - -6.3 Taking Keys Into Use - - Key exchange ends by each side sending an SSH_MSG_NEWKEYS message. - This message is sent with the old keys and algorithms. All messages - sent after this message MUST use the new keys and algorithms. - - - When this message is received, the new keys and algorithms MUST be - taken into use for receiving. - - - This message is the only valid message after key exchange, in - addition to SSH_MSG_DEBUG, SSH_MSG_DISCONNECT and SSH_MSG_IGNORE - messages. The purpose of this message is to ensure that a party is - able to respond with a disconnect message that the other party can - understand if something goes wrong with the key exchange. - Implementations MUST NOT accept any other messages after key exchange - before receiving SSH_MSG_NEWKEYS. - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - byte SSH_MSG_NEWKEYS - - -7. Diffie-Hellman Key Exchange - - The Diffie-Hellman key exchange provides a shared secret that can not - be determined by either party alone. The key exchange is combined - with a signature with the host key to provide host authentication. - - - In the following description (C is the client, S is the server; p is - a large safe prime, g is a generator for a subgroup of GF(p), and q - is the order of the subgroup; V_S is S's version string; V_C is C's - version string; K_S is S's public host key; I_C is C's KEXINIT - message and I_S S's KEXINIT message which have been exchanged before - this part begins): - - - 1. C generates a random number x (1 < x < q) and computes e = g^x - mod p. C sends "e" to S. - - 2. S generates a random number y (0 < y < q) and computes f = g^y - mod p. S receives "e". It computes K = e^y mod p, H = hash(V_C - || V_S || I_C || I_S || K_S || e || f || K) (these elements are - encoded according to their types; see below), and signature s on - H with its private host key. S sends "K_S || f || s" to C. The - signing operation may involve a second hashing operation. - - 3. C verifies that K_S really is the host key for S (e.g. using - certificates or a local database). C is also allowed to accept - the key without verification; however, doing so will render the - protocol insecure against active attacks (but may be desirable - for practical reasons in the short term in many environments). C - then computes K = f^x mod p, H = hash(V_C || V_S || I_C || I_S || - K_S || e || f || K), and verifies the signature s on H. - - Either side MUST NOT send or accept e or f values that are not in the - range [1, p-1]. If this condition is violated, the key exchange - fails. - - - This is implemented with the following messages. The hash algorithm - for computing the exchange hash is defined by the method name, and is - called HASH. The public key algorithm for signing is negotiated with - the KEXINIT messages. - - First, the client sends the following: - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - byte SSH_MSG_KEXDH_INIT - mpint e - - - The server responds with the following: - - byte SSH_MSG_KEXDH_REPLY - string server public host key and certificates (K_S) - mpint f - string signature of H - - The hash H is computed as the HASH hash of the concatenation of the - following: - - string V_C, the client's version string (CR and NL excluded) - string V_S, the server's version string (CR and NL excluded) - string I_C, the payload of the client's SSH_MSG_KEXINIT - string I_S, the payload of the server's SSH_MSG_KEXINIT - string K_S, the host key - mpint e, exchange value sent by the client - mpint f, exchange value sent by the server - mpint K, the shared secret - - This value is called the exchange hash, and it is used to - authenticate the key exchange. The exchange hash SHOULD be kept - secret. - - - The signature algorithm MUST be applied over H, not the original - data. Most signature algorithms include hashing and additional - padding. For example, "ssh-dss" specifies SHA-1 hashing; in that - case, the data is first hashed with HASH to compute H, and H is then - hashed with SHA-1 as part of the signing operation. - -7.1 diffie-hellman-group1-sha1 - - The "diffie-hellman-group1-sha1" method specifies Diffie-Hellman key - exchange with SHA-1 as HASH, and Oakley group 14 [RFC3526] (2048-bit - MODP Group). It is included below in hexadecimal and decimal. - - The prime p is equal to 2^1024 - 2^960 - 1 + 2^64 * floor( 2^894 Pi + - 129093 ). Its hexadecimal value is: - - FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 - 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD - EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 - E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED - EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - FFFFFFFF FFFFFFFF. - - In decimal, this value is: - - 179769313486231590770839156793787453197860296048756011706444 - 423684197180216158519368947833795864925541502180565485980503 - 646440548199239100050792877003355816639229553136239076508735 - 759914822574862575007425302077447712589550957937778424442426 - 617334727629299387668709205606050270810842907692932019128194 - 467627007. - - The generator used with this prime is g = 2. The group order q is (p - - 1) / 2. - -8. Key Re-Exchange - - Key re-exchange is started by sending an SSH_MSG_KEXINIT packet when - not already doing a key exchange (as described in Section Section - 6.1). When this message is received, a party MUST respond with its - own SSH_MSG_KEXINIT message except when the received SSH_MSG_KEXINIT - already was a reply. Either party MAY initiate the re-exchange, but - roles MUST NOT be changed (i.e., the server remains the server, and - the client remains the client). - - - Key re-exchange is performed using whatever encryption was in effect - when the exchange was started. Encryption, compression, and MAC - methods are not changed before a new SSH_MSG_NEWKEYS is sent after - the key exchange (as in the initial key exchange). Re-exchange is - processed identically to the initial key exchange, except for the - session identifier that will remain unchanged. It is permissible to - change some or all of the algorithms during the re-exchange. Host - keys can also change. All keys and initialization vectors are - recomputed after the exchange. Compression and encryption contexts - are reset. - - - It is recommended that the keys are changed after each gigabyte of - transmitted data or after each hour of connection time, whichever - comes sooner. However, since the re-exchange is a public key - operation, it requires a fair amount of processing power and should - not be performed too often. - - - More application data may be sent after the SSH_MSG_NEWKEYS packet - has been sent; key exchange does not affect the protocols that lie - above the SSH transport layer. - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - -9. Service Request - - After the key exchange, the client requests a service. The service is - identified by a name. The format of names and procedures for defining - new names are defined in [SSH-ARCH]. - - - Currently, the following names have been reserved: - - ssh-userauth - ssh-connection - - Similar local naming policy is applied to the service names, as is - applied to the algorithm names; a local service should use the - "servicename@domain" syntax. - - byte SSH_MSG_SERVICE_REQUEST - string service name - - If the server rejects the service request, it SHOULD send an - appropriate SSH_MSG_DISCONNECT message and MUST disconnect. - - - When the service starts, it may have access to the session identifier - generated during the key exchange. - - - If the server supports the service (and permits the client to use - it), it MUST respond with the following: - - byte SSH_MSG_SERVICE_ACCEPT - string service name - - Message numbers used by services should be in the area reserved for - them (see Section 6 in [SSH-ARCH]). The transport level will - continue to process its own messages. - - - Note that after a key exchange with implicit server authentication, - the client MUST wait for response to its service request message - before sending any further data. - -10. Additional Messages - - Either party may send any of the following messages at any time. - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - -10.1 Disconnection Message - - byte SSH_MSG_DISCONNECT - uint32 reason code - string description [RFC2279] - string language tag [RFC3066] - - This message causes immediate termination of the connection. All - implementations MUST be able to process this message; they SHOULD be - able to send this message. - - The sender MUST NOT send or receive any data after this message, and - the recipient MUST NOT accept any data after receiving this message. - The description field gives a more specific explanation in a - human-readable form. The error code gives the reason in a more - machine-readable format (suitable for localization), and can have the - following values: - - #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 - #define SSH_DISCONNECT_PROTOCOL_ERROR 2 - #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3 - #define SSH_DISCONNECT_RESERVED 4 - #define SSH_DISCONNECT_MAC_ERROR 5 - #define SSH_DISCONNECT_COMPRESSION_ERROR 6 - #define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7 - #define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 - #define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 - #define SSH_DISCONNECT_CONNECTION_LOST 10 - #define SSH_DISCONNECT_BY_APPLICATION 11 - #define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12 - #define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13 - #define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 - #define SSH_DISCONNECT_ILLEGAL_USER_NAME 15 - - If the description string is displayed, control character filtering - discussed in [SSH-ARCH] should be used to avoid attacks by sending - terminal control characters. - -10.2 Ignored Data Message - - byte SSH_MSG_IGNORE - string data - - All implementations MUST understand (and ignore) this message at any - time (after receiving the protocol version). No implementation is - required to send them. This message can be used as an additional - protection measure against advanced traffic analysis techniques. - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - -10.3 Debug Message - - byte SSH_MSG_DEBUG - boolean always_display - string message [RFC2279] - string language tag [RFC3066] - - All implementations MUST understand this message, but they are - allowed to ignore it. This message is used to pass the other side - information that may help debugging. If always_display is TRUE, the - message SHOULD be displayed. Otherwise, it SHOULD NOT be displayed - unless debugging information has been explicitly requested by the - user. - - - The message doesn't need to contain a newline. It is, however, - allowed to consist of multiple lines separated by CRLF (Carriage - Return - Line Feed) pairs. - - - If the message string is displayed, terminal control character - filtering discussed in [SSH-ARCH] should be used to avoid attacks by - sending terminal control characters. - -10.4 Reserved Messages - - An implementation MUST respond to all unrecognized messages with an - SSH_MSG_UNIMPLEMENTED message in the order in which the messages were - received. Such messages MUST be otherwise ignored. Later protocol - versions may define other meanings for these message types. - - byte SSH_MSG_UNIMPLEMENTED - uint32 packet sequence number of rejected message - - -11. Summary of Message Numbers - - The following message numbers have been defined in this protocol: - - #define SSH_MSG_DISCONNECT 1 - #define SSH_MSG_IGNORE 2 - #define SSH_MSG_UNIMPLEMENTED 3 - #define SSH_MSG_DEBUG 4 - #define SSH_MSG_SERVICE_REQUEST 5 - #define SSH_MSG_SERVICE_ACCEPT 6 - - #define SSH_MSG_KEXINIT 20 - #define SSH_MSG_NEWKEYS 21 - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 23] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - /* Numbers 30-49 used for kex packets. - Different kex methods may reuse message numbers in - this range. */ - - #define SSH_MSG_KEXDH_INIT 30 - #define SSH_MSG_KEXDH_REPLY 31 - - -12. IANA Considerations - - This document is part of a set, the IANA considerations for the SSH - protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH], - [SSH-CONNECT] are detailed in [SSH-NUMBERS]. - -13. Security Considerations - - This protocol provides a secure encrypted channel over an insecure - network. It performs server host authentication, key exchange, - encryption, and integrity protection. It also derives a unique - session id that may be used by higher-level protocols. - - Full security considerations for this protocol are provided in - Section 8 of [SSH-ARCH] - -14. Intellectual Property - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementers or users of this specification can - be obtained from the IETF Secretariat. - - The IETF has been notified of intellectual property rights claimed in - regard to some or all of the specification contained in this - document. For more information consult the online list of claimed - rights. - -15. Additional Information - - The current document editor is: Darren.Moffat@Sun.COM. Comments on - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 24] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - this internet draft should be sent to the IETF SECSH working group, - details at: http://ietf.org/html.charters/secsh-charter.html - -Normative - - [SSH-ARCH] - Ylonen, T., "SSH Protocol Architecture", I-D - draft-ietf-architecture-15.txt, Oct 2003. - - [SSH-TRANS] - Ylonen, T., "SSH Transport Layer Protocol", I-D - draft-ietf-transport-17.txt, Oct 2003. - - [SSH-USERAUTH] - Ylonen, T., "SSH Authentication Protocol", I-D - draft-ietf-userauth-18.txt, Oct 2003. - - [SSH-CONNECT] - Ylonen, T., "SSH Connection Protocol", I-D - draft-ietf-connect-18.txt, Oct 2003. - - [SSH-NUMBERS] - Lehtinen, S. and D. Moffat, "SSH Protocol Assigned - Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct - 2003. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - -Informative - - [FIPS-186] - Federal Information Processing Standards Publication, - "FIPS PUB 186, Digital Signature Standard", May 1994. - - [FIPS-197] - NIST, "FIPS PUB 197 Advanced Encryption Standard (AES)", - November 2001. - - [FIPS-46-3] - U.S. Dept. of Commerce, "FIPS PUB 46-3, Data Encryption - Standard (DES)", October 1999. - - [RFC2459] Housley, R., Ford, W., Polk, T. and D. Solo, "Internet - X.509 Public Key Infrastructure Certificate and CRL - Profile", RFC 2459, January 1999. - - [RFC1034] Mockapetris, P., "Domain names - concepts and facilities", - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 25] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - STD 13, RFC 1034, November 1987. - - [RFC3066] Alvestrand, H., "Tags for the Identification of - Languages", BCP 47, RFC 3066, January 2001. - - [RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data Format - Specification version 3.3", RFC 1950, May 1996. - - [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification - version 1.3", RFC 1951, May 1996. - - [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - - [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: - Keyed-Hashing for Message Authentication", RFC 2104, - February 1997. - - [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144, - May 1997. - - [RFC2440] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer, - "OpenPGP Message Format", RFC 2440, November 1998. - - [RFC2693] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas, - B. and T. Ylonen, "SPKI Certificate Theory", RFC 2693, - September 1999. - - [RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential (MODP) - Diffie-Hellman groups for Internet Key Exchange (IKE)", - RFC 3526, May 2003. - - [SCHNEIER] - Schneier, B., "Applied Cryptography Second Edition: - protocols algorithms and source in code in C", 1996. - - [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A - 128-Bit Block Cipher, 1st Edition", March 1999. - - - - - - - - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 26] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - -Authors' Addresses - - Tatu Ylonen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: ylo@ssh.com - - - Darren J. Moffat (editor) - Sun Microsystems, Inc - 17 Network Circle - Menlo Park 95025 - USA - - EMail: Darren.Moffat@Sun.COM - -Appendix A. Contibutors - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 27] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - -Intellectual Property Statement - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementors or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - The IETF has been notified of intellectual property rights claimed in - regard to some or all of the specification contained in this - document. For more information consult the online list of claimed - rights. - - -Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assignees. - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 28] - -Internet-Draft SSH Transport Layer Protocol Oct 2003 - - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - -Acknowledgment - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat, Editor Expires March 31, 2004 [Page 29] \ No newline at end of file diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps deleted file mode 100644 index be5799dbce..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps +++ /dev/null @@ -1,1881 +0,0 @@ -%!PS-Adobe-3.0 -%%BoundingBox: 75 0 595 747 -%%Title: Enscript Output -%%For: Magnus Thoang -%%Creator: GNU enscript 1.6.1 -%%CreationDate: Fri Oct 31 13:35:32 2003 -%%Orientation: Portrait -%%Pages: 8 0 -%%DocumentMedia: A4 595 842 0 () () -%%DocumentNeededResources: (atend) -%%EndComments -%%BeginProlog -%%BeginProcSet: PStoPS 1 15 -userdict begin -[/showpage/erasepage/copypage]{dup where{pop dup load - type/operatortype eq{1 array cvx dup 0 3 index cvx put - bind def}{pop}ifelse}{pop}ifelse}forall -[/letter/legal/executivepage/a4/a4small/b5/com10envelope - /monarchenvelope/c5envelope/dlenvelope/lettersmall/note - /folio/quarto/a5]{dup where{dup wcheck{exch{}put} - {pop{}def}ifelse}{pop}ifelse}forall -/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put} - {pop def}ifelse}{def}ifelse -/PStoPSmatrix matrix currentmatrix def -/PStoPSxform matrix def/PStoPSclip{clippath}def -/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def -/initmatrix{matrix defaultmatrix setmatrix}bind def -/initclip[{matrix currentmatrix PStoPSmatrix setmatrix - [{currentpoint}stopped{$error/newerror false put{newpath}} - {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse] - {[/newpath cvx{/moveto cvx}{/lineto cvx} - {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop} - stopped{$error/errorname get/invalidaccess eq{cleartomark - $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop - /initclip dup load dup type dup/operatortype eq{pop exch pop} - {dup/arraytype eq exch/packedarraytype eq or - {dup xcheck{exch pop aload pop}{pop cvx}ifelse} - {pop cvx}ifelse}ifelse - {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def -/initgraphics{initmatrix newpath initclip 1 setlinewidth - 0 setlinecap 0 setlinejoin []0 setdash 0 setgray - 10 setmiterlimit}bind def -end -%%EndProcSet -%%BeginResource: procset Enscript-Prolog 1.6 1 -% -% Procedures. -% - -/_S { % save current state - /_s save def -} def -/_R { % restore from saved state - _s restore -} def - -/S { % showpage protecting gstate - gsave - showpage - grestore -} bind def - -/MF { % fontname newfontname -> - make a new encoded font - /newfontname exch def - /fontname exch def - - /fontdict fontname findfont def - /newfont fontdict maxlength dict def - - fontdict { - exch - dup /FID eq { - % skip FID pair - pop pop - } { - % copy to the new font dictionary - exch newfont 3 1 roll put - } ifelse - } forall - - newfont /FontName newfontname put - - % insert only valid encoding vectors - encoding_vector length 256 eq { - newfont /Encoding encoding_vector put - } if - - newfontname newfont definefont pop -} def - -/SF { % fontname width height -> - set a new font - /height exch def - /width exch def - - findfont - [width 0 0 height 0 0] makefont setfont -} def - -/SUF { % fontname width height -> - set a new user font - /height exch def - /width exch def - - /F-gs-user-font MF - /F-gs-user-font width height SF -} def - -/M {moveto} bind def -/s {show} bind def - -/Box { % x y w h -> - define box path - /d_h exch def /d_w exch def /d_y exch def /d_x exch def - d_x d_y moveto - d_w 0 rlineto - 0 d_h rlineto - d_w neg 0 rlineto - closepath -} def - -/bgs { % x y height blskip gray str -> - show string with bg color - /str exch def - /gray exch def - /blskip exch def - /height exch def - /y exch def - /x exch def - - gsave - x y blskip sub str stringwidth pop height Box - gray setgray - fill - grestore - x y M str s -} def - -% Highlight bars. -/highlight_bars { % nlines lineheight output_y_margin gray -> - - gsave - setgray - /ymarg exch def - /lineheight exch def - /nlines exch def - - % This 2 is just a magic number to sync highlight lines to text. - 0 d_header_y ymarg sub 2 sub translate - - /cw d_output_w cols div def - /nrows d_output_h ymarg 2 mul sub lineheight div cvi def - - % for each column - 0 1 cols 1 sub { - cw mul /xp exch def - - % for each rows - 0 1 nrows 1 sub { - /rn exch def - rn lineheight mul neg /yp exch def - rn nlines idiv 2 mod 0 eq { - % Draw highlight bar. 4 is just a magic indentation. - xp 4 add yp cw 8 sub lineheight neg Box fill - } if - } for - } for - - grestore -} def - -% Line highlight bar. -/line_highlight { % x y width height gray -> - - gsave - /gray exch def - Box gray setgray fill - grestore -} def - -% Column separator lines. -/column_lines { - gsave - .1 setlinewidth - 0 d_footer_h translate - /cw d_output_w cols div def - 1 1 cols 1 sub { - cw mul 0 moveto - 0 d_output_h rlineto stroke - } for - grestore -} def - -% Column borders. -/column_borders { - gsave - .1 setlinewidth - 0 d_footer_h moveto - 0 d_output_h rlineto - d_output_w 0 rlineto - 0 d_output_h neg rlineto - closepath stroke - grestore -} def - -% Do the actual underlay drawing -/draw_underlay { - ul_style 0 eq { - ul_str true charpath stroke - } { - ul_str show - } ifelse -} def - -% Underlay -/underlay { % - -> - - gsave - 0 d_page_h translate - d_page_h neg d_page_w atan rotate - - ul_gray setgray - ul_font setfont - /dw d_page_h dup mul d_page_w dup mul add sqrt def - ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto - draw_underlay - grestore -} def - -/user_underlay { % - -> - - gsave - ul_x ul_y translate - ul_angle rotate - ul_gray setgray - ul_font setfont - 0 0 ul_h_ptsize 2 div sub moveto - draw_underlay - grestore -} def - -% Page prefeed -/page_prefeed { % bool -> - - statusdict /prefeed known { - statusdict exch /prefeed exch put - } { - pop - } ifelse -} def - -% Wrapped line markers -/wrapped_line_mark { % x y charwith charheight type -> - - /type exch def - /h exch def - /w exch def - /y exch def - /x exch def - - type 2 eq { - % Black boxes (like TeX does) - gsave - 0 setlinewidth - x w 4 div add y M - 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto - closepath fill - grestore - } { - type 3 eq { - % Small arrows - gsave - .2 setlinewidth - x w 2 div add y h 2 div add M - w 4 div 0 rlineto - x w 4 div add y lineto stroke - - x w 4 div add w 8 div add y h 4 div add M - x w 4 div add y lineto - w 4 div h 8 div rlineto stroke - grestore - } { - % do nothing - } ifelse - } ifelse -} def - -% EPSF import. - -/BeginEPSF { - /b4_Inc_state save def % Save state for cleanup - /dict_count countdictstack def % Count objects on dict stack - /op_count count 1 sub def % Count objects on operand stack - userdict begin - /showpage { } def - 0 setgray 0 setlinecap - 1 setlinewidth 0 setlinejoin - 10 setmiterlimit [ ] 0 setdash newpath - /languagelevel where { - pop languagelevel - 1 ne { - false setstrokeadjust false setoverprint - } if - } if -} bind def - -/EndEPSF { - count op_count sub { pos } repeat % Clean up stacks - countdictstack dict_count sub { end } repeat - b4_Inc_state restore -} bind def - -% Check PostScript language level. -/languagelevel where { - pop /gs_languagelevel languagelevel def -} { - /gs_languagelevel 1 def -} ifelse -%%EndResource -%%BeginResource: procset Enscript-Encoding-88591 1.6 1 -/encoding_vector [ -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclam /quotedbl /numbersign -/dollar /percent /ampersand /quoteright -/parenleft /parenright /asterisk /plus -/comma /hyphen /period /slash -/zero /one /two /three -/four /five /six /seven -/eight /nine /colon /semicolon -/less /equal /greater /question -/at /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 /bracketleft -/backslash /bracketright /asciicircum /underscore -/quoteleft /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 /braceleft -/bar /braceright /tilde /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/.notdef /.notdef /.notdef /.notdef -/space /exclamdown /cent /sterling -/currency /yen /brokenbar /section -/dieresis /copyright /ordfeminine /guillemotleft -/logicalnot /hyphen /registered /macron -/degree /plusminus /twosuperior /threesuperior -/acute /mu /paragraph /bullet -/cedilla /onesuperior /ordmasculine /guillemotright -/onequarter /onehalf /threequarters /questiondown -/Agrave /Aacute /Acircumflex /Atilde -/Adieresis /Aring /AE /Ccedilla -/Egrave /Eacute /Ecircumflex /Edieresis -/Igrave /Iacute /Icircumflex /Idieresis -/Eth /Ntilde /Ograve /Oacute -/Ocircumflex /Otilde /Odieresis /multiply -/Oslash /Ugrave /Uacute /Ucircumflex -/Udieresis /Yacute /Thorn /germandbls -/agrave /aacute /acircumflex /atilde -/adieresis /aring /ae /ccedilla -/egrave /eacute /ecircumflex /edieresis -/igrave /iacute /icircumflex /idieresis -/eth /ntilde /ograve /oacute -/ocircumflex /otilde /odieresis /divide -/oslash /ugrave /uacute /ucircumflex -/udieresis /yacute /thorn /ydieresis -] def -%%EndResource -%%EndProlog -%%BeginSetup -%%IncludeResource: font Courier-Bold -%%IncludeResource: font Courier -/HFpt_w 10 def -/HFpt_h 10 def -/Courier-Bold /HF-gs-font MF -/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def -/Courier /F-gs-font MF -/F-gs-font 10 10 SF -/#copies 1 def -/d_page_w 520 def -/d_page_h 747 def -/d_header_x 0 def -/d_header_y 747 def -/d_header_w 520 def -/d_header_h 0 def -/d_footer_x 0 def -/d_footer_y 0 def -/d_footer_w 520 def -/d_footer_h 0 def -/d_output_w 520 def -/d_output_h 747 def -/cols 1 def -userdict/PStoPSxform PStoPSmatrix matrix currentmatrix - matrix invertmatrix matrix concatmatrix - matrix invertmatrix put -%%EndSetup -%%Page: (0,1) 1 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 1 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 701 M -(Network Working Group T. Ylonen) s -5 690 M -(Internet-Draft SSH Communications Security Corp) s -5 679 M -(Expires: March 2, 2003 D. Moffat, Ed.) s -5 668 M -( Sun Microsystems, Inc) s -5 657 M -( September 2002) s -5 624 M -( SSH Authentication Protocol) s -5 613 M -( draft-ietf-secsh-userauth-18.txt) s -5 591 M -(Status of this Memo) s -5 569 M -( This document is an Internet-Draft and is in full conformance with) s -5 558 M -( all provisions of Section 10 of RFC2026.) s -5 536 M -( Internet-Drafts are working documents of the Internet Engineering) s -5 525 M -( Task Force \(IETF\), its areas, and its working groups. Note that other) s -5 514 M -( groups may also distribute working documents as Internet-Drafts.) s -5 492 M -( Internet-Drafts are draft documents valid for a maximum of six months) s -5 481 M -( and may be updated, replaced, or obsoleted by other documents at any) s -5 470 M -( time. It is inappropriate to use Internet-Drafts as reference) s -5 459 M -( material or to cite them other than as "work in progress.") s -5 437 M -( The list of current Internet-Drafts can be accessed at http://) s -5 426 M -( www.ietf.org/ietf/1id-abstracts.txt.) s -5 404 M -( The list of Internet-Draft Shadow Directories can be accessed at) s -5 393 M -( http://www.ietf.org/shadow.html.) s -5 371 M -( This Internet-Draft will expire on March 2, 2003.) s -5 349 M -(Copyright Notice) s -5 327 M -( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s -5 305 M -(Abstract) s -5 283 M -( SSH is a protocol for secure remote login and other secure network) s -5 272 M -( services over an insecure network. This document describes the SSH) s -5 261 M -( authentication protocol framework and public key, password, and) s -5 250 M -( host-based client authentication methods. Additional authentication) s -5 239 M -( methods are described in separate documents. The SSH authentication) s -5 228 M -( protocol runs on top of the SSH transport layer protocol and provides) s -5 217 M -( a single authenticated tunnel for the SSH connection protocol.) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 1]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 2 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -(Table of Contents) s -5 668 M -( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 657 M -( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s -5 646 M -( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s -5 635 M -( 3.1 The Authentication Protocol Framework . . . . . . . . . . . 3) s -5 624 M -( 3.1.1 Authentication Requests . . . . . . . . . . . . . . . . . . 4) s -5 613 M -( 3.1.2 Responses to Authentication Requests . . . . . . . . . . . . 5) s -5 602 M -( 3.1.3 The "none" Authentication Request . . . . . . . . . . . . . 6) s -5 591 M -( 3.1.4 Completion of User Authentication . . . . . . . . . . . . . 6) s -5 580 M -( 3.1.5 Banner Message . . . . . . . . . . . . . . . . . . . . . . . 7) s -5 569 M -( 3.2 Authentication Protocol Message Numbers . . . . . . . . . . 7) s -5 558 M -( 3.3 Public Key Authentication Method: publickey . . . . . . . . 8) s -5 547 M -( 3.4 Password Authentication Method: password . . . . . . . . . . 10) s -5 536 M -( 3.5 Host-Based Authentication: hostbased . . . . . . . . . . . . 11) s -5 525 M -( 4. Security Considerations . . . . . . . . . . . . . . . . . . 12) s -5 514 M -( Normative . . . . . . . . . . . . . . . . . . . . . . . . . 13) s -5 503 M -( Informative . . . . . . . . . . . . . . . . . . . . . . . . 13) s -5 492 M -( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 14) s -5 481 M -( Intellectual Property and Copyright Statements . . . . . . . 15) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 2]) s -_R -S -PStoPSsaved restore -%%Page: (2,3) 2 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 3 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -(1. Contributors) s -5 668 M -( The major original contributors of this document were: Tatu Ylonen,) s -5 657 M -( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s -5 646 M -( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s -5 635 M -( Jyvaskyla\)) s -5 613 M -( The document editor is: Darren.Moffat@Sun.COM. Comments on this) s -5 602 M -( internet draft should be sent to the IETF SECSH working group,) s -5 591 M -( details at: http://ietf.org/html.charters/secsh-charter.html) s -5 569 M -(2. Introduction) s -5 547 M -( The SSH authentication protocol is a general-purpose user) s -5 536 M -( authentication protocol. It is intended to be run over the SSH) s -5 525 M -( transport layer protocol [SSH-TRANS]. This protocol assumes that the) s -5 514 M -( underlying protocols provide integrity and confidentiality) s -5 503 M -( protection.) s -5 481 M -( This document should be read only after reading the SSH architecture) s -5 470 M -( document [SSH-ARCH]. This document freely uses terminology and) s -5 459 M -( notation from the architecture document without reference or further) s -5 448 M -( explanation.) s -5 426 M -( The service name for this protocol is "ssh-userauth".) s -5 404 M -( When this protocol starts, it receives the session identifier from) s -5 393 M -( the lower-level protocol \(this is the exchange hash H from the first) s -5 382 M -( key exchange\). The session identifier uniquely identifies this) s -5 371 M -( session and is suitable for signing in order to prove ownership of a) s -5 360 M -( private key. This protocol also needs to know whether the lower-level) s -5 349 M -( protocol provides confidentiality protection.) s -5 327 M -(3. Conventions Used in This Document) s -5 305 M -( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s -5 294 M -( and "MAY" that appear in this document are to be interpreted as) s -5 283 M -( described in [RFC2119]) s -5 261 M -( The used data types and terminology are specified in the architecture) s -5 250 M -( document [SSH-ARCH]) s -5 228 M -( The architecture document also discusses the algorithm naming) s -5 217 M -( conventions that MUST be used with the SSH protocols.) s -5 195 M -(3.1 The Authentication Protocol Framework) s -5 173 M -( The server drives the authentication by telling the client which) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 3]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 4 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( authentication methods can be used to continue the exchange at any) s -5 679 M -( given time. The client has the freedom to try the methods listed by) s -5 668 M -( the server in any order. This gives the server complete control over) s -5 657 M -( the authentication process if desired, but also gives enough) s -5 646 M -( flexibility for the client to use the methods it supports or that are) s -5 635 M -( most convenient for the user, when multiple methods are offered by) s -5 624 M -( the server.) s -5 602 M -( Authentication methods are identified by their name, as defined in) s -5 591 M -( [SSH-ARCH]. The "none" method is reserved, and MUST NOT be listed as) s -5 580 M -( supported. However, it MAY be sent by the client. The server MUST) s -5 569 M -( always reject this request, unless the client is to be allowed in) s -5 558 M -( without any authentication, in which case the server MUST accept this) s -5 547 M -( request. The main purpose of sending this request is to get the list) s -5 536 M -( of supported methods from the server.) s -5 514 M -( The server SHOULD have a timeout for authentication, and disconnect) s -5 503 M -( if the authentication has not been accepted within the timeout) s -5 492 M -( period. The RECOMMENDED timeout period is 10 minutes. Additionally,) s -5 481 M -( the implementation SHOULD limit the number of failed authentication) s -5 470 M -( attempts a client may perform in a single session \(the RECOMMENDED) s -5 459 M -( limit is 20 attempts\). If the threshold is exceeded, the server) s -5 448 M -( SHOULD disconnect.) s -5 426 M -(3.1.1 Authentication Requests) s -5 404 M -( All authentication requests MUST use the following message format.) s -5 393 M -( Only the first few fields are defined; the remaining fields depend on) s -5 382 M -( the authentication method.) s -5 360 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 349 M -( string user name \(in ISO-10646 UTF-8 encoding [RFC2279]\)) s -5 338 M -( string service name \(in US-ASCII\)) s -5 327 M -( string method name \(US-ASCII\)) s -5 316 M -( The rest of the packet is method-specific.) s -5 294 M -( The user name and service are repeated in every new authentication) s -5 283 M -( attempt, and MAY change. The server implementation MUST carefully) s -5 272 M -( check them in every message, and MUST flush any accumulated) s -5 261 M -( authentication states if they change. If it is unable to flush some) s -5 250 M -( authentication state, it MUST disconnect if the user or service name) s -5 239 M -( changes.) s -5 217 M -( The service name specifies the service to start after authentication.) s -5 206 M -( There may be several different authenticated services provided. If) s -5 195 M -( the requested service is not available, the server MAY disconnect) s -5 184 M -( immediately or at any later time. Sending a proper disconnect) s -5 173 M -( message is RECOMMENDED. In any case, if the service does not exist,) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 4]) s -_R -S -PStoPSsaved restore -%%Page: (4,5) 3 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 5 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( authentication MUST NOT be accepted.) s -5 668 M -( If the requested user does not exist, the server MAY disconnect, or) s -5 657 M -( MAY send a bogus list of acceptable authentication methods, but never) s -5 646 M -( accept any. This makes it possible for the server to avoid) s -5 635 M -( disclosing information on which accounts exist. In any case, if the) s -5 624 M -( user does not exist, the authentication request MUST NOT be accepted.) s -5 602 M -( While there is usually little point for clients to send requests that) s -5 591 M -( the server does not list as acceptable, sending such requests is not) s -5 580 M -( an error, and the server SHOULD simply reject requests that it does) s -5 569 M -( not recognize.) s -5 547 M -( An authentication request MAY result in a further exchange of) s -5 536 M -( messages. All such messages depend on the authentication method) s -5 525 M -( used, and the client MAY at any time continue with a new) s -5 514 M -( SSH_MSG_USERAUTH_REQUEST message, in which case the server MUST) s -5 503 M -( abandon the previous authentication attempt and continue with the new) s -5 492 M -( one.) s -5 470 M -(3.1.2 Responses to Authentication Requests) s -5 448 M -( If the server rejects the authentication request, it MUST respond) s -5 437 M -( with the following:) s -5 415 M -( byte SSH_MSG_USERAUTH_FAILURE) s -5 404 M -( string authentications that can continue) s -5 393 M -( boolean partial success) s -5 371 M -( "Authentications that can continue" is a comma-separated list of) s -5 360 M -( authentication method names that may productively continue the) s -5 349 M -( authentication dialog.) s -5 327 M -( It is RECOMMENDED that servers only include those methods in the list) s -5 316 M -( that are actually useful. However, it is not illegal to include) s -5 305 M -( methods that cannot be used to authenticate the user.) s -5 283 M -( Already successfully completed authentications SHOULD NOT be included) s -5 272 M -( in the list, unless they really should be performed again for some) s -5 261 M -( reason.) s -5 239 M -( "Partial success" MUST be TRUE if the authentication request to which) s -5 228 M -( this is a response was successful. It MUST be FALSE if the request) s -5 217 M -( was not successfully processed.) s -5 195 M -( When the server accepts authentication, it MUST respond with the) s -5 184 M -( following:) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 5]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 6 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( byte SSH_MSG_USERAUTH_SUCCESS) s -5 668 M -( Note that this is not sent after each step in a multi-method) s -5 657 M -( authentication sequence, but only when the authentication is) s -5 646 M -( complete.) s -5 624 M -( The client MAY send several authentication requests without waiting) s -5 613 M -( for responses from previous requests. The server MUST process each) s -5 602 M -( request completely and acknowledge any failed requests with a) s -5 591 M -( SSH_MSG_USERAUTH_FAILURE message before processing the next request.) s -5 569 M -( A request that results in further exchange of messages will be) s -5 558 M -( aborted by a second request. It is not possible to send a second) s -5 547 M -( request without waiting for a response from the server, if the first) s -5 536 M -( request will result in further exchange of messages. No) s -5 525 M -( SSH_MSG_USERAUTH_FAILURE message will be sent for the aborted method.) s -5 503 M -( SSH_MSG_USERAUTH_SUCCESS MUST be sent only once. When) s -5 492 M -( SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication) s -5 481 M -( requests received after that SHOULD be silently ignored.) s -5 459 M -( Any non-authentication messages sent by the client after the request) s -5 448 M -( that resulted in SSH_MSG_USERAUTH_SUCCESS being sent MUST be passed) s -5 437 M -( to the service being run on top of this protocol. Such messages can) s -5 426 M -( be identified by their message numbers \(see Section Message Numbers) s -5 415 M -( \(Section 3.2\)\).) s -5 393 M -(3.1.3 The "none" Authentication Request) s -5 371 M -( A client may request a list of authentication methods that may) s -5 360 M -( continue by using the "none" authentication method.) s -5 338 M -( If no authentication at all is needed for the user, the server MUST) s -5 327 M -( return SSH_MSG_USERAUTH_SUCCESS. Otherwise, the server MUST return) s -5 316 M -( SSH_MSG_USERAUTH_FAILURE and MAY return with it a list of) s -5 305 M -( authentication methods that can continue.) s -5 283 M -( This method MUST NOT be listed as supported by the server.) s -5 261 M -(3.1.4 Completion of User Authentication) s -5 239 M -( Authentication is complete when the server has responded with) s -5 228 M -( SSH_MSG_USERAUTH_SUCCESS; all authentication related messages) s -5 217 M -( received after sending this message SHOULD be silently ignored.) s -5 195 M -( After sending SSH_MSG_USERAUTH_SUCCESS, the server starts the) s -5 184 M -( requested service.) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 6]) s -_R -S -PStoPSsaved restore -%%Page: (6,7) 4 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 7 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -(3.1.5 Banner Message) s -5 668 M -( In some jurisdictions, sending a warning message before) s -5 657 M -( authentication may be relevant for getting legal protection. Many) s -5 646 M -( UNIX machines, for example, normally display text from `/etc/issue',) s -5 635 M -( or use "tcp wrappers" or similar software to display a banner before) s -5 624 M -( issuing a login prompt.) s -5 602 M -( The SSH server may send a SSH_MSG_USERAUTH_BANNER message at any time) s -5 591 M -( before authentication is successful. This message contains text to) s -5 580 M -( be displayed to the client user before authentication is attempted.) s -5 569 M -( The format is as follows:) s -5 547 M -( byte SSH_MSG_USERAUTH_BANNER) s -5 536 M -( string message \(ISO-10646 UTF-8\)) s -5 525 M -( string language tag \(as defined in [RFC3066]\)) s -5 503 M -( The client SHOULD by default display the message on the screen.) s -5 492 M -( However, since the message is likely to be sent for every login) s -5 481 M -( attempt, and since some client software will need to open a separate) s -5 470 M -( window for this warning, the client software may allow the user to) s -5 459 M -( explicitly disable the display of banners from the server. The) s -5 448 M -( message may consist of multiple lines.) s -5 426 M -( If the message string is displayed, control character filtering) s -5 415 M -( discussed in [SSH-ARCH] SHOULD be used to avoid attacks by sending) s -5 404 M -( terminal control characters.) s -5 382 M -(3.2 Authentication Protocol Message Numbers) s -5 360 M -( All message numbers used by this authentication protocol are in the) s -5 349 M -( range from 50 to 79, which is part of the range reserved for) s -5 338 M -( protocols running on top of the SSH transport layer protocol.) s -5 316 M -( Message numbers of 80 and higher are reserved for protocols running) s -5 305 M -( after this authentication protocol, so receiving one of them before) s -5 294 M -( authentication is complete is an error, to which the server MUST) s -5 283 M -( respond by disconnecting \(preferably with a proper disconnect message) s -5 272 M -( sent first to ease troubleshooting\).) s -5 250 M -( After successful authentication, such messages are passed to the) s -5 239 M -( higher-level service.) s -5 217 M -( These are the general authentication message codes:) s -5 195 M -( #define SSH_MSG_USERAUTH_REQUEST 50) s -5 184 M -( #define SSH_MSG_USERAUTH_FAILURE 51) s -5 173 M -( #define SSH_MSG_USERAUTH_SUCCESS 52) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 7]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 8 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( #define SSH_MSG_USERAUTH_BANNER 53) s -5 668 M -( In addition to the above, there is a range of message numbers) s -5 657 M -( \(60..79\) reserved for method-specific messages. These messages are) s -5 646 M -( only sent by the server \(client sends only SSH_MSG_USERAUTH_REQUEST) s -5 635 M -( messages\). Different authentication methods reuse the same message) s -5 624 M -( numbers.) s -5 602 M -(3.3 Public Key Authentication Method: publickey) s -5 580 M -( The only REQUIRED authentication method is public key authentication.) s -5 569 M -( All implementations MUST support this method; however, not all users) s -5 558 M -( need to have public keys, and most local policies are not likely to) s -5 547 M -( require public key authentication for all users in the near future.) s -5 525 M -( With this method, the possession of a private key serves as) s -5 514 M -( authentication. This method works by sending a signature created) s -5 503 M -( with a private key of the user. The server MUST check that the key) s -5 492 M -( is a valid authenticator for the user, and MUST check that the) s -5 481 M -( signature is valid. If both hold, the authentication request MUST be) s -5 470 M -( accepted; otherwise it MUST be rejected. \(Note that the server MAY) s -5 459 M -( require additional authentications after successful authentication.\)) s -5 437 M -( Private keys are often stored in an encrypted form at the client) s -5 426 M -( host, and the user must supply a passphrase before the signature can) s -5 415 M -( be generated. Even if they are not, the signing operation involves) s -5 404 M -( some expensive computation. To avoid unnecessary processing and user) s -5 393 M -( interaction, the following message is provided for querying whether) s -5 382 M -( authentication using the key would be acceptable.) s -5 360 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 349 M -( string user name) s -5 338 M -( string service) s -5 327 M -( string "publickey") s -5 316 M -( boolean FALSE) s -5 305 M -( string public key algorithm name) s -5 294 M -( string public key blob) s -5 272 M -( Public key algorithms are defined in the transport layer) s -5 261 M -( specification [SSH-TRANS]. The public key blob may contain) s -5 250 M -( certificates.) s -5 228 M -( Any public key algorithm may be offered for use in authentication.) s -5 217 M -( In particular, the list is not constrained by what was negotiated) s -5 206 M -( during key exchange. If the server does not support some algorithm,) s -5 195 M -( it MUST simply reject the request.) s -5 173 M -( The server MUST respond to this message with either) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 8]) s -_R -S -PStoPSsaved restore -%%Page: (8,9) 5 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 9 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( SSH_MSG_USERAUTH_FAILURE or with the following:) s -5 668 M -( byte SSH_MSG_USERAUTH_PK_OK) s -5 657 M -( string public key algorithm name from the request) s -5 646 M -( string public key blob from the request) s -5 624 M -( To perform actual authentication, the client MAY then send a) s -5 613 M -( signature generated using the private key. The client MAY send the) s -5 602 M -( signature directly without first verifying whether the key is) s -5 591 M -( acceptable. The signature is sent using the following packet:) s -5 569 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 558 M -( string user name) s -5 547 M -( string service) s -5 536 M -( string "publickey") s -5 525 M -( boolean TRUE) s -5 514 M -( string public key algorithm name) s -5 503 M -( string public key to be used for authentication) s -5 492 M -( string signature) s -5 470 M -( Signature is a signature by the corresponding private key over the) s -5 459 M -( following data, in the following order:) s -5 437 M -( string session identifier) s -5 426 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 415 M -( string user name) s -5 404 M -( string service) s -5 393 M -( string "publickey") s -5 382 M -( boolean TRUE) s -5 371 M -( string public key algorithm name) s -5 360 M -( string public key to be used for authentication) s -5 338 M -( When the server receives this message, it MUST check whether the) s -5 327 M -( supplied key is acceptable for authentication, and if so, it MUST) s -5 316 M -( check whether the signature is correct.) s -5 294 M -( If both checks succeed, this method is successful. Note that the) s -5 283 M -( server may require additional authentications. The server MUST) s -5 272 M -( respond with SSH_MSG_USERAUTH_SUCCESS \(if no more authentications are) s -5 261 M -( needed\), or SSH_MSG_USERAUTH_FAILURE \(if the request failed, or more) s -5 250 M -( authentications are needed\).) s -5 228 M -( The following method-specific message numbers are used by the) s -5 217 M -( publickey authentication method.) s -5 195 M -( /* Key-based */) s -5 184 M -( #define SSH_MSG_USERAUTH_PK_OK 60) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 9]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 10 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -(3.4 Password Authentication Method: password) s -5 668 M -( Password authentication uses the following packets. Note that a) s -5 657 M -( server MAY request the user to change the password. All) s -5 646 M -( implementations SHOULD support password authentication.) s -5 624 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 613 M -( string user name) s -5 602 M -( string service) s -5 591 M -( string "password") s -5 580 M -( boolean FALSE) s -5 569 M -( string plaintext password \(ISO-10646 UTF-8\)) s -5 547 M -( Note that the password is encoded in ISO-10646 UTF-8. It is up to) s -5 536 M -( the server how it interprets the password and validates it against) s -5 525 M -( the password database. However, if the client reads the password in) s -5 514 M -( some other encoding \(e.g., ISO 8859-1 \(ISO Latin1\)\), it MUST convert) s -5 503 M -( the password to ISO-10646 UTF-8 before transmitting, and the server) s -5 492 M -( MUST convert the password to the encoding used on that system for) s -5 481 M -( passwords.) s -5 459 M -( Note that even though the cleartext password is transmitted in the) s -5 448 M -( packet, the entire packet is encrypted by the transport layer. Both) s -5 437 M -( the server and the client should check whether the underlying) s -5 426 M -( transport layer provides confidentiality \(i.e., if encryption is) s -5 415 M -( being used\). If no confidentiality is provided \(none cipher\),) s -5 404 M -( password authentication SHOULD be disabled. If there is no) s -5 393 M -( confidentiality or no MAC, password change SHOULD be disabled.) s -5 371 M -( Normally, the server responds to this message with success or) s -5 360 M -( failure. However, if the password has expired the server SHOULD) s -5 349 M -( indicate this by responding with SSH_MSG_USERAUTH_PASSWD_CHANGEREQ.) s -5 338 M -( In anycase the server MUST NOT allow an expired password to be used) s -5 327 M -( for authentication.) s -5 305 M -( byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) s -5 294 M -( string prompt \(ISO-10646 UTF-8\)) s -5 283 M -( string language tag \(as defined in [RFC3066]\)) s -5 261 M -( In this case, the client MAY continue with a different authentication) s -5 250 M -( method, or request a new password from the user and retry password) s -5 239 M -( authentication using the following message. The client MAY also send) s -5 228 M -( this message instead of the normal password authentication request) s -5 217 M -( without the server asking for it.) s -5 195 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 184 M -( string user name) s -5 173 M -( string service) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 10]) s -_R -S -PStoPSsaved restore -%%Page: (10,11) 6 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 11 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( string "password") s -5 679 M -( boolean TRUE) s -5 668 M -( string plaintext old password \(ISO-10646 UTF-8\)) s -5 657 M -( string plaintext new password \(ISO-10646 UTF-8\)) s -5 635 M -( The server must reply to request message with) s -5 624 M -( SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another) s -5 613 M -( SSH_MSG_USERAUTH_PASSWD_CHANGEREQ. The meaning of these is as) s -5 602 M -( follows:) s -5 580 M -( SSH_MSG_USERAUTH_SUCCESS The password has been changed, and) s -5 569 M -( authentication has been successfully completed.) s -5 547 M -( SSH_MSG_USERAUTH_FAILURE with partial success The password has) s -5 536 M -( been changed, but more authentications are needed.) s -5 514 M -( SSH_MSG_USERAUTH_FAILURE without partial success The password has) s -5 503 M -( not been changed. Either password changing was not supported, or) s -5 492 M -( the old password was bad. Note that if the server has already) s -5 481 M -( sent SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, we know that it supports) s -5 470 M -( changing the password.) s -5 448 M -( SSH_MSG_USERAUTH_CHANGEREQ The password was not changed because) s -5 437 M -( the new password was not acceptable \(e.g. too easy to guess\).) s -5 415 M -( The following method-specific message numbers are used by the) s -5 404 M -( password authentication method.) s -5 382 M -( #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60) s -5 349 M -(3.5 Host-Based Authentication: hostbased) s -5 327 M -( Some sites wish to allow authentication based on the host where the) s -5 316 M -( user is coming from, and the user name on the remote host. While) s -5 305 M -( this form of authentication is not suitable for high-security sites,) s -5 294 M -( it can be very convenient in many environments. This form of) s -5 283 M -( authentication is OPTIONAL. When used, special care SHOULD be taken) s -5 272 M -( to prevent a regular user from obtaining the private host key.) s -5 250 M -( The client requests this form of authentication by sending the) s -5 239 M -( following message. It is similar to the UNIX "rhosts" and) s -5 228 M -( "hosts.equiv" styles of authentication, except that the identity of) s -5 217 M -( the client host is checked more rigorously.) s -5 195 M -( This method works by having the client send a signature created with) s -5 184 M -( the private key of the client host, which the server checks with that) s -5 173 M -( host's public key. Once the client host's identity is established,) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 11]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 12 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( authorization \(but no further authentication\) is performed based on) s -5 679 M -( the user names on the server and the client, and the client host) s -5 668 M -( name.) s -5 646 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 635 M -( string user name) s -5 624 M -( string service) s -5 613 M -( string "hostbased") s -5 602 M -( string public key algorithm for host key) s -5 591 M -( string public host key and certificates for client host) s -5 580 M -( string client host name \(FQDN; US-ASCII\)) s -5 569 M -( string user name on the client host \(ISO-10646 UTF-8\)) s -5 558 M -( string signature) s -5 536 M -( Public key algorithm names for use in "public key algorithm for host) s -5 525 M -( key" are defined in the transport layer specification. The "public) s -5 514 M -( host key for client host" may include certificates.) s -5 492 M -( Signature is a signature with the private host key of the following) s -5 481 M -( data, in this order:) s -5 459 M -( string session identifier) s -5 448 M -( byte SSH_MSG_USERAUTH_REQUEST) s -5 437 M -( string user name) s -5 426 M -( string service) s -5 415 M -( string "hostbased") s -5 404 M -( string public key algorithm for host key) s -5 393 M -( string public host key and certificates for client host) s -5 382 M -( string client host name \(FQDN; US-ASCII\)) s -5 371 M -( string user name on the client host\(ISO-10646 UTF-8\)) s -5 349 M -( The server MUST verify that the host key actually belongs to the) s -5 338 M -( client host named in the message, that the given user on that host is) s -5 327 M -( allowed to log in, and that the signature is a valid signature on the) s -5 316 M -( appropriate value by the given host key. The server MAY ignore the) s -5 305 M -( client user name, if it wants to authenticate only the client host.) s -5 283 M -( It is RECOMMENDED that whenever possible, the server perform) s -5 272 M -( additional checks to verify that the network address obtained from) s -5 261 M -( the \(untrusted\) network matches the given client host name. This) s -5 250 M -( makes exploiting compromised host keys more difficult. Note that) s -5 239 M -( this may require special handling for connections coming through a) s -5 228 M -( firewall.) s -5 206 M -(4. Security Considerations) s -5 184 M -( The purpose of this protocol is to perform client user) s -5 173 M -( authentication. It assumed that this runs over a secure transport) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 12]) s -_R -S -PStoPSsaved restore -%%Page: (12,13) 7 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 13 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( layer protocol, which has already authenticated the server machine,) s -5 679 M -( established an encrypted communications channel, and computed a) s -5 668 M -( unique session identifier for this session. The transport layer) s -5 657 M -( provides forward secrecy for password authentication and other) s -5 646 M -( methods that rely on secret data.) s -5 624 M -( Full security considerations for this protocol are provided in) s -5 613 M -( Section 8 of [SSH-ARCH]) s -5 591 M -(Normative) s -5 569 M -( [SSH-ARCH]) s -5 558 M -( Ylonen, T., "SSH Protocol Architecture", I-D) s -5 547 M -( draft-ietf-architecture-15.txt, Oct 2003.) s -5 525 M -( [SSH-TRANS]) s -5 514 M -( Ylonen, T., "SSH Transport Layer Protocol", I-D) s -5 503 M -( draft-ietf-transport-17.txt, Oct 2003.) s -5 481 M -( [SSH-USERAUTH]) s -5 470 M -( Ylonen, T., "SSH Authentication Protocol", I-D) s -5 459 M -( draft-ietf-userauth-18.txt, Oct 2003.) s -5 437 M -( [SSH-CONNECT]) s -5 426 M -( Ylonen, T., "SSH Connection Protocol", I-D) s -5 415 M -( draft-ietf-connect-18.txt, Oct 2003.) s -5 393 M -( [SSH-NUMBERS]) s -5 382 M -( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s -5 371 M -( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s -5 360 M -( 2003.) s -5 338 M -( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s -5 327 M -( Requirement Levels", BCP 14, RFC 2119, March 1997.) s -5 305 M -(Informative) s -5 283 M -( [RFC3066] Alvestrand, H., "Tags for the Identification of) s -5 272 M -( Languages", BCP 47, RFC 3066, January 2001.) s -5 250 M -( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s -5 239 M -( 10646", RFC 2279, January 1998.) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 13]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 14 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -(Authors' Addresses) s -5 668 M -( Tatu Ylonen) s -5 657 M -( SSH Communications Security Corp) s -5 646 M -( Fredrikinkatu 42) s -5 635 M -( HELSINKI FIN-00100) s -5 624 M -( Finland) s -5 602 M -( EMail: ylo@ssh.com) s -5 569 M -( Darren J. Moffat \(editor\)) s -5 558 M -( Sun Microsystems, Inc) s -5 547 M -( 17 Network Circle) s -5 536 M -( Menlo Park 95025) s -5 525 M -( USA) s -5 503 M -( EMail: Darren.Moffat@Sun.COM) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 14]) s -_R -S -PStoPSsaved restore -%%Page: (14,15) 8 -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 0.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -/showpage{}def/copypage{}def/erasepage{}def -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 15 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -(Intellectual Property Statement) s -5 668 M -( The IETF takes no position regarding the validity or scope of any) s -5 657 M -( intellectual property or other rights that might be claimed to) s -5 646 M -( pertain to the implementation or use of the technology described in) s -5 635 M -( this document or the extent to which any license under such rights) s -5 624 M -( might or might not be available; neither does it represent that it) s -5 613 M -( has made any effort to identify any such rights. Information on the) s -5 602 M -( IETF's procedures with respect to rights in standards-track and) s -5 591 M -( standards-related documentation can be found in BCP-11. Copies of) s -5 580 M -( claims of rights made available for publication and any assurances of) s -5 569 M -( licenses to be made available, or the result of an attempt made to) s -5 558 M -( obtain a general license or permission for the use of such) s -5 547 M -( proprietary rights by implementors or users of this specification can) s -5 536 M -( be obtained from the IETF Secretariat.) s -5 514 M -( The IETF invites any interested party to bring to its attention any) s -5 503 M -( copyrights, patents or patent applications, or other proprietary) s -5 492 M -( rights which may cover technology that may be required to practice) s -5 481 M -( this standard. Please address the information to the IETF Executive) s -5 470 M -( Director.) s -5 448 M -( The IETF has been notified of intellectual property rights claimed in) s -5 437 M -( regard to some or all of the specification contained in this) s -5 426 M -( document. For more information consult the online list of claimed) s -5 415 M -( rights.) s -5 382 M -(Full Copyright Statement) s -5 360 M -( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s -5 338 M -( This document and translations of it may be copied and furnished to) s -5 327 M -( others, and derivative works that comment on or otherwise explain it) s -5 316 M -( or assist in its implementation may be prepared, copied, published) s -5 305 M -( and distributed, in whole or in part, without restriction of any) s -5 294 M -( kind, provided that the above copyright notice and this paragraph are) s -5 283 M -( included on all such copies and derivative works. However, this) s -5 272 M -( document itself may not be modified in any way, such as by removing) s -5 261 M -( the copyright notice or references to the Internet Society or other) s -5 250 M -( Internet organizations, except as needed for the purpose of) s -5 239 M -( developing Internet standards in which case the procedures for) s -5 228 M -( copyrights defined in the Internet Standards process must be) s -5 217 M -( followed, or as required to translate it into languages other than) s -5 206 M -( English.) s -5 184 M -( The limited permissions granted above are perpetual and will not be) s -5 173 M -( revoked by the Internet Society or its successors or assignees.) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 15]) s -_R -S -PStoPSsaved restore -userdict/PStoPSsaved save put -PStoPSmatrix setmatrix -595.000000 421.271378 translate -90 rotate -0.706651 dup scale -userdict/PStoPSmatrix matrix currentmatrix put -userdict/PStoPSclip{0 0 moveto - 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto - closepath}put initclip -PStoPSxform concat -%%BeginPageSetup -_S -75 0 translate -/pagenum 16 def -/fname () def -/fdir () def -/ftail () def -/user_header_p false def -%%EndPageSetup -5 723 M -(Internet-Draft SSH Authentication Protocol September 2002) s -5 690 M -( This document and the information contained herein is provided on an) s -5 679 M -( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s -5 668 M -( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s -5 657 M -( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s -5 646 M -( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s -5 635 M -( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s -5 602 M -(Acknowledgment) s -5 580 M -( Funding for the RFC Editor function is currently provided by the) s -5 569 M -( Internet Society.) s -5 129 M -(Ylonen & Moffat Expires March 2, 2003 [Page 16]) s -_R -S -PStoPSsaved restore -%%Trailer -%%Pages: 16 -%%DocumentNeededResources: font Courier-Bold Courier -%%EOF diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt deleted file mode 100644 index 9dae578a35..0000000000 --- a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt +++ /dev/null @@ -1,896 +0,0 @@ - - - -Network Working Group T. Ylonen -Internet-Draft SSH Communications Security Corp -Expires: March 2, 2003 D. Moffat, Ed. - Sun Microsystems, Inc - September 2002 - - - SSH Authentication Protocol - draft-ietf-secsh-userauth-18.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on March 2, 2003. - -Copyright Notice - - Copyright (C) The Internet Society (2002). All Rights Reserved. - -Abstract - - SSH is a protocol for secure remote login and other secure network - services over an insecure network. This document describes the SSH - authentication protocol framework and public key, password, and - host-based client authentication methods. Additional authentication - methods are described in separate documents. The SSH authentication - protocol runs on top of the SSH transport layer protocol and provides - a single authenticated tunnel for the SSH connection protocol. - - - - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 1] - -Internet-Draft SSH Authentication Protocol September 2002 - - -Table of Contents - - 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 - 3. Conventions Used in This Document . . . . . . . . . . . . . 3 - 3.1 The Authentication Protocol Framework . . . . . . . . . . . 3 - 3.1.1 Authentication Requests . . . . . . . . . . . . . . . . . . 4 - 3.1.2 Responses to Authentication Requests . . . . . . . . . . . . 5 - 3.1.3 The "none" Authentication Request . . . . . . . . . . . . . 6 - 3.1.4 Completion of User Authentication . . . . . . . . . . . . . 6 - 3.1.5 Banner Message . . . . . . . . . . . . . . . . . . . . . . . 7 - 3.2 Authentication Protocol Message Numbers . . . . . . . . . . 7 - 3.3 Public Key Authentication Method: publickey . . . . . . . . 8 - 3.4 Password Authentication Method: password . . . . . . . . . . 10 - 3.5 Host-Based Authentication: hostbased . . . . . . . . . . . . 11 - 4. Security Considerations . . . . . . . . . . . . . . . . . . 12 - Normative . . . . . . . . . . . . . . . . . . . . . . . . . 13 - Informative . . . . . . . . . . . . . . . . . . . . . . . . 13 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 14 - Intellectual Property and Copyright Statements . . . . . . . 15 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 2] - -Internet-Draft SSH Authentication Protocol September 2002 - - -1. Contributors - - The major original contributors of this document were: Tatu Ylonen, - Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications - Security Corp), and Markku-Juhani O. Saarinen (University of - Jyvaskyla) - - The document editor is: Darren.Moffat@Sun.COM. Comments on this - internet draft should be sent to the IETF SECSH working group, - details at: http://ietf.org/html.charters/secsh-charter.html - -2. Introduction - - The SSH authentication protocol is a general-purpose user - authentication protocol. It is intended to be run over the SSH - transport layer protocol [SSH-TRANS]. This protocol assumes that the - underlying protocols provide integrity and confidentiality - protection. - - This document should be read only after reading the SSH architecture - document [SSH-ARCH]. This document freely uses terminology and - notation from the architecture document without reference or further - explanation. - - The service name for this protocol is "ssh-userauth". - - When this protocol starts, it receives the session identifier from - the lower-level protocol (this is the exchange hash H from the first - key exchange). The session identifier uniquely identifies this - session and is suitable for signing in order to prove ownership of a - private key. This protocol also needs to know whether the lower-level - protocol provides confidentiality protection. - -3. Conventions Used in This Document - - The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", - and "MAY" that appear in this document are to be interpreted as - described in [RFC2119] - - The used data types and terminology are specified in the architecture - document [SSH-ARCH] - - The architecture document also discusses the algorithm naming - conventions that MUST be used with the SSH protocols. - -3.1 The Authentication Protocol Framework - - The server drives the authentication by telling the client which - - - -Ylonen & Moffat Expires March 2, 2003 [Page 3] - -Internet-Draft SSH Authentication Protocol September 2002 - - - authentication methods can be used to continue the exchange at any - given time. The client has the freedom to try the methods listed by - the server in any order. This gives the server complete control over - the authentication process if desired, but also gives enough - flexibility for the client to use the methods it supports or that are - most convenient for the user, when multiple methods are offered by - the server. - - Authentication methods are identified by their name, as defined in - [SSH-ARCH]. The "none" method is reserved, and MUST NOT be listed as - supported. However, it MAY be sent by the client. The server MUST - always reject this request, unless the client is to be allowed in - without any authentication, in which case the server MUST accept this - request. The main purpose of sending this request is to get the list - of supported methods from the server. - - The server SHOULD have a timeout for authentication, and disconnect - if the authentication has not been accepted within the timeout - period. The RECOMMENDED timeout period is 10 minutes. Additionally, - the implementation SHOULD limit the number of failed authentication - attempts a client may perform in a single session (the RECOMMENDED - limit is 20 attempts). If the threshold is exceeded, the server - SHOULD disconnect. - -3.1.1 Authentication Requests - - All authentication requests MUST use the following message format. - Only the first few fields are defined; the remaining fields depend on - the authentication method. - - byte SSH_MSG_USERAUTH_REQUEST - string user name (in ISO-10646 UTF-8 encoding [RFC2279]) - string service name (in US-ASCII) - string method name (US-ASCII) - The rest of the packet is method-specific. - - The user name and service are repeated in every new authentication - attempt, and MAY change. The server implementation MUST carefully - check them in every message, and MUST flush any accumulated - authentication states if they change. If it is unable to flush some - authentication state, it MUST disconnect if the user or service name - changes. - - The service name specifies the service to start after authentication. - There may be several different authenticated services provided. If - the requested service is not available, the server MAY disconnect - immediately or at any later time. Sending a proper disconnect - message is RECOMMENDED. In any case, if the service does not exist, - - - -Ylonen & Moffat Expires March 2, 2003 [Page 4] - -Internet-Draft SSH Authentication Protocol September 2002 - - - authentication MUST NOT be accepted. - - If the requested user does not exist, the server MAY disconnect, or - MAY send a bogus list of acceptable authentication methods, but never - accept any. This makes it possible for the server to avoid - disclosing information on which accounts exist. In any case, if the - user does not exist, the authentication request MUST NOT be accepted. - - While there is usually little point for clients to send requests that - the server does not list as acceptable, sending such requests is not - an error, and the server SHOULD simply reject requests that it does - not recognize. - - An authentication request MAY result in a further exchange of - messages. All such messages depend on the authentication method - used, and the client MAY at any time continue with a new - SSH_MSG_USERAUTH_REQUEST message, in which case the server MUST - abandon the previous authentication attempt and continue with the new - one. - -3.1.2 Responses to Authentication Requests - - If the server rejects the authentication request, it MUST respond - with the following: - - byte SSH_MSG_USERAUTH_FAILURE - string authentications that can continue - boolean partial success - - "Authentications that can continue" is a comma-separated list of - authentication method names that may productively continue the - authentication dialog. - - It is RECOMMENDED that servers only include those methods in the list - that are actually useful. However, it is not illegal to include - methods that cannot be used to authenticate the user. - - Already successfully completed authentications SHOULD NOT be included - in the list, unless they really should be performed again for some - reason. - - "Partial success" MUST be TRUE if the authentication request to which - this is a response was successful. It MUST be FALSE if the request - was not successfully processed. - - When the server accepts authentication, it MUST respond with the - following: - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 5] - -Internet-Draft SSH Authentication Protocol September 2002 - - - byte SSH_MSG_USERAUTH_SUCCESS - - Note that this is not sent after each step in a multi-method - authentication sequence, but only when the authentication is - complete. - - The client MAY send several authentication requests without waiting - for responses from previous requests. The server MUST process each - request completely and acknowledge any failed requests with a - SSH_MSG_USERAUTH_FAILURE message before processing the next request. - - A request that results in further exchange of messages will be - aborted by a second request. It is not possible to send a second - request without waiting for a response from the server, if the first - request will result in further exchange of messages. No - SSH_MSG_USERAUTH_FAILURE message will be sent for the aborted method. - - SSH_MSG_USERAUTH_SUCCESS MUST be sent only once. When - SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication - requests received after that SHOULD be silently ignored. - - Any non-authentication messages sent by the client after the request - that resulted in SSH_MSG_USERAUTH_SUCCESS being sent MUST be passed - to the service being run on top of this protocol. Such messages can - be identified by their message numbers (see Section Message Numbers - (Section 3.2)). - -3.1.3 The "none" Authentication Request - - A client may request a list of authentication methods that may - continue by using the "none" authentication method. - - If no authentication at all is needed for the user, the server MUST - return SSH_MSG_USERAUTH_SUCCESS. Otherwise, the server MUST return - SSH_MSG_USERAUTH_FAILURE and MAY return with it a list of - authentication methods that can continue. - - This method MUST NOT be listed as supported by the server. - -3.1.4 Completion of User Authentication - - Authentication is complete when the server has responded with - SSH_MSG_USERAUTH_SUCCESS; all authentication related messages - received after sending this message SHOULD be silently ignored. - - After sending SSH_MSG_USERAUTH_SUCCESS, the server starts the - requested service. - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 6] - -Internet-Draft SSH Authentication Protocol September 2002 - - -3.1.5 Banner Message - - In some jurisdictions, sending a warning message before - authentication may be relevant for getting legal protection. Many - UNIX machines, for example, normally display text from `/etc/issue', - or use "tcp wrappers" or similar software to display a banner before - issuing a login prompt. - - The SSH server may send a SSH_MSG_USERAUTH_BANNER message at any time - before authentication is successful. This message contains text to - be displayed to the client user before authentication is attempted. - The format is as follows: - - byte SSH_MSG_USERAUTH_BANNER - string message (ISO-10646 UTF-8) - string language tag (as defined in [RFC3066]) - - The client SHOULD by default display the message on the screen. - However, since the message is likely to be sent for every login - attempt, and since some client software will need to open a separate - window for this warning, the client software may allow the user to - explicitly disable the display of banners from the server. The - message may consist of multiple lines. - - If the message string is displayed, control character filtering - discussed in [SSH-ARCH] SHOULD be used to avoid attacks by sending - terminal control characters. - -3.2 Authentication Protocol Message Numbers - - All message numbers used by this authentication protocol are in the - range from 50 to 79, which is part of the range reserved for - protocols running on top of the SSH transport layer protocol. - - Message numbers of 80 and higher are reserved for protocols running - after this authentication protocol, so receiving one of them before - authentication is complete is an error, to which the server MUST - respond by disconnecting (preferably with a proper disconnect message - sent first to ease troubleshooting). - - After successful authentication, such messages are passed to the - higher-level service. - - These are the general authentication message codes: - - #define SSH_MSG_USERAUTH_REQUEST 50 - #define SSH_MSG_USERAUTH_FAILURE 51 - #define SSH_MSG_USERAUTH_SUCCESS 52 - - - -Ylonen & Moffat Expires March 2, 2003 [Page 7] - -Internet-Draft SSH Authentication Protocol September 2002 - - - #define SSH_MSG_USERAUTH_BANNER 53 - - In addition to the above, there is a range of message numbers - (60..79) reserved for method-specific messages. These messages are - only sent by the server (client sends only SSH_MSG_USERAUTH_REQUEST - messages). Different authentication methods reuse the same message - numbers. - -3.3 Public Key Authentication Method: publickey - - The only REQUIRED authentication method is public key authentication. - All implementations MUST support this method; however, not all users - need to have public keys, and most local policies are not likely to - require public key authentication for all users in the near future. - - With this method, the possession of a private key serves as - authentication. This method works by sending a signature created - with a private key of the user. The server MUST check that the key - is a valid authenticator for the user, and MUST check that the - signature is valid. If both hold, the authentication request MUST be - accepted; otherwise it MUST be rejected. (Note that the server MAY - require additional authentications after successful authentication.) - - Private keys are often stored in an encrypted form at the client - host, and the user must supply a passphrase before the signature can - be generated. Even if they are not, the signing operation involves - some expensive computation. To avoid unnecessary processing and user - interaction, the following message is provided for querying whether - authentication using the key would be acceptable. - - byte SSH_MSG_USERAUTH_REQUEST - string user name - string service - string "publickey" - boolean FALSE - string public key algorithm name - string public key blob - - Public key algorithms are defined in the transport layer - specification [SSH-TRANS]. The public key blob may contain - certificates. - - Any public key algorithm may be offered for use in authentication. - In particular, the list is not constrained by what was negotiated - during key exchange. If the server does not support some algorithm, - it MUST simply reject the request. - - The server MUST respond to this message with either - - - -Ylonen & Moffat Expires March 2, 2003 [Page 8] - -Internet-Draft SSH Authentication Protocol September 2002 - - - SSH_MSG_USERAUTH_FAILURE or with the following: - - byte SSH_MSG_USERAUTH_PK_OK - string public key algorithm name from the request - string public key blob from the request - - To perform actual authentication, the client MAY then send a - signature generated using the private key. The client MAY send the - signature directly without first verifying whether the key is - acceptable. The signature is sent using the following packet: - - byte SSH_MSG_USERAUTH_REQUEST - string user name - string service - string "publickey" - boolean TRUE - string public key algorithm name - string public key to be used for authentication - string signature - - Signature is a signature by the corresponding private key over the - following data, in the following order: - - string session identifier - byte SSH_MSG_USERAUTH_REQUEST - string user name - string service - string "publickey" - boolean TRUE - string public key algorithm name - string public key to be used for authentication - - When the server receives this message, it MUST check whether the - supplied key is acceptable for authentication, and if so, it MUST - check whether the signature is correct. - - If both checks succeed, this method is successful. Note that the - server may require additional authentications. The server MUST - respond with SSH_MSG_USERAUTH_SUCCESS (if no more authentications are - needed), or SSH_MSG_USERAUTH_FAILURE (if the request failed, or more - authentications are needed). - - The following method-specific message numbers are used by the - publickey authentication method. - - /* Key-based */ - #define SSH_MSG_USERAUTH_PK_OK 60 - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 9] - -Internet-Draft SSH Authentication Protocol September 2002 - - -3.4 Password Authentication Method: password - - Password authentication uses the following packets. Note that a - server MAY request the user to change the password. All - implementations SHOULD support password authentication. - - byte SSH_MSG_USERAUTH_REQUEST - string user name - string service - string "password" - boolean FALSE - string plaintext password (ISO-10646 UTF-8) - - Note that the password is encoded in ISO-10646 UTF-8. It is up to - the server how it interprets the password and validates it against - the password database. However, if the client reads the password in - some other encoding (e.g., ISO 8859-1 (ISO Latin1)), it MUST convert - the password to ISO-10646 UTF-8 before transmitting, and the server - MUST convert the password to the encoding used on that system for - passwords. - - Note that even though the cleartext password is transmitted in the - packet, the entire packet is encrypted by the transport layer. Both - the server and the client should check whether the underlying - transport layer provides confidentiality (i.e., if encryption is - being used). If no confidentiality is provided (none cipher), - password authentication SHOULD be disabled. If there is no - confidentiality or no MAC, password change SHOULD be disabled. - - Normally, the server responds to this message with success or - failure. However, if the password has expired the server SHOULD - indicate this by responding with SSH_MSG_USERAUTH_PASSWD_CHANGEREQ. - In anycase the server MUST NOT allow an expired password to be used - for authentication. - - byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ - string prompt (ISO-10646 UTF-8) - string language tag (as defined in [RFC3066]) - - In this case, the client MAY continue with a different authentication - method, or request a new password from the user and retry password - authentication using the following message. The client MAY also send - this message instead of the normal password authentication request - without the server asking for it. - - byte SSH_MSG_USERAUTH_REQUEST - string user name - string service - - - -Ylonen & Moffat Expires March 2, 2003 [Page 10] - -Internet-Draft SSH Authentication Protocol September 2002 - - - string "password" - boolean TRUE - string plaintext old password (ISO-10646 UTF-8) - string plaintext new password (ISO-10646 UTF-8) - - The server must reply to request message with - SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another - SSH_MSG_USERAUTH_PASSWD_CHANGEREQ. The meaning of these is as - follows: - - SSH_MSG_USERAUTH_SUCCESS The password has been changed, and - authentication has been successfully completed. - - SSH_MSG_USERAUTH_FAILURE with partial success The password has - been changed, but more authentications are needed. - - SSH_MSG_USERAUTH_FAILURE without partial success The password has - not been changed. Either password changing was not supported, or - the old password was bad. Note that if the server has already - sent SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, we know that it supports - changing the password. - - SSH_MSG_USERAUTH_CHANGEREQ The password was not changed because - the new password was not acceptable (e.g. too easy to guess). - - The following method-specific message numbers are used by the - password authentication method. - - #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60 - - -3.5 Host-Based Authentication: hostbased - - Some sites wish to allow authentication based on the host where the - user is coming from, and the user name on the remote host. While - this form of authentication is not suitable for high-security sites, - it can be very convenient in many environments. This form of - authentication is OPTIONAL. When used, special care SHOULD be taken - to prevent a regular user from obtaining the private host key. - - The client requests this form of authentication by sending the - following message. It is similar to the UNIX "rhosts" and - "hosts.equiv" styles of authentication, except that the identity of - the client host is checked more rigorously. - - This method works by having the client send a signature created with - the private key of the client host, which the server checks with that - host's public key. Once the client host's identity is established, - - - -Ylonen & Moffat Expires March 2, 2003 [Page 11] - -Internet-Draft SSH Authentication Protocol September 2002 - - - authorization (but no further authentication) is performed based on - the user names on the server and the client, and the client host - name. - - byte SSH_MSG_USERAUTH_REQUEST - string user name - string service - string "hostbased" - string public key algorithm for host key - string public host key and certificates for client host - string client host name (FQDN; US-ASCII) - string user name on the client host (ISO-10646 UTF-8) - string signature - - Public key algorithm names for use in "public key algorithm for host - key" are defined in the transport layer specification. The "public - host key for client host" may include certificates. - - Signature is a signature with the private host key of the following - data, in this order: - - string session identifier - byte SSH_MSG_USERAUTH_REQUEST - string user name - string service - string "hostbased" - string public key algorithm for host key - string public host key and certificates for client host - string client host name (FQDN; US-ASCII) - string user name on the client host(ISO-10646 UTF-8) - - The server MUST verify that the host key actually belongs to the - client host named in the message, that the given user on that host is - allowed to log in, and that the signature is a valid signature on the - appropriate value by the given host key. The server MAY ignore the - client user name, if it wants to authenticate only the client host. - - It is RECOMMENDED that whenever possible, the server perform - additional checks to verify that the network address obtained from - the (untrusted) network matches the given client host name. This - makes exploiting compromised host keys more difficult. Note that - this may require special handling for connections coming through a - firewall. - -4. Security Considerations - - The purpose of this protocol is to perform client user - authentication. It assumed that this runs over a secure transport - - - -Ylonen & Moffat Expires March 2, 2003 [Page 12] - -Internet-Draft SSH Authentication Protocol September 2002 - - - layer protocol, which has already authenticated the server machine, - established an encrypted communications channel, and computed a - unique session identifier for this session. The transport layer - provides forward secrecy for password authentication and other - methods that rely on secret data. - - Full security considerations for this protocol are provided in - Section 8 of [SSH-ARCH] - -Normative - - [SSH-ARCH] - Ylonen, T., "SSH Protocol Architecture", I-D - draft-ietf-architecture-15.txt, Oct 2003. - - [SSH-TRANS] - Ylonen, T., "SSH Transport Layer Protocol", I-D - draft-ietf-transport-17.txt, Oct 2003. - - [SSH-USERAUTH] - Ylonen, T., "SSH Authentication Protocol", I-D - draft-ietf-userauth-18.txt, Oct 2003. - - [SSH-CONNECT] - Ylonen, T., "SSH Connection Protocol", I-D - draft-ietf-connect-18.txt, Oct 2003. - - [SSH-NUMBERS] - Lehtinen, S. and D. Moffat, "SSH Protocol Assigned - Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct - 2003. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - -Informative - - [RFC3066] Alvestrand, H., "Tags for the Identification of - Languages", BCP 47, RFC 3066, January 2001. - - [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - - - - - - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 13] - -Internet-Draft SSH Authentication Protocol September 2002 - - -Authors' Addresses - - Tatu Ylonen - SSH Communications Security Corp - Fredrikinkatu 42 - HELSINKI FIN-00100 - Finland - - EMail: ylo@ssh.com - - - Darren J. Moffat (editor) - Sun Microsystems, Inc - 17 Network Circle - Menlo Park 95025 - USA - - EMail: Darren.Moffat@Sun.COM - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 14] - -Internet-Draft SSH Authentication Protocol September 2002 - - -Intellectual Property Statement - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementors or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - The IETF has been notified of intellectual property rights claimed in - regard to some or all of the specification contained in this - document. For more information consult the online list of claimed - rights. - - -Full Copyright Statement - - Copyright (C) The Internet Society (2002). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assignees. - - - -Ylonen & Moffat Expires March 2, 2003 [Page 15] - -Internet-Draft SSH Authentication Protocol September 2002 - - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - -Acknowledgment - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ylonen & Moffat Expires March 2, 2003 [Page 16] \ No newline at end of file -- cgit v1.2.3 From 6a885ee06515c2a8dfa3e0594123ef76cda9672a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 10 Nov 2015 12:35:31 +0100 Subject: ssh: updated ssh_app.xml with ecdsa info --- lib/ssh/doc/src/ssh_app.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index 4c85585820..0baa44a6a7 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -62,10 +62,13 @@ authorized_keys2 id_dsa id_rsa + id_ecdsa ssh_host_dsa_key ssh_host_rsa_key + ssh_host_ecdsa_key

By default, ssh looks for id_dsa, id_rsa, + id_ecdsa_key, known_hosts, and authorized_keys in ~/.ssh, and for the host key files in /etc/ssh. These locations can be changed by the options user_dir and system_dir. @@ -79,7 +82,7 @@

Public Keys -

id_dsa and id_rsa are the users private key files. +

id_dsa, id_rsa and id_ecdsa are the users private key files. Notice that the public key is part of the private key so the ssh application does not use the id_<*>.pub files. These are for the user's convenience when it is needed to convey the user's @@ -104,8 +107,8 @@

Host Keys

RSA and DSA host keys are supported and are - expected to be found in files named ssh_host_rsa_key and - ssh_host_dsa_key. + expected to be found in files named ssh_host_rsa_key, + ssh_host_dsa_key and ssh_host_ecdsa_key.

-- cgit v1.2.3 From 05f4a611d3269b12edd709a988fa1da4c4690a82 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 10 Nov 2015 13:01:38 +0100 Subject: ssh: links to crypto and public_key in the ssh app ref --- lib/ssh/doc/src/ssh_app.xml | 9 ++++++--- lib/ssh/doc/src/ssh_connection.xml | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index 0baa44a6a7..1ae1558607 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -41,11 +41,14 @@
DEPENDENCIES -

The ssh application uses the applications public_key and - crypto to handle public keys and encryption. Hence, these +

The ssh application uses the applications + public_key and + crypto + to handle public keys and encryption. Hence, these applications must be loaded for the ssh application to work. In an embedded environment this means that they must be started with - application:start/[1,2] before the ssh application is started. + application:start/1,2 before the + ssh application is started.

diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml index 7e7cfad90d..064a623eb6 100644 --- a/lib/ssh/doc/src/ssh_connection.xml +++ b/lib/ssh/doc/src/ssh_connection.xml @@ -373,7 +373,7 @@

Is to be called by client- and server-channel processes to send data to each other.

-

The function subsystem/4 and subsequent +

The function subsystem/4 and subsequent calls of send/3,4,5 must be executed in the same process.

@@ -458,7 +458,7 @@ subsystem on the server.

The function subsystem/4 and subsequent calls of - send/3,4,5 must be executed in the same process. + send/3,4,5 must be executed in the same process.

-- cgit v1.2.3 From 77acb473d8f056f6f534395f131c6e45693797f0 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 4 Nov 2015 15:14:21 +0100 Subject: inets: Terminate gracfully when an invalid chunked length header is encountered Also use integer_to_list/2 and list_to_integer/2 instead of reimplementing it. --- lib/inets/src/http_lib/http_chunk.erl | 8 ++- lib/inets/src/http_lib/http_util.erl | 69 ++-------------------- .../src/http_server/httpd_request_handler.erl | 10 +++- 3 files changed, 18 insertions(+), 69 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl index 9476ea9f5f..c17ff6cce5 100644 --- a/lib/inets/src/http_lib/http_chunk.erl +++ b/lib/inets/src/http_lib/http_chunk.erl @@ -143,20 +143,22 @@ decode_size(Data = <>, HexList, {MaxBodySize, Body, AccLength, MaxHeaderSize}) -> - ChunkSize = http_util:hexlist_to_integer(lists:reverse(HexList)), - case ChunkSize of + try http_util:hexlist_to_integer(lists:reverse(HexList)) of 0 -> % Last chunk, there was no data ignore_extensions(Data, {?MODULE, decode_trailer, [<<>>, [],[], MaxHeaderSize, Body, integer_to_list(AccLength)]}); - _ -> + ChunkSize -> %% Note decode_data may call decode_size again if there %% is more than one chunk, hence here is where the last parameter %% to this function comes in. decode_data(ChunkSize, ChunkRest, {MaxBodySize, Body, ChunkSize + AccLength , MaxHeaderSize}) + catch + _:_ -> + throw({error, {chunk_size, HexList}}) end; decode_size(<<";", Rest/binary>>, HexList, Info) -> %% Note ignore_extensions will call decode_size/1 again when diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl index 0d07231302..aafa97afee 100644 --- a/lib/inets/src/http_lib/http_util.erl +++ b/lib/inets/src/http_lib/http_util.erl @@ -152,27 +152,11 @@ convert_netscapecookie_date([_D,_A,_Y, _SP, Sec=list_to_integer([S1,S2]), {{Year,Month,Day},{Hour,Min,Sec}}. -hexlist_to_integer([]) -> - empty; -%%When the string only contains one value its eaasy done. -%% 0-9 -hexlist_to_integer([Size]) when (Size >= 48) andalso (Size =< 57) -> - Size - 48; -%% A-F -hexlist_to_integer([Size]) when (Size >= 65) andalso (Size =< 70) -> - Size - 55; -%% a-f -hexlist_to_integer([Size]) when (Size >= 97) andalso (Size =< 102) -> - Size - 87; -hexlist_to_integer([_Size]) -> - not_a_num; +hexlist_to_integer(List) -> + list_to_integer(List, 16). -hexlist_to_integer(Size) -> - Len = string:span(Size, "1234567890abcdefABCDEF"), - hexlist_to_integer2(Size, 16 bsl (4 *(Len-2)),0). - -integer_to_hexlist(Num)-> - integer_to_hexlist(Num, get_size(Num), []). +integer_to_hexlist(Int) -> + integer_to_list(Int, 16). convert_month("Jan") -> 1; convert_month("Feb") -> 2; @@ -213,51 +197,6 @@ html_encode(Chars) -> %%%======================================================================== %%% Internal functions %%%======================================================================== -hexlist_to_integer2([],_Pos,Sum)-> - Sum; -hexlist_to_integer2([HexVal | HexString], Pos, Sum) - when HexVal >= 48, HexVal =< 57 -> - hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-48) * Pos)); - -hexlist_to_integer2([HexVal | HexString], Pos, Sum) - when HexVal >= 65, HexVal =<70 -> - hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-55) * Pos)); - -hexlist_to_integer2([HexVal | HexString], Pos, Sum) - when HexVal>=97, HexVal=<102 -> - hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-87) * Pos)); - -hexlist_to_integer2(_AfterHexString, _Pos, Sum)-> - Sum. - -integer_to_hexlist(Num, Pot, Res) when Pot < 0 -> - convert_to_ascii([Num | Res]); - -integer_to_hexlist(Num,Pot,Res) -> - Position = (16 bsl (Pot*4)), - PosVal = Num div Position, - integer_to_hexlist(Num - (PosVal*Position), Pot-1, [PosVal | Res]). - -get_size(Num)-> - get_size(Num, 0). - -get_size(Num, Pot) when Num < (16 bsl(Pot *4)) -> - Pot-1; - -get_size(Num, Pot) -> - get_size(Num, Pot+1). - -convert_to_ascii(RevesedNum) -> - convert_to_ascii(RevesedNum, []). - -convert_to_ascii([], Num)-> - Num; -convert_to_ascii([Num | Reversed], Number) - when (Num > -1) andalso (Num < 10) -> - convert_to_ascii(Reversed, [Num + 48 | Number]); -convert_to_ascii([Num | Reversed], Number) - when (Num > 9) andalso (Num < 16) -> - convert_to_ascii(Reversed, [Num + 55 | Number]). char_to_html_entity(Char, Reserved) -> case sets:is_element(Char, Reserved) of diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl index e5d006c1fd..143d599edb 100644 --- a/lib/inets/src/http_server/httpd_request_handler.erl +++ b/lib/inets/src/http_server/httpd_request_handler.erl @@ -443,7 +443,7 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State, MaxHeaderSize, MaxBodySize) -> case Headers#http_request_h.'transfer-encoding' of "chunked" -> - case http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of + try http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of {Module, Function, Args} -> http_transport:setopts(ModData#mod.socket_type, ModData#mod.socket, @@ -455,6 +455,14 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State, http_chunk:handle_headers(Headers, ChunkedHeaders), handle_response(State#state{headers = NewHeaders, body = NewBody}) + catch + throw:Error -> + httpd_response:send_status(ModData, 400, + "Bad input"), + Reason = io_lib:format("Chunk decoding failed: ~p~n", + [Error]), + error_log(Reason, ModData), + {stop, normal, State#state{response_sent = true}} end; Encoding when is_list(Encoding) -> httpd_response:send_status(ModData, 501, -- cgit v1.2.3 From 6848ea3aa947ea8862e939af4f794700ebbcfed3 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 5 Nov 2015 15:56:03 +0100 Subject: inets: CT'ify http_format_SUITE --- lib/inets/test/http_format_SUITE.erl | 155 +++++++++++------------------------ 1 file changed, 46 insertions(+), 109 deletions(-) (limited to 'lib') diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl index a97b51601f..83ffe259b3 100644 --- a/lib/inets/test/http_format_SUITE.erl +++ b/lib/inets/test/http_format_SUITE.erl @@ -20,26 +20,12 @@ %% -module(http_format_SUITE). --author('ingela@erix.ericsson.se'). -include_lib("common_test/include/ct.hrl"). --include("test_server_line.hrl"). -include("http_internal.hrl"). -%% Test server specific exports --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). - -%% Test cases must be exported. --export([ chunk_decode/1, chunk_encode/1, - chunk_extensions_otp_6005/1, chunk_decode_otp_6264/1, - chunk_decode_empty_chunk_otp_6511/1, - chunk_decode_trailer/1, - http_response/1, http_request/1, validate_request_line/1, - esi_parse_headers/1, cgi_parse_headers/1, - is_absolut_uri/1, convert_netscapecookie_date/1, - check_content_length_encoding/1]). - -suite() -> [{ct_hooks,[ts_install_cth]}]. +%% Note: This directive should only be used in test suites. +-compile(export_all). all() -> [{group, chunk}, http_response, http_request, @@ -81,12 +67,8 @@ end_per_testcase(_, Config) -> %% Test cases starts here. %%------------------------------------------------------------------------- - -%%------------------------------------------------------------------------- -chunk_decode(doc) -> - ["Test http_chunk:decode/3"]; -chunk_decode(suite) -> - []; +chunk_decode() -> + [{doc, "Test http_chunk:decode/3"}]. chunk_decode(Config) when is_list(Config) -> ReqHeaders = #http_request_h{'transfer-encoding' = "chunked"}, ChunkedBody = "A" ++ ?CRLF ++ "1234567890" ++ ?CRLF ++ "4" ++ @@ -114,10 +96,8 @@ chunk_decode(Config) when is_list(Config) -> ok. %%------------------------------------------------------------------------- -chunk_extensions_otp_6005(doc) -> - ["Make sure so called extensions are ignored"]; -chunk_extensions_otp_6005(suite) -> - []; +chunk_extensions_otp_6005() -> + [{doc, "Make sure so called extensions are ignored"}]. chunk_extensions_otp_6005(Config) when is_list(Config)-> ChunkedBody = "A;ignore this" ++ ?CRLF ++ "1234567890" ++ ?CRLF ++ "4" ++ ?CRLF ++ "HEJ!"++ ?CRLF ++ "0" ++ @@ -136,14 +116,11 @@ chunk_extensions_otp_6005(Config) when is_list(Config)-> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, NewBody} = parse(Module1, Function1, Args1, tl(ChunkedBody1)), - "1234567890HEJ!" = binary_to_list(NewBody), - ok. + "1234567890HEJ!" = binary_to_list(NewBody). %%------------------------------------------------------------------------- -chunk_decode_otp_6264(doc) -> - ["Check that 0 in the body does not count as the last chunk"]; -chunk_decode_otp_6264(suite) -> - []; +chunk_decode_otp_6264() -> + [{doc, "Check that 0 in the body does not count as the last chunk"}]. chunk_decode_otp_6264(Config) when is_list(Config)-> ChunkedBody = "A;ignore this" ++ ?CRLF ++ "1234567890" ++ ?CRLF ++ "4" ++ ?CRLF ++ "0123"++ ?CRLF ++ "0" ++ @@ -173,27 +150,18 @@ chunk_decode_otp_6264(Config) when is_list(Config)-> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, NewBody} = parse(Module1, Function1, Args1, tl(NewChunkedBody1)), - "12345678900" = binary_to_list(NewBody), - - ok. + "12345678900" = binary_to_list(NewBody). %%------------------------------------------------------------------------- -chunk_decode_empty_chunk_otp_6511(doc) -> - [""]; -chunk_decode_empty_chunk_otp_6511(suite) -> - []; chunk_decode_empty_chunk_otp_6511(Config) when is_list(Config) -> ChunkedBody = "0" ++ ?CRLF ++ ?CRLF, {ok,{["content-length:0"],<<>>}} = http_chunk:decode(list_to_binary(ChunkedBody), - ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), - ok. + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE). %%------------------------------------------------------------------------- -chunk_decode_trailer(doc) -> - ["Make sure trailers are handled correctly. Trailers should" - "become new headers"]; -chunk_decode_trailer(suite) -> - []; +chunk_decode_trailer() -> + [{doc,"Make sure trailers are handled correctly. Trailers should" + "become new headers"}]. chunk_decode_trailer(Config) when is_list(Config)-> ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++ "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF @@ -249,15 +217,11 @@ chunk_decode_trailer(Config) when is_list(Config)-> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, NewBody} = parse(Module1, Function1, Args1, tl(ChunkedBody3)), - "abcdefghijklmnopqrstuvwxyz1234567890abcdef" = binary_to_list(NewBody), - - ok. + "abcdefghijklmnopqrstuvwxyz1234567890abcdef" = binary_to_list(NewBody). %%------------------------------------------------------------------------- -chunk_encode(doc) -> - ["Test http_chunk:encode/1 & http_chunk:encode_last/0"]; -chunk_encode(suite) -> - []; +chunk_encode() -> + [{doc, "Test http_chunk:encode/1 & http_chunk:encode_last/0"}]. chunk_encode(Config) when is_list(Config) -> <<54, ?CR, ?LF, 102,111,111,98,97,114, ?CR, ?LF>> = http_chunk:encode(list_to_binary("foobar")), @@ -267,12 +231,10 @@ chunk_encode(Config) when is_list(Config) -> %%------------------------------------------------------------------------- -http_response(doc) -> - ["Test httpc_response:parse*. This test case will simulate that the " +http_response() -> + [{doc, "Test httpc_response:parse*. This test case will simulate that the " "message will be recived a little at the time on a socket and the " - "package may be broken up into smaller parts at arbitrary point."]; -http_response(suite) -> - []; + "package may be broken up into smaller parts at arbitrary point."}]. http_response(Config) when is_list(Config) -> HttpHead1 = ["HTTP", "/1.1 ", "20", "0 ", "ok", [?CR, ?LF], @@ -340,12 +302,10 @@ http_response(Config) when is_list(Config) -> [<<>>,Length1], HttpBody1)), ok. %%------------------------------------------------------------------------- -http_request(doc) -> - ["Test httpd_request:parse* This test case will simulate that the " +http_request() -> + [{doc, "Test httpd_request:parse* This test case will simulate that the " "message will be recived a little at the time on a socket and the " - "package may be broken up into smaller parts at arbitrary point."]; -http_request(suite) -> - []; + "package may be broken up into smaller parts at arbitrary point."}]. http_request(Config) when is_list(Config) -> HttpHead = ["GE", "T ", "http://www.erlang", ".org ", "HTTP", @@ -407,15 +367,12 @@ http_request(Config) when is_list(Config) -> NewBody1 = binary_to_list(parse (httpd_request, whole_body, - [<<>>, Length1], HttpBody1)), - ok. + [<<>>, Length1], HttpBody1)). %%------------------------------------------------------------------------- -validate_request_line(doc) -> - ["Test httpd_request:validate/3. Makes sure you can not get past" +validate_request_line() -> + [{doc, "Test httpd_request:validate/3. Makes sure you can not get past" " the server_root and that the request is recognized by the server" - " and protcol version." ]; -validate_request_line(suite) -> - []; + " and protcol version."}]. validate_request_line(Config) when is_list(Config) -> %% HTTP/0.9 only has GET requests @@ -468,16 +425,12 @@ validate_request_line(Config) when is_list(Config) -> NewForbiddenUri1 = "http://127.0.0.1:8888/../home/ingela/test.html", {error, {bad_request, {forbidden, NewForbiddenUri1}}} = - httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1"), - - ok. + httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1"). %%------------------------------------------------------------------------- -check_content_length_encoding(doc) -> - ["Test http_request:headers/2. Check that the content-length is" - " encoded even when it is zero." ]; -check_content_length_encoding(suite) -> - []; +check_content_length_encoding() -> + [{doc, "Test http_request:headers/2. Check that the content-length is" + " encoded even when it is zero."}]. check_content_length_encoding(Config) when is_list(Config) -> %% Check that the content-length is preserved. @@ -486,16 +439,12 @@ check_content_length_encoding(Config) when is_list(Config) -> true = (string:str(Header1, "content-length: 123\r\n") > 0), %% Check that content-length=0 is handled correctly. Header2 = http_request:http_headers(#http_request_h{'content-length'="0"}), - true = (string:str(Header2, "content-length: 0\r\n") > 0), - - ok. + true = (string:str(Header2, "content-length: 0\r\n") > 0). %%------------------------------------------------------------------------- -esi_parse_headers(doc) -> - ["Test httpd_esi:*. All header values are received in the same" - " erlang message."]; -esi_parse_headers(suite) -> - []; +esi_parse_headers() -> + [{doc, "Test httpd_esi:*. All header values are received in the same" + " erlang message."}]. esi_parse_headers(Config) when is_list(Config) -> ESIResult = "content-type:text/html\r\ndate:Thu, 28 Oct 2004 07:57:43 " @@ -522,16 +471,14 @@ esi_parse_headers(Config) when is_list(Config) -> httpd_esi:handle_headers(Headers2), {proceed,"/foo/bar.html"} = - httpd_esi:handle_headers("location:/foo/bar.html\r\n"), - ok. + httpd_esi:handle_headers("location:/foo/bar.html\r\n"). %%-------------------------------------------------------------------- -cgi_parse_headers(doc) -> - ["Test httpd_cgi:*. This test case will simulate that the " +cgi_parse_headers() -> + [{doc, "Test httpd_cgi:*. This test case will simulate that the " "message will be recived a little at the time on a socket and the " - "package may be broken up into smaller parts at arbitrary point."]; -cgi_parse_headers(suite) -> - []; + "package may be broken up into smaller parts at arbitrary point."}]. + cgi_parse_headers(Config) when is_list(Config) -> CGIResult = ["content-type:text", "/html\ndate:Thu, 28 Oct 2004 07:57:43 " @@ -567,26 +514,18 @@ cgi_parse_headers(Config) when is_list(Config) -> {ok,[{"content-type","text/html"}, {"connection","close"}, {"content-language","en"}, - {"age","4711"}], {200,"ok"}} = httpd_cgi:handle_headers(Headers3), - - ok. - + {"age","4711"}], {200,"ok"}} = httpd_cgi:handle_headers(Headers3). %%------------------------------------------------------------------------- -is_absolut_uri(doc) -> - ["Test http_request:is_absolut_uri/1."]; -is_absolut_uri(suite) -> - []; +is_absolut_uri() -> + [{doc, "Test http_request:is_absolut_uri/1."}]. is_absolut_uri(Config) when is_list(Config) -> true = http_request:is_absolut_uri("http://www.erlang.org"), true = http_request:is_absolut_uri("https://www.erlang.org"), false = http_request:is_absolut_uri("index.html"). - %%------------------------------------------------------------------------- -convert_netscapecookie_date(doc) -> - ["Test http_util:convert_netscapecookie_date/1."]; -convert_netscapecookie_date(suite) -> - []; +convert_netscapecookie_date() -> + [{doc, "Test http_util:convert_netscapecookie_date/1."}]. convert_netscapecookie_date(Config) when is_list(Config) -> {{2006,1,6},{8,59,38}} = http_util:convert_netscapecookie_date("Mon, 06-Jan-2006 08:59:38 GMT"), @@ -619,9 +558,7 @@ convert_netscapecookie_date(Config) when is_list(Config) -> {{2006,12,12},{8,59,38}} = http_util:convert_netscapecookie_date("Sun 12-Dec-06 08:59:38 GMT"), {{2036,1,1},{8,0,1}} = - http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT"), - ok. - + http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT"). %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- -- cgit v1.2.3 From 1545eae1470c0183bacbf1786d6f1c0366138157 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 5 Nov 2015 09:53:26 +0100 Subject: inets: Improve max header size handling The chunked length header should be checked as well as headers present in the chunk trailer part, ignored extensions are counted as header bytes. Also the decode trailer function will stop as soon as the header size is exceed, when that happens. --- lib/inets/src/http_lib/http_chunk.erl | 163 ++++++++++++++++++---------------- lib/inets/test/http_format_SUITE.erl | 67 ++++++++++++-- 2 files changed, 147 insertions(+), 83 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl index c17ff6cce5..2f8476a49d 100644 --- a/lib/inets/src/http_lib/http_chunk.erl +++ b/lib/inets/src/http_lib/http_chunk.erl @@ -57,7 +57,7 @@ %%------------------------------------------------------------------------- decode(ChunkedBody, MaxBodySize, MaxHeaderSize) -> %% Note decode_size will call decode_data. - decode_size([ChunkedBody, <<>>, [], + decode_size([ChunkedBody, <<>>, [], 0, {MaxBodySize, <<>>, 0, MaxHeaderSize}]). %%------------------------------------------------------------------------- @@ -120,67 +120,80 @@ handle_headers(ResponseHeaderRecord = #http_response_h{}, ChunkedHeaders) -> %% Functions that may be returned during the decoding process %% if the input data is incompleate. -decode_size([Bin, Rest, HexList, Info]) -> - decode_size(<>, HexList, Info). +decode_size([Bin, Rest, HexList, AccSize, Info]) -> + decode_size(<>, HexList, AccSize, Info). -ignore_extensions([Bin, Rest, NextFunction]) -> - ignore_extensions(<>, NextFunction). +ignore_extensions([Bin, Rest, RemainingSize, TotalMaxHeaderSize, NextFunction]) -> + ignore_extensions(<>, RemainingSize, TotalMaxHeaderSize, NextFunction). decode_data([Bin, ChunkSize, TotalChunk, Info]) -> decode_data(ChunkSize, <>, Info). -decode_trailer([Bin, Rest, Header, Headers, MaxHeaderSize, Body, - BodyLength]) -> +decode_trailer([Bin, Rest, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]) -> decode_trailer(<>, - Header, Headers, MaxHeaderSize, Body, BodyLength). + Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize). %%%======================================================================== %%% Internal functions %%%======================================================================== -decode_size(<<>>, HexList, Info) -> - {?MODULE, decode_size, [<<>>, HexList, Info]}; -decode_size(Data = <>, HexList, +decode_size(_, _, AccHeaderSize, {_,_,_, MaxHeaderSize}) when + AccHeaderSize > MaxHeaderSize -> + throw({error, {header_too_long, {max, MaxHeaderSize}}}); + +decode_size(<<>>, HexList, AccHeaderSize, Info) -> + {?MODULE, decode_size, [<<>>, HexList, AccHeaderSize, Info]}; +decode_size(Data = <>, HexList, AccHeaderSize, {MaxBodySize, Body, AccLength, MaxHeaderSize}) -> try http_util:hexlist_to_integer(lists:reverse(HexList)) of 0 -> % Last chunk, there was no data - ignore_extensions(Data, {?MODULE, decode_trailer, - [<<>>, [],[], MaxHeaderSize, - Body, - integer_to_list(AccLength)]}); + ignore_extensions(Data, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize, + {?MODULE, decode_trailer, + [<<>>, [],[], + Body, + integer_to_list(AccLength)]}); ChunkSize -> %% Note decode_data may call decode_size again if there %% is more than one chunk, hence here is where the last parameter %% to this function comes in. decode_data(ChunkSize, ChunkRest, {MaxBodySize, Body, - ChunkSize + AccLength , + ChunkSize + AccLength, MaxHeaderSize}) catch _:_ -> - throw({error, {chunk_size, HexList}}) + throw({error, {chunk_size, lists:reverse(HexList)}}) end; -decode_size(<<";", Rest/binary>>, HexList, Info) -> +decode_size(<<";", Rest/binary>>, HexList, AccHeaderSize, {_,_,_, MaxHeaderSize} = Info) -> %% Note ignore_extensions will call decode_size/1 again when %% it ignored all extensions. - ignore_extensions(Rest, {?MODULE, decode_size, [<<>>, HexList, Info]}); -decode_size(<> = Data, HexList, Info) -> - {?MODULE, decode_size, [Data, HexList, Info]}; -decode_size(<>, HexList, Info) -> - decode_size(Rest, [Octet | HexList], Info). + ignore_extensions(Rest, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize, + {?MODULE, decode_size, [<<>>, HexList, AccHeaderSize, Info]}); +decode_size(<> = Data, HexList, AccHeaderSize, Info) -> + {?MODULE, decode_size, [Data, HexList, AccHeaderSize, Info]}; +decode_size(<>, HexList, AccHeaderSize, Info) -> + decode_size(Rest, [Octet | HexList], AccHeaderSize + 1, Info). %% "All applications MUST ignore chunk-extension extensions they %% do not understand.", see RFC 2616 Section 3.6.1 We don't %% understand any extension... -ignore_extensions(<<>>, NextFunction) -> - {?MODULE, ignore_extensions, [<<>>, NextFunction]}; -ignore_extensions(Data = <>, +ignore_extensions(_, 0, TotalMaxHeaderSize, _) -> + throw({error, {header_too_long, {max, TotalMaxHeaderSize}}}); +ignore_extensions(<<>>, RemainingSize, TotalMaxHeaderSize, NextFunction) -> + {?MODULE, ignore_extensions, [<<>>, RemainingSize, TotalMaxHeaderSize, NextFunction]}; +ignore_extensions(Data = <>, RemainingSize, TotalMaxHeaderSize, {Module, Function, Args}) -> - Module:Function([Data | Args]); -ignore_extensions(<> = Data, NextFunction) -> - {?MODULE, ignore_extensions, [Data, NextFunction]}; -ignore_extensions(<<_Octet, Rest/binary>>, NextFunction) -> - ignore_extensions(Rest, NextFunction). + case Function of + decode_trailer -> + Module:Function([Data | Args ++ [RemainingSize, TotalMaxHeaderSize]]); + _ -> + Module:Function([Data | Args]) + end; +ignore_extensions(<> = Data, RemainingSize, TotalMaxHeaderSize, NextFunction) -> + {?MODULE, ignore_extensions, [Data, RemainingSize, TotalMaxHeaderSize, NextFunction]}; +ignore_extensions(<<_Octet, Rest/binary>>, RemainingSize, TotalMaxHeaderSize, NextFunction) -> + ignore_extensions(Rest, remaing_size(RemainingSize, 1), TotalMaxHeaderSize, NextFunction). decode_data(ChunkSize, TotalChunk, Info = {MaxBodySize, BodySoFar, AccLength, MaxHeaderSize}) @@ -192,83 +205,81 @@ decode_data(ChunkSize, TotalChunk, %% once it ignored all extensions. {?MODULE, ignore_extensions, [<<>>, - {?MODULE, decode_trailer, [<<>>, [],[], MaxHeaderSize, + {?MODULE, decode_trailer, [<<>>, [],[], <>, integer_to_list(AccLength)]}]}; <> -> %% Note ignore_extensions will call decode_trailer/1 %% once it ignored all extensions. - ignore_extensions(Rest, {?MODULE, decode_trailer, - [<<>>, [],[], MaxHeaderSize, + ignore_extensions(Rest, MaxHeaderSize, MaxHeaderSize, + {?MODULE, decode_trailer, + [<<>>, [],[], <>, integer_to_list(AccLength)]}); <> -> - {?MODULE, decode_trailer, [<>, [],[], MaxHeaderSize, + {?MODULE, decode_trailer, [<>, [],[], <>, - integer_to_list(AccLength)]}; + integer_to_list(AccLength), MaxHeaderSize, MaxHeaderSize]}; <> -> - decode_trailer(<>, [],[], MaxHeaderSize, + decode_trailer(<>, [],[], <>, - integer_to_list(AccLength)); - %% There are more chunks, so here we go agin... + integer_to_list(AccLength), MaxHeaderSize, MaxHeaderSize); + %% There are more chunks, so here we go again... <> -> NewBody = <>, - {?MODULE, decode_size, [<<>>, [], {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}; + {?MODULE, decode_size, [<<>>, [], 0, {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}; <> when (AccLength < MaxBodySize) or (MaxBodySize == nolimit) -> - decode_size(Rest, [], + decode_size(Rest, [], 0, {MaxBodySize, <>, AccLength, MaxHeaderSize}); <<_:ChunkSize/binary, ?CR, ?LF, _/binary>> -> - throw({error, body_too_big}); + throw({error, {body_too_big, {max, MaxBodySize}}}); _ -> {?MODULE, decode_data, [ChunkSize, TotalChunk, Info]} end; decode_data(ChunkSize, TotalChunk, Info) -> {?MODULE, decode_data, [ChunkSize, TotalChunk, Info]}. -decode_trailer(<<>>, Header, Headers, MaxHeaderSize, Body, BodyLength) -> - {?MODULE, decode_trailer, [<<>>, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; - +decode_trailer(_,_,_,_,_, 0, TotalMaxHeaderSize) -> + throw({error, {header_too_long, {max, TotalMaxHeaderSize}}}); +decode_trailer(<<>>, Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [<<>>, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; %% Note: If Bin is not empty it is part of a pipelined request/response. -decode_trailer(<>, [], [], _, Body, BodyLength) -> +decode_trailer(<>, [], [], Body, BodyLength, _, _) -> {ok, {["content-length:" ++ BodyLength], <>}}; decode_trailer(<>, - Header, Headers, MaxHeaderSize, Body, BodyLength) -> + Header, Headers, Body, BodyLength, _, _) -> NewHeaders = case Header of [] -> Headers; _ -> [lists:reverse(Header) | Headers] end, - Length = length(NewHeaders), - case Length > MaxHeaderSize of - true -> - throw({error, {header_too_long, MaxHeaderSize, - MaxHeaderSize-Length}}); - false -> - {ok, {["content-length:" ++ BodyLength | NewHeaders], - <>}} - end; -decode_trailer(<> = Data, Header, Headers, MaxHeaderSize, - Body, BodyLength) -> - {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; -decode_trailer(<> = Data, Header, Headers, MaxHeaderSize, - Body, BodyLength) -> - {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; -decode_trailer(<> = Data, Header, Headers, MaxHeaderSize, - Body, BodyLength) -> - {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; -decode_trailer(<>, Header, Headers, - MaxHeaderSize, Body, BodyLength) -> + {ok, {["content-length:" ++ BodyLength | NewHeaders], + <>}}; +decode_trailer(<> = Data, Header, Headers, + Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [Data, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; +decode_trailer(<> = Data, Header, Headers, + Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [Data, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; +decode_trailer(<> = Data, Header, Headers, + Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [Data, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; +decode_trailer(<>, Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> decode_trailer(Rest, [], [lists:reverse(Header) | Headers], - MaxHeaderSize, Body, BodyLength); + Body, BodyLength, RemainingSize, TotalMaxHeaderSize); +decode_trailer(<>, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize) -> + decode_trailer(Rest, [Octet | Header], Headers, + Body, BodyLength, RemainingSize - 1, TotalMaxHeaderSize). -decode_trailer(<>, Header, Headers, MaxHeaderSize, Body, - BodyLength) -> - decode_trailer(Rest, [Octet | Header], Headers, MaxHeaderSize, - Body, BodyLength). +remaing_size(nolimit, _) -> + nolimit; +remaing_size(Total, Consumed) -> + Total - Consumed. diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl index 83ffe259b3..a927adc75e 100644 --- a/lib/inets/test/http_format_SUITE.erl +++ b/lib/inets/test/http_format_SUITE.erl @@ -38,7 +38,7 @@ groups() -> [chunk_decode, chunk_encode, chunk_extensions_otp_6005, chunk_decode_otp_6264, chunk_decode_empty_chunk_otp_6511, - chunk_decode_trailer]}]. + chunk_decode_trailer, chunk_max_headersize, chunk_max_bodysize, chunk_not_hex]}]. init_per_suite(Config) -> Config. @@ -91,9 +91,7 @@ chunk_decode(Config) when is_list(Config) -> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, Body} = parse(Module, Function, Args, tl(NewChunkedBody)), - "1234567890HEJ!" = binary_to_list(Body), - - ok. + "1234567890HEJ!" = binary_to_list(Body). %%------------------------------------------------------------------------- chunk_extensions_otp_6005() -> @@ -226,9 +224,64 @@ chunk_encode(Config) when is_list(Config) -> <<54, ?CR, ?LF, 102,111,111,98,97,114, ?CR, ?LF>> = http_chunk:encode(list_to_binary("foobar")), ["6", ?CR, ?LF,"foobar", ?CR, ?LF] = http_chunk:encode("foobar"), - <<$0, ?CR, ?LF, ?CR, ?LF >> = http_chunk:encode_last(), - ok. - + <<$0, ?CR, ?LF, ?CR, ?LF >> = http_chunk:encode_last(). +%%------------------------------------------------------------------------- +chunk_max_headersize() -> + [{doc, "Test max header limit"}]. +chunk_max_headersize(Config) when is_list(Config) -> + ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + + {ok, {_, _}} = + http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), + + %% Too long in length header + {error,{header_too_long, {max, 1}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, 1)), + + %% Too long in extension field + {error,{header_too_long, {max, 10}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, 10)), + + %% Too long in trailer + {error,{header_too_long, {max, 30}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, 30)). +%%------------------------------------------------------------------------- +chunk_not_hex() -> + [{doc, "Test bad chunked length header"}]. +chunk_not_hex(Config) when is_list(Config) -> + ChunkedBody = "åäö; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + {error,{chunk_size, "åäö"}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE)). +%%------------------------------------------------------------------------- +chunk_max_bodysize() -> + [{doc, "Test max body limit"}]. +chunk_max_bodysize(Config) when is_list(Config) -> + ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + {ok, {_, _}} = + http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), + + %% Too long body + {error,{body_too_big, {max, 10}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + 10, ?HTTP_MAX_HEADER_SIZE)). %%------------------------------------------------------------------------- http_response() -> -- cgit v1.2.3 From f05f7ae5e8ea4b19be5fa49681ad6efb01daae6d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 9 Nov 2015 15:08:35 +0100 Subject: inets: Remove debug macros that mimic call trace --- lib/inets/src/http_lib/http_transport.erl | 44 ++++++------------------------- 1 file changed, 8 insertions(+), 36 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index 719dc4c425..484e07cd84 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -40,12 +40,6 @@ -include_lib("inets/src/inets_app/inets_internal.hrl"). -include("http_internal.hrl"). --define(SERVICE, httpl). --define(hlri(Label, Content), ?report_important(Label, ?SERVICE, Content)). --define(hlrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)). --define(hlrd(Label, Content), ?report_debug(Label, ?SERVICE, Content)). --define(hlrt(Label, Content), ?report_trace(Label, ?SERVICE, Content)). - %%%========================================================================= %%% Internal application API @@ -107,8 +101,6 @@ connect(SocketType, Address, Opts) -> connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout) when is_list(Opts0) -> Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0], - ?hlrt("connect using gen_tcp", - [{host, Host}, {port, Port}, {opts, Opts}, {timeout, Timeout}]), try gen_tcp:connect(Host, Port, Opts, Timeout) of {ok, _} = OK -> OK; @@ -127,11 +119,6 @@ connect({ssl, SslConfig}, Address, Opts, Timeout) -> connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) -> Opts = [binary, {active, false}, {ssl_imp, new} | Opts0] ++ SslConfig, - ?hlrt("connect using essl", - [{host, Host}, - {port, Port}, - {ssl_config, SslConfig}, - {timeout, Timeout}]), case (catch ssl:connect(Host, Port, Opts, Timeout)) of {'EXIT', Reason} -> {error, {eoptions, Reason}}; @@ -156,29 +143,23 @@ connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) -> %% reason for this to enable a HTTP-server not running as root to use %% port 80. %%------------------------------------------------------------------------- -listen(ip_comm = _SocketType, Addr, Port, Fd, IpFamily) -> - listen_ip_comm(Addr, Port, Fd, IpFamily); - +listen(ip_comm, Addr, Port, Fd, IpFamily) -> + listen_ip_comm(Addr, Port, [], Fd, IpFamily); + +listen({ip_comm, SockOpts}, Addr, Port, Fd, IpFamily) -> + listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily); + listen({essl, SSLConfig}, Addr, Port, Fd, IpFamily) -> listen_ssl(Addr, Port, Fd, SSLConfig, IpFamily, []). -listen(ip_comm = _SocketType, Addr, Port, IpFamily) -> - listen_ip_comm(Addr, Port, undefined, IpFamily); +listen(ip_comm, Addr, Port, IpFamily) -> + listen_ip_comm(Addr, Port, [], undefined, IpFamily); %% Wrapper for backaward compatibillity listen({ssl, SSLConfig}, Addr, Port, IpFamily) -> - ?hlrt("listen (wrapper)", - [{addr, Addr}, - {port, Port}, - {ssl_config, SSLConfig}]), listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port, IpFamily); - listen({essl, SSLConfig}, Addr, Port, IpFamily) -> - ?hlrt("listen (essl)", - [{addr, Addr}, - {port, Port}, - {ssl_config, SSLConfig}]), {SSLConfig2, ExtraOpts} = case proplists:get_value(log_alert, SSLConfig, undefined) of undefined -> {SSLConfig, []}; @@ -325,7 +306,6 @@ controlling_process({essl, _}, Socket, NewOwner) -> %% gen_tcp or ssl. %%------------------------------------------------------------------------- setopts(ip_comm, Socket, Options) -> - ?hlrt("ip_comm setopts", [{socket, Socket}, {options, Options}]), inet:setopts(Socket, Options); %% Wrapper for backaward compatibillity @@ -351,7 +331,6 @@ getopts(SocketType, Socket) -> getopts(SocketType, Socket, Opts). getopts(ip_comm, Socket, Options) -> - ?hlrt("ip_comm getopts", [{socket, Socket}, {options, Options}]), case inet:getopts(Socket, Options) of {ok, SocketOpts} -> SocketOpts; @@ -364,7 +343,6 @@ getopts({ssl, SSLConfig}, Socket, Options) -> getopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options); getopts({essl, _}, Socket, Options) -> - ?hlrt("essl getopts", [{socket, Socket}, {options, Options}]), getopts_ssl(Socket, Options). getopts_ssl(Socket, Options) -> @@ -384,7 +362,6 @@ getopts_ssl(Socket, Options) -> %% Description: Gets the socket stats values for the socket %%------------------------------------------------------------------------- getstat(ip_comm = _SocketType, Socket) -> - ?hlrt("ip_comm getstat", [{socket, Socket}]), case inet:getstat(Socket) of {ok, Stats} -> Stats; @@ -555,22 +532,17 @@ sock_opts(Opts) -> %% -- negotiate -- negotiate(ip_comm,_,_) -> - ?hlrt("negotiate(ip_comm)", []), ok; negotiate({ssl, SSLConfig}, Socket, Timeout) -> - ?hlrt("negotiate(ssl)", []), negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout); negotiate({essl, _}, Socket, Timeout) -> - ?hlrt("negotiate(essl)", []), negotiate_ssl(Socket, Timeout). negotiate_ssl(Socket, Timeout) -> - ?hlrt("negotiate_ssl", [{socket, Socket}, {timeout, Timeout}]), case ssl:ssl_accept(Socket, Timeout) of ok -> ok; {error, Reason} -> - ?hlrd("negotiate_ssl - accept failed", [{reason, Reason}]), %% Look for "valid" error reasons ValidReasons = [timeout, econnreset, esslaccept, esslerrssl], case lists:member(Reason, ValidReasons) of -- cgit v1.2.3 From 4b7be97512d6fc62b337e810f697a6bb0db1773c Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 9 Nov 2015 15:09:40 +0100 Subject: inets: httpd - Add possibility to specify socket options for HTTP Was already possible for HTTPS. Also remove use of legacy option inet6fb4. IPv6 standard moved away from beeing able to fallback to IPv4 so this option makes little sense, will use inet (Ipv4) as default instead of inet6fb4. --- lib/inets/doc/src/httpd.xml | 13 ++-- lib/inets/src/http_lib/http_transport.erl | 116 ++++++++++-------------------- lib/inets/src/http_server/httpd_conf.erl | 101 +++++++++++++------------- lib/inets/src/http_server/httpd_sup.erl | 4 +- lib/inets/src/http_server/httpd_util.erl | 12 +--- lib/inets/test/httpd_SUITE.erl | 24 ++++--- 6 files changed, 115 insertions(+), 155 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml index 2a4aea41c2..0fc3cb1ce7 100644 --- a/lib/inets/doc/src/httpd.xml +++ b/lib/inets/doc/src/httpd.xml @@ -177,21 +177,22 @@ - {socket_type, ip_comm | {essl, Config::proplist()}} + {socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}} +

For ip_comm configuration options, see + gen_tcp:listen/2, some options + that are used internally by httpd can not be set.

For SSL configuration options, see ssl:listen/2.

Default is ip_comm.

- {ipfamily, inet | inet6 | inet6fb4} + {ipfamily, inet | inet6} -

This option is only used when option - socket_type has value ip_comm.

-

Default is inet6fb4.

+

Default is inet, legacy option inet6fb4 no longer makes sense and will be translated + to inet.

- {minimum_bytes_per_second, integer()} diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index 484e07cd84..e3d7382043 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -53,7 +53,8 @@ %%------------------------------------------------------------------------- start(ip_comm) -> do_start_ip_comm(); - +start({ip_comm, _}) -> + do_start_ip_comm(); %% This is just for backward compatibillity start({ssl, _}) -> do_start_ssl(); @@ -97,10 +98,8 @@ do_start_ssl() -> connect(SocketType, Address, Opts) -> connect(SocketType, Address, Opts, infinity). - -connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout) - when is_list(Opts0) -> - Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0], +connect(ip_comm, {Host, Port}, Opts0, Timeout) -> + Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0 ], try gen_tcp:connect(Host, Port, Opts, Timeout) of {ok, _} = OK -> OK; @@ -168,83 +167,30 @@ listen({essl, SSLConfig}, Addr, Port, IpFamily) -> end, listen_ssl(Addr, Port, undefined, SSLConfig2, IpFamily, ExtraOpts). -listen_ip_comm(Addr, Port, Fd, IpFamily) -> - case (catch do_listen_ip_comm(Addr, Port, Fd, IpFamily)) of +listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily) -> + case (catch do_listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily)) of {'EXIT', Reason} -> {error, {exit, Reason}}; Else -> Else end. -do_listen_ip_comm(Addr, Port, Fd, IpFamily) -> - {NewPort, Opts} = get_socket_info(Addr, Port, Fd), - case IpFamily of - inet6fb4 -> - Opts2 = [inet6 | Opts], - ?hlrt("try ipv6 listen", [{port, NewPort}, {opts, Opts2}]), - case (catch gen_tcp:listen(NewPort, Opts2)) of - {error, Reason} when ((Reason =:= nxdomain) orelse - (Reason =:= eafnosupport)) -> - Opts3 = [inet | Opts], - ?hlrt("ipv6 listen failed - try ipv4 instead", - [{reason, Reason}, {port, NewPort}, {opts, Opts3}]), - gen_tcp:listen(NewPort, Opts3); - - %% This is when a given hostname has resolved to a - %% IPv4-address. The inet6-option together with a - %% {ip, IPv4} option results in badarg - {'EXIT', Reason} -> - Opts3 = [inet | Opts], - ?hlrt("ipv6 listen exit - try ipv4 instead", - [{reason, Reason}, {port, NewPort}, {opts, Opts3}]), - gen_tcp:listen(NewPort, Opts3); - - Other -> - ?hlrt("ipv6 listen done", [{other, Other}]), - Other - end; - _ -> - Opts2 = [IpFamily | Opts], - ?hlrt("listen", [{port, NewPort}, {opts, Opts2}]), - gen_tcp:listen(NewPort, Opts2) - end. +do_listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily) -> + Backlog = proplists:get_value(backlog, SockOpts, 128), + {NewPort, Opts} = get_socket_info(Addr, Port, Fd, + [{backlog, Backlog}, {reuseaddr, true} | SockOpts]), + Opts2 = [IpFamily | Opts], + gen_tcp:listen(NewPort, Opts2). listen_ssl(Addr, Port, Fd, Opts0, IpFamily, ExtraOpts) -> - {NewPort, SockOpt} = get_socket_info(Addr, Port, Fd), + Backlog = proplists:get_value(backlog, Opts0, 128), + {NewPort, SockOpt} = get_socket_info(Addr, Port, Fd, + [{backlog, Backlog}, {reuseaddr, true}]), Opts = SockOpt ++ Opts0, - case IpFamily of - inet6fb4 -> - Opts2 = [inet6 | Opts] ++ ExtraOpts, - ?hlrt("try ipv6 listen", [{opts, Opts2}]), - case (catch ssl:listen(Port, Opts2)) of - {error, Reason} when ((Reason =:= nxdomain) orelse - (Reason =:= eafnosupport)) -> - Opts3 = [inet | Opts] ++ ExtraOpts, - ?hlrt("ipv6 listen failed - try ipv4 instead", - [{reason, Reason}, {opts, Opts3}]), - ssl:listen(NewPort, Opts3); - - {'EXIT', Reason} -> - Opts3 = [inet | Opts] ++ ExtraOpts, - ?hlrt("ipv6 listen exit - try ipv4 instead", - [{reason, Reason}, {opts, Opts3}]), - ssl:listen(NewPort, Opts3); - - Other -> - ?hlrt("ipv6 listen done", [{other, Other}]), - Other - end; - - _ -> - Opts2 = [IpFamily | Opts], - ?hlrt("listen", [{opts, Opts2}]), - ssl:listen(NewPort, Opts2 ++ ExtraOpts) - end. + Opts2 = [IpFamily | Opts], + ssl:listen(NewPort, Opts2 ++ ExtraOpts). - - -get_socket_info(Addr, Port, Fd) -> - BaseOpts = [{backlog, 128}, {reuseaddr, true}], +get_socket_info(Addr, Port, Fd, BaseOpts) -> %% The presence of a file descriptor takes precedence case Fd of undefined -> @@ -269,6 +215,8 @@ accept(SocketType, ListenSocket) -> accept(ip_comm, ListenSocket, Timeout) -> gen_tcp:accept(ListenSocket, Timeout); +accept({ip_comm, _}, ListenSocket, Timeout) -> + gen_tcp:accept(ListenSocket, Timeout); %% Wrapper for backaward compatibillity accept({ssl, SSLConfig}, ListenSocket, Timeout) -> @@ -288,6 +236,8 @@ accept({essl, _SSLConfig}, ListenSocket, Timeout) -> %%------------------------------------------------------------------------- controlling_process(ip_comm, Socket, NewOwner) -> gen_tcp:controlling_process(Socket, NewOwner); +controlling_process({ip_comm, _}, Socket, NewOwner) -> + gen_tcp:controlling_process(Socket, NewOwner); %% Wrapper for backaward compatibillity controlling_process({ssl, SSLConfig}, Socket, NewOwner) -> @@ -307,16 +257,15 @@ controlling_process({essl, _}, Socket, NewOwner) -> %%------------------------------------------------------------------------- setopts(ip_comm, Socket, Options) -> inet:setopts(Socket, Options); +setopts({ip_comm, _}, Socket, Options) -> + inet:setopts(Socket, Options); %% Wrapper for backaward compatibillity setopts({ssl, SSLConfig}, Socket, Options) -> setopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options); setopts({essl, _}, Socket, Options) -> - ?hlrt("[e]ssl setopts", [{socket, Socket}, {options, Options}]), - Reason = (catch ssl:setopts(Socket, Options)), - ?hlrt("[e]ssl setopts result", [{reason, Reason}]), - Reason. + (catch ssl:setopts(Socket, Options)). %%------------------------------------------------------------------------- @@ -330,6 +279,9 @@ getopts(SocketType, Socket) -> Opts = [packet, packet_size, recbuf, sndbuf, priority, tos, send_timeout], getopts(SocketType, Socket, Opts). +getopts({ip_comm, _}, Socket, Options) -> + getopts(ip_comm, Socket, Options); + getopts(ip_comm, Socket, Options) -> case inet:getopts(Socket, Options) of {ok, SocketOpts} -> @@ -386,6 +338,8 @@ getstat({essl, _} = _SocketType, _Socket) -> %%------------------------------------------------------------------------- send(ip_comm, Socket, Message) -> gen_tcp:send(Socket, Message); +send({ip_comm, _}, Socket, Message) -> + gen_tcp:send(Socket, Message); %% Wrapper for backaward compatibillity send({ssl, SSLConfig}, Socket, Message) -> @@ -394,7 +348,6 @@ send({ssl, SSLConfig}, Socket, Message) -> send({essl, _}, Socket, Message) -> ssl:send(Socket, Message). - %%------------------------------------------------------------------------- %% close(SocketType, Socket) -> ok | {error, Reason} %% SocketType = ip_comm | {ssl, _} @@ -404,6 +357,8 @@ send({essl, _}, Socket, Message) -> %%------------------------------------------------------------------------- close(ip_comm, Socket) -> gen_tcp:close(Socket); +close({ip_comm, []}, Socket) -> + gen_tcp:close(Socket); %% Wrapper for backaward compatibillity close({ssl, SSLConfig}, Socket) -> @@ -425,6 +380,8 @@ close({essl, _}, Socket) -> %%------------------------------------------------------------------------- peername(ip_comm, Socket) -> do_peername(inet:peername(Socket)); +peername({ip_comm, _}, Socket) -> + do_peername(inet:peername(Socket)); %% Wrapper for backaward compatibillity peername({ssl, SSLConfig}, Socket) -> @@ -457,7 +414,8 @@ do_peername({error, _}) -> %%------------------------------------------------------------------------- sockname(ip_comm, Socket) -> do_sockname(inet:sockname(Socket)); - +sockname({ip_comm, _}, Socket) -> + do_sockname(inet:sockname(Socket)); %% Wrapper for backaward compatibillity sockname({ssl, SSLConfig}, Socket) -> sockname({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket); @@ -533,6 +491,8 @@ sock_opts(Opts) -> %% -- negotiate -- negotiate(ip_comm,_,_) -> ok; +negotiate({ip_comm, _},_,_) -> + ok; negotiate({ssl, SSLConfig}, Socket, Timeout) -> negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout); negotiate({essl, _}, Socket, Timeout) -> diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl index 7d31989244..62e8a95b19 100644 --- a/lib/inets/src/http_server/httpd_conf.erl +++ b/lib/inets/src/http_server/httpd_conf.erl @@ -156,7 +156,7 @@ load("BindAddress " ++ Address0, []) -> case string:tokens(Address0, [$|]) of [Address1] -> ?hdrv("load BindAddress", [{address1, Address1}]), - {clean_address(Address1), inet6fb4}; + {clean_address(Address1), inet}; [Address1, IpFamilyStr] -> ?hdrv("load BindAddress", [{address1, Address1}, @@ -353,14 +353,21 @@ clean_address(Addr) -> make_ipfamily(IpFamilyStr) -> - IpFamily = list_to_atom(IpFamilyStr), - case lists:member(IpFamily, [inet, inet6, inet6fb4]) of - true -> - IpFamily; - false -> - throw({error, {bad_ipfamily, IpFamilyStr}}) - end. - + validate_ipfamily(list_to_atom(IpFamilyStr)). + +validate_ipfamily(inet) -> + inet; +validate_ipfamily(inet6) -> + inet6; +%% Backwards compatibility wrapper, +%% fallback to the default, IPV4, +%% as it will most proably work. +%% IPv6 standard moved away from +%% beeing able to fallback to ipv4 +validate_ipfamily(inet6fb4) -> + inet; +validate_ipfamily(IpFamilyStr) -> + throw({error, {bad_ipfamily, IpFamilyStr}}). %% %% load_mime_types/1 -> {ok, MimeTypes} | {error, Reason} @@ -393,20 +400,16 @@ validate_properties2(Properties) -> undefined -> case proplists:get_value(sock_type, Properties, ip_comm) of ip_comm -> - case proplists:get_value(ipfamily, Properties) of - undefined -> - [{bind_address, any}, - {ipfamily, inet6fb4} | Properties]; - _ -> - [{bind_address, any} | Properties] - end; + add_inet_defaults(Properties); + {ip_comm, _} -> + add_inet_defaults(Properties); _ -> [{bind_address, any} | Properties] end; any -> Properties; Address0 -> - IpFamily = proplists:get_value(ipfamily, Properties, inet6fb4), + IpFamily = proplists:get_value(ipfamily, Properties, inet), case httpd_util:ip_address(Address0, IpFamily) of {ok, Address} -> Properties1 = proplists:delete(bind_address, Properties), @@ -418,6 +421,16 @@ validate_properties2(Properties) -> throw(Error) end end. + +add_inet_defaults(Properties) -> + case proplists:get_value(ipfamily, Properties) of + undefined -> + [{bind_address, any}, + {ipfamily, inet} | Properties]; + _ -> + [{bind_address, any} | Properties] + end. + check_minimum_bytes_per_second(Properties) -> case proplists:get_value(minimum_bytes_per_second, Properties, false) of false -> @@ -487,12 +500,11 @@ validate_config_params([{server_tokens, Value} | _]) -> validate_config_params([{socket_type, ip_comm} | Rest]) -> validate_config_params(Rest); -validate_config_params([{socket_type, Value} | Rest]) - when Value == ssl; Value == essl -> - validate_config_params(Rest); - -validate_config_params([{socket_type, {Value, _}} | Rest]) - when Value == essl orelse Value == ssl -> +validate_config_params([{socket_type, {Value, Opts}} | Rest]) when Value == ip_comm; + Value == ssl; + Value == essl -> + %% Make sure not to set socket values used internaly + validate_config_params(Opts), validate_config_params(Rest); validate_config_params([{socket_type, Value} | _]) -> @@ -622,21 +634,32 @@ validate_config_params([{disable_chunked_transfer_encoding_send, Value} | validate_config_params([{disable_chunked_transfer_encoding_send, Value} | _ ]) -> throw({disable_chunked_transfer_encoding_send, Value}); +validate_config_params([{Name, _} = Opt | _]) when Name == packet; + Name == mode; + Name == active; + Name == reuseaddr -> + throw({internaly_handled_opt_can_not_be_set, Opt}); validate_config_params([_| Rest]) -> validate_config_params(Rest). -%% It is actually pointless to check bind_address in this way since -%% we need ipfamily to do it properly... is_bind_address(any) -> true; is_bind_address(Value) -> - case httpd_util:ip_address(Value, inet6fb4) of + case is_bind_address(Value, inet) of + false -> + is_bind_address(Value, inet6); + True -> + True + end. + +is_bind_address(Value, IpFamily) -> + case httpd_util:ip_address(Value, IpFamily) of {ok, _} -> true; _ -> false end. - + store(ConfigList0) -> ?hdrd("store", []), try validate_config_params(ConfigList0) of @@ -776,28 +799,6 @@ remove(ConfigDB) -> ets:delete(ConfigDB), ok. -%% config(ConfigDB) -> -%% case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of -%% ssl -> -%% case ssl_certificate_file(ConfigDB) of -%% undefined -> -%% {error, -%% "Directive SSLCertificateFile " -%% "not found in the config file"}; -%% SSLCertificateFile -> -%% {ssl, -%% SSLCertificateFile++ -%% ssl_certificate_key_file(ConfigDB)++ -%% ssl_verify_client(ConfigDB)++ -%% ssl_ciphers(ConfigDB)++ -%% ssl_password(ConfigDB)++ -%% ssl_verify_depth(ConfigDB)++ -%% ssl_ca_certificate_file(ConfigDB)} -%% end; -%% ip_comm -> -%% ip_comm -%% end. - get_config(Address, Port, Profile) -> Tab = httpd_util:make_name("httpd_conf", Address, Port, Profile), @@ -836,6 +837,8 @@ lookup_socket_type(ConfigDB) -> case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of ip_comm -> ip_comm; + {ip_comm, _} = Type -> + Type; {Tag, Conf} -> {Tag, Conf}; SSL when (SSL =:= ssl) orelse (SSL =:= essl) -> diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl index f0b1942e2f..bf40cedd5c 100644 --- a/lib/inets/src/http_server/httpd_sup.erl +++ b/lib/inets/src/http_server/httpd_sup.erl @@ -241,7 +241,7 @@ listen(Address, Port, Config) -> case http_transport:start(SocketType) of ok -> {ok, Fd} = get_fd(Port), - IpFamily = proplists:get_value(ipfamily, Config, inet6fb4), + IpFamily = proplists:get_value(ipfamily, Config, inet), case http_transport:listen(SocketType, Address, Port, Fd, IpFamily) of {ok, ListenSocket} -> NewConfig = proplists:delete(port, Config), @@ -286,6 +286,8 @@ socket_type(Config) -> socket_type(ip_comm = SocketType, _) -> SocketType; +socket_type({ip_comm, _} = SocketType, _) -> + SocketType; socket_type({essl, _} = SocketType, _) -> SocketType; socket_type(_, Config) -> diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl index fc69baf829..0387d71911 100644 --- a/lib/inets/src/http_server/httpd_util.erl +++ b/lib/inets/src/http_server/httpd_util.erl @@ -42,17 +42,7 @@ ip_address({_,_,_,_,_,_,_,_} = Address, _IpFamily) -> {ok, Address}; ip_address(Host, IpFamily) when ((IpFamily =:= inet) orelse (IpFamily =:= inet6)) -> - inet:getaddr(Host, IpFamily); -ip_address(Host, inet6fb4 = _IpFamily) -> - Inet = case gen_tcp:listen(0, [inet6]) of - {ok, Dummyport} -> - gen_tcp:close(Dummyport), - inet6; - _ -> - inet - end, - inet:getaddr(Host, Inet). - + inet:getaddr(Host, IpFamily). %% lookup diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index b50d31a5c1..9bd6f3636c 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -1434,9 +1434,11 @@ server_config(http_reload, Config) -> server_config(https_reload, Config) -> [{keep_alive_timeout, 2}] ++ server_config(https, Config); server_config(http_limit, Config) -> - [{max_clients, 1}, - %% Make sure option checking code is run - {max_content_length, 100000002}] ++ server_config(http, Config); + Conf = [{max_clients, 1}, + %% Make sure option checking code is run + {max_content_length, 100000002}] ++ server_config(http, Config), + ct:pal("Received message ~p~n", [Conf]), + Conf; server_config(http_custom, Config) -> [{customize, ?MODULE}] ++ server_config(http, Config); server_config(https_custom, Config) -> @@ -1486,6 +1488,7 @@ server_config(http_mime_types, Config0) -> server_config(http, Config) -> ServerRoot = ?config(server_root, Config), [{port, 0}, + {socket_type, {ip_comm, [{nodelay, true}]}}, {server_name,"httpd_test"}, {server_root, ServerRoot}, {document_root, ?config(doc_root, Config)}, @@ -1507,13 +1510,14 @@ server_config(http, Config) -> server_config(https, Config) -> PrivDir = ?config(priv_dir, Config), [{socket_type, {essl, - [{cacertfile, - filename:join(PrivDir, "public_key_cacert.pem")}, - {certfile, - filename:join(PrivDir, "public_key_cert.pem")}, - {keyfile, - filename:join(PrivDir, "public_key_cert_key.pem")} - ]}}] ++ server_config(http, Config). + [{nodelay, true}, + {cacertfile, + filename:join(PrivDir, "public_key_cacert.pem")}, + {certfile, + filename:join(PrivDir, "public_key_cert.pem")}, + {keyfile, + filename:join(PrivDir, "public_key_cert_key.pem")} + ]}}] ++ proplists:delete(socket_type, server_config(http, Config)). init_httpd(Group, Config0) -> Config1 = proplists:delete(port, Config0), -- cgit v1.2.3 From 51a236b296a07ef488e29e4f1b38ee4d707e8a88 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 9 Nov 2015 15:48:32 +0100 Subject: Inets: Clean up code Remove point less instructions looking for return values, that in most cases no long exist, of which the result would anyhow be ignored --- lib/inets/src/http_lib/http_transport.erl | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index e3d7382043..ddfd6a030e 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -499,16 +499,4 @@ negotiate({essl, _}, Socket, Timeout) -> negotiate_ssl(Socket, Timeout). negotiate_ssl(Socket, Timeout) -> - case ssl:ssl_accept(Socket, Timeout) of - ok -> - ok; - {error, Reason} -> - %% Look for "valid" error reasons - ValidReasons = [timeout, econnreset, esslaccept, esslerrssl], - case lists:member(Reason, ValidReasons) of - true -> - {error, normal}; - false -> - {error, Reason} - end - end. + ssl:ssl_accept(Socket, Timeout). -- cgit v1.2.3 From ef9d44bdd378d30dd1233dbb89abc97ecc155868 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 11 Nov 2015 10:30:23 +0100 Subject: inets: Do not use internal or shell convenience functions in application ssl:start/[1,2] is a shell convenience function and should not be called by other applications. inet_db:start is an internal function that we should not have to call. This was done for legacy reasons and is no longer needed. --- lib/inets/src/http_lib/http_transport.erl | 34 ++++++++++--------------------- 1 file changed, 11 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index ddfd6a030e..ab6afe9c6c 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -49,39 +49,27 @@ %% start(SocketType) -> ok | {error, Reason} %% SocketType = ip_comm | {ssl, _} %% -%% Description: Makes sure inet_db or ssl is started. +%% Description: Makes sure ssl is started. %%------------------------------------------------------------------------- start(ip_comm) -> - do_start_ip_comm(); + ok; start({ip_comm, _}) -> - do_start_ip_comm(); -%% This is just for backward compatibillity + ok; start({ssl, _}) -> do_start_ssl(); start({essl, _}) -> do_start_ssl(). - -do_start_ip_comm() -> - case inet_db:start() of - {ok, _} -> - ok; - {error, {already_started, _}} -> - ok; - Error -> - Error - end. - do_start_ssl() -> - case ssl:start() of - ok -> - ok; - {error, {already_started,_}} -> - ok; - Error -> - Error + try lists:foreach(fun(App) -> + ok = application:ensure_started(App) + end, + [crypto, asn1, public_key, ssl]) + catch + _:Reason -> + {error, Reason} end. - + %%------------------------------------------------------------------------- %% connect(SocketType, Address, Options, Timeout) -> -- cgit v1.2.3 From 35214e082400c8a0a072308986271a28a7a1cc30 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 11 Nov 2015 15:00:29 +0100 Subject: inets: Prepare for release --- lib/inets/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 480caeca4b..7cc95fa6d3 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 6.0.2 +INETS_VSN = 6.0.3 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" -- cgit v1.2.3 From 7448114c9bc35815051fbaf6f4b1ed7846d97b69 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 11 Nov 2015 16:05:53 +0100 Subject: ssh: moved "supported" section from ssh module man page to SSH_app man page --- lib/ssh/doc/src/ssh.xml | 28 ++-------------- lib/ssh/doc/src/ssh_app.xml | 82 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 0e5a0706f5..1e9acf4a99 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -32,34 +32,10 @@ Main API of the ssh application

Interface module for the ssh application.

+

See ssh(6) for details of supported version, + algorithms and unicode support.

-
- SSH - - - For application dependencies see ssh(6) - Supported SSH version is 2.0. - Supported public key algorithms: ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa and ssh-dss. - Supported MAC algorithms: hmac-sha2-256, hmac-sha2-512 and hmac-sha1. - Supported encryption algorithms: aes256-ctr, aes192-ctr, aes128-ctr, aes128-cb and 3des-cbc. - Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group-exchange-sha256 and diffie-hellman-group1-sha1 - Supported compression algorithms: none, zlib@openssh.com and zlib - Supports unicode filenames if the emulator and the underlaying OS support it. - See section DESCRIPTION in the - file manual page in kernel - for information about this subject. - Supports unicode in shell and CLI. - -

The actual set of algorithms can vary depending on which OpenSSL crypto library that is installed on the machine. - For the list on a particular installation, use the command default_algorithms/0. - The user may override the default algorithm configuration both on the server side and the client side. - See the option preferred_algorithms in the daemon and - connect functions. -

- -
-
OPTIONS

The exact behaviour of some functions can be adjusted with the use of options which are documented together diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index 1ae1558607..f461f87d1b 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -52,7 +52,7 @@

-
+
CONFIGURATION

The ssh application does not have an application- @@ -119,6 +119,86 @@

The ssh application uses the default OTP error logger to log unexpected errors or print information about special events.

+
+ + SUPPORTED +

The supported SSH version is 2.0.

+ + Algorithms +

The actual set of algorithms may vary depending on which OpenSSL crypto library that is installed on the machine. + For the list on a particular installation, use the command + ssh:default_algorithms/0. + The user may override the default algorithm configuration both on the server side and the client side. + See the option preferred_algorithms in the ssh:daemon/1,2,3 and + ssh:connect/3,4 functions. +

+ +

Supported algorithms are:

+ + + Public key algorithms + + + ecdsa-sha2-nistp256 + ecdsa-sha2-nistp384 + ecdsa-sha2-nistp521 + ssh-rsa + ssh-dss + + + + MAC algorithms + + + hmac-sha2-256 + hmac-sha2-512 + hmac-sha1 + + + + Encryption algorithms + + + aes128-ctr + aes192-ctr + aes256-ctr + aes128-cbc + 3des-cbc + + + + Key exchange algorithms + + + ecdh-sha2-nistp256 + ecdh-sha2-nistp384 + ecdh-sha2-nistp521 + diffie-hellman-group-exchange-sha1 + diffie-hellman-group-exchange-sha256 + diffie-hellman-group14-sha1 + diffie-hellman-group1-sha1 + + + + Compression algorithms + + + none + zlib@openssh.com + zlib + + + + + Unicode support +

Unicode filenames are supported if the emulator and the underlaying OS support it. See section DESCRIPTION in the + file manual page in kernel for information about this subject. +

+

The shell and the cli support unicode. +

+ +
+
SEE ALSO

application(3)

-- cgit v1.2.3 From 65ac12ef11a869fa45f63dd64e905e55b1c7cdd5 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 11 Nov 2015 16:54:37 +0100 Subject: ssh: list supported rfcs --- lib/ssh/doc/src/ssh_app.xml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index f461f87d1b..f91285d8b8 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -202,6 +202,36 @@
SEE ALSO

application(3)

+

The following rfc:s are supported:

+ + RFC 4251, The Secure Shell (SSH) Protocol Architecture. + (Except 9.4.6, 9.5.2, 9.5.3) + + RFC 4252, The Secure Shell (SSH) Authentication Protocol. + (Except 9. Host-Based Authentication: "hostbased") + + RFC 4253, The Secure Shell (SSH) Transport Layer Protocol. + + RFC 4254, The Secure Shell (SSH) Connection Protocol. + (Except 6.3. X11 Forwarding, 7. TCP/IP Port Forwarding) + + RFC 4256, Generic Message Exchange Authentication for + the Secure Shell Protocol (SSH). + (Except num-prompts > 1, password changing, other identification methods than userid-password) + + RFC 4419, Diffie-Hellman Group Exchange for + the Secure Shell (SSH) Transport Layer Protocol. + + RFC 4716, The Secure Shell (SSH) Public Key File Format. + + RFC 5656, Elliptic Curve Algorithm Integration in + the Secure Shell Transport Layer. + (Except 5. ECMQV Key Exchange, 6.4. ECMQV Key Exchange and Verification Method Name, + 7.2. ECMQV Message Numbers, 10.2. Recommended Curves) + + + +
-- cgit v1.2.3 From b1915f1e807614f0c74af4de6773e4f1656ca1a2 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Thu, 12 Nov 2015 10:50:18 +0100 Subject: Update release notes --- lib/inets/doc/src/notes.xml | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index ef11fdc10c..8c4fdfdf70 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,40 @@ notes.xml -
Inets 6.0.2 +
Inets 6.0.3 + +
Fixed Bugs and Malfunctions + + +

+ Improved error handling and gracfully termination when an + invalid chunked length header is encountered.

+

+ Own Id: OTP-13061

+
+
+
+ + +
Improvements and New Features + + +

+ Add possibility to set socket options, such as nodelay, + for httpd. Also phase out legacy option value inet6bf4 + for the ipfamily option. This value will be translated to + the value inet.

+

+ *** POTENTIAL INCOMPATIBILITY ***

+

+ Own Id: OTP-13062

+
+
+
+ +
+ +
Inets 6.0.2
Fixed Bugs and Malfunctions -- cgit v1.2.3 From 777c373cee742f2ba14246a437a4a12e68f93b5b Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 13 Nov 2015 12:21:15 +0100 Subject: ssh: alternative look --- lib/ssh/doc/src/ssh_app.xml | 71 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index f91285d8b8..29cbbd79a2 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -121,9 +121,10 @@
- SUPPORTED + SUPPORTED SPECIFICATIONS AND STANDARDS

The supported SSH version is 2.0.

- +
+
Algorithms

The actual set of algorithms may vary depending on which OpenSSL crypto library that is installed on the machine. For the list on a particular installation, use the command @@ -189,49 +190,89 @@ - +

+
Unicode support

Unicode filenames are supported if the emulator and the underlaying OS support it. See section DESCRIPTION in the file manual page in kernel for information about this subject.

-

The shell and the cli support unicode. +

The shell and the cli both support unicode.

-
- SEE ALSO -

application(3)

+ Rfcs

The following rfc:s are supported:

RFC 4251, The Secure Shell (SSH) Protocol Architecture. - (Except 9.4.6, 9.5.2, 9.5.3) +

Except + + 9.4.6 Host-Based Authentication + 9.5.2 Proxy Forwarding + 9.5.3 X11 Forwarding + +

+ RFC 4252, The Secure Shell (SSH) Authentication Protocol. - (Except 9. Host-Based Authentication: "hostbased") +

Except + + 9. Host-Based Authentication: "hostbased" + +

+ RFC 4253, The Secure Shell (SSH) Transport Layer Protocol. +

+ RFC 4254, The Secure Shell (SSH) Connection Protocol. - (Except 6.3. X11 Forwarding, 7. TCP/IP Port Forwarding) +

Except + + 6.3. X11 Forwarding + 7. TCP/IP Port Forwarding + +

+ RFC 4256, Generic Message Exchange Authentication for the Secure Shell Protocol (SSH). - (Except num-prompts > 1, password changing, other identification methods than userid-password) +

Except + + num-prompts > 1 + password changing + other identification methods than userid-password + +

+ RFC 4419, Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol. +

+ RFC 4716, The Secure Shell (SSH) Public Key File Format. +

+ RFC 5656, Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer. - (Except 5. ECMQV Key Exchange, 6.4. ECMQV Key Exchange and Verification Method Name, - 7.2. ECMQV Message Numbers, 10.2. Recommended Curves) +

Except + + 5. ECMQV Key Exchange + 6.4. ECMQV Key Exchange and Verification Method Name + 7.2. ECMQV Message Numbers + 10.2. Recommended Curves + +

- -
+ +
+ +
+ SEE ALSO +

application(3)

-- cgit v1.2.3 From b638b3e8c3be7599724fc086e0dfd652b89b72c2 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 5 Nov 2015 11:42:53 +0100 Subject: ssh: more public keys added to test suite --- lib/ssh/test/ssh_algorithms_SUITE.erl | 4 +++- lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa | 5 +++++ lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub | 1 + lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256 | 5 +++++ lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub | 1 + lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256 | 5 +++++ lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub | 1 + 7 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256 create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256 create mode 100644 lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub (limited to 'lib') diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index 85415a17de..fbfca324b2 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -358,7 +358,9 @@ start_pubkey_daemon(Opts, Config) -> setup_pubkey(Config) -> DataDir = ?config(data_dir, Config), UserDir = ?config(priv_dir, Config), - ssh_test_lib:setup_dsa_known_host(DataDir, UserDir), + ssh_test_lib:setup_dsa(DataDir, UserDir), + ssh_test_lib:setup_rsa(DataDir, UserDir), + ssh_test_lib:setup_ecdsa("256", DataDir, UserDir), Config. diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa new file mode 100644 index 0000000000..4b1eb12eaa --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJfCaBKIIKhjbJl5F8BedqlXOQYDX5ba9Skypllmx/w+oAoGCCqGSM49 +AwEHoUQDQgAE49RbK2xQ/19ji3uDPM7uT4692LbwWF1TiaA9vUuebMGazoW/98br +N9xZu0L1AWwtEjs3kmJDTB7eJEGXnjUAcQ== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub new file mode 100644 index 0000000000..a0147e60fa --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPUWytsUP9fY4t7gzzO7k+Ovdi28FhdU4mgPb1LnmzBms6Fv/fG6zfcWbtC9QFsLRI7N5JiQ0we3iRBl541AHE= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256 b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256 new file mode 100644 index 0000000000..4b1eb12eaa --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJfCaBKIIKhjbJl5F8BedqlXOQYDX5ba9Skypllmx/w+oAoGCCqGSM49 +AwEHoUQDQgAE49RbK2xQ/19ji3uDPM7uT4692LbwWF1TiaA9vUuebMGazoW/98br +N9xZu0L1AWwtEjs3kmJDTB7eJEGXnjUAcQ== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub new file mode 100644 index 0000000000..a0147e60fa --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPUWytsUP9fY4t7gzzO7k+Ovdi28FhdU4mgPb1LnmzBms6Fv/fG6zfcWbtC9QFsLRI7N5JiQ0we3iRBl541AHE= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256 new file mode 100644 index 0000000000..2979ea88ed --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49 +AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s +VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub new file mode 100644 index 0000000000..85dc419345 --- /dev/null +++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32 -- cgit v1.2.3 From 9cce80c63af4e1bfbbddb2c2f32a17760d5e6b7d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 12 Nov 2015 10:09:44 +0100 Subject: ssh: Add env var info printout to ssh_algorithms_SUTE:init_per_suite --- lib/ssh/test/ssh_algorithms_SUITE.erl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index fbfca324b2..f0ac92fef6 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -69,6 +69,9 @@ two_way_tags() -> [cipher,mac,compression]. %%-------------------------------------------------------------------- init_per_suite(Config) -> + ct:log("os:getenv(\"HOME\") = ~p~n" + "init:get_argument(home) = ~p", + [os:getenv("HOME"), init:get_argument(home)]), ct:log("~n~n" "OS ssh:~n=======~n~p~n~n~n" "Erl ssh:~n========~n~p~n~n~n" -- cgit v1.2.3 From ae6cec13757195406c65c598ddd9b979a2c4f517 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 6 Nov 2015 13:23:13 +0100 Subject: ssh: ssh_file:default_user_dir/0 - try HOME env var first --- lib/ssh/src/ssh_file.erl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index 2f16a31cba..3e066c453d 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -336,8 +336,18 @@ is_auth_key(Key, Key) -> is_auth_key(_,_) -> false. -default_user_dir()-> - {ok,[[Home|_]]} = init:get_argument(home), + +default_user_dir() -> + try + default_user_dir(os:getenv("HOME")) + catch + _:_ -> + default_user_dir(init:get_argument(home)) + end. + +default_user_dir({ok,[[Home|_]]}) -> + default_user_dir(Home); +default_user_dir(Home) when is_list(Home) -> UserDir = filename:join(Home, ".ssh"), ok = filelib:ensure_dir(filename:join(UserDir, "dummy")), {ok,Info} = file:read_file_info(UserDir), -- cgit v1.2.3 From d5ce9036c629939cd979a03ace1b0107c23a9d78 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Fri, 13 Nov 2015 16:50:16 +0000 Subject: Add test for dist_nodelay option Run the 'basic' test with dist_nodelay set to false. --- lib/ssl/test/ssl_dist_SUITE.erl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index 1a1b2af8d4..a76fa03d33 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -43,7 +43,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [basic, payload, plain_options, plain_verify_options]. + [basic, payload, plain_options, plain_verify_options, nodelay_option]. groups() -> []. @@ -255,6 +255,17 @@ plain_verify_options(Config) when is_list(Config) -> stop_ssl_node(NH1), stop_ssl_node(NH2), success(Config). +%%-------------------------------------------------------------------- +nodelay_option() -> + [{doc,"Test specifying dist_nodelay option"}]. +nodelay_option(Config) -> + try + %% The default is 'true', so try setting it to 'false'. + application:set_env(kernel, dist_nodelay, false), + basic(Config) + after + application:unset_env(kernel, dist_nodelay) + end. %%-------------------------------------------------------------------- %%% Internal functions ----------------------------------------------- -- cgit v1.2.3 From fd1e6b2b2623395512ea0450c3b4e656cb354f42 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 13 Nov 2015 19:13:03 +0100 Subject: stdlib: Fix bug in binary:split for empty binary Bug introduced om master branch at b93e9b611056828a and reported in ERL-43. --- lib/stdlib/test/binary_module_SUITE.erl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl index 70c946bdb9..933c3ce5a9 100644 --- a/lib/stdlib/test/binary_module_SUITE.erl +++ b/lib/stdlib/test/binary_module_SUITE.erl @@ -536,6 +536,12 @@ do_interesting(Module) -> ?line [<<3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>, [<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>], [global,trim_all]), + [<<>>] = binary:split(<<>>, <<",">>, []), + [] = binary:split(<<>>, <<",">>, [trim]), + [] = binary:split(<<>>, <<",">>, [trim_all]), + [] = binary:split(<<>>, <<",">>, [global,trim]), + [] = binary:split(<<>>, <<",">>, [global,trim_all]), + ?line badarg = ?MASK_ERROR( Module:replace(<<1,2,3,4,5,6,7,8>>, [<<4,5>>,<<7>>,<<8>>],<<99>>, -- cgit v1.2.3 From 192c4a80c7d6fe9949aecb864901c4a3d9549f36 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Wed, 11 Nov 2015 12:37:09 +0100 Subject: musl: fix gethostbyname_r/gethostbyaddr_ selection To fix conditional selection of the actually available gethostbyname_r and gethostbyaddr_r, we replace __GLIBC__ with __linux__. @zenhack tested this to work with gcc and clang targeting glibc, uclibc, musl, and bionic. The proper way to check this is through configure.in. --- lib/erl_interface/src/connect/ei_resolve.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c index 3f1be2b17d..6381b02393 100644 --- a/lib/erl_interface/src/connect/ei_resolve.c +++ b/lib/erl_interface/src/connect/ei_resolve.c @@ -601,6 +601,16 @@ struct hostent *ei_gethostbyaddr(const char *addr, int len, int type) return gethostbyaddr(addr, len, type); } +/* + * Imprecise way to select the actually available gethostbyname_r and + * gethostbyaddr_r. + * + * TODO: check this properly in configure.in + */ +#if (defined(__linux__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__)) + #define HAVE_GETHOSTBYADDR_R_8 1 +#endif + struct hostent *ei_gethostbyaddr_r(const char *addr, int length, int type, @@ -616,7 +626,7 @@ struct hostent *ei_gethostbyaddr_r(const char *addr, #ifndef HAVE_GETHOSTBYNAME_R return my_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop); #else -#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__)) +#ifdef HAVE_GETHOSTBYADDR_R_8 struct hostent *result; gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, &result, @@ -643,7 +653,7 @@ struct hostent *ei_gethostbyname_r(const char *name, #ifndef HAVE_GETHOSTBYNAME_R return my_gethostbyname_r(name,hostp,buffer,buflen,h_errnop); #else -#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__) || defined(__ANDROID__)) +#ifdef HAVE_GETHOSTBYADDR_R_8 struct hostent *result; gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop); -- cgit v1.2.3 From 56025e23118f69b8d1b87b0478a93499752360cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Wei=C3=9Fl?= Date: Sat, 14 Nov 2015 19:30:52 +0100 Subject: inets: Allow whitespace after HTTP chunk again Before 77acb47 http:request/1 could parse server responses with whitespace after the HTTP chunk size (some embedded legacy devices still do this). This patch restores this functionality. --- lib/inets/src/http_lib/http_chunk.erl | 2 +- lib/inets/test/http_format_SUITE.erl | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl index 2f8476a49d..9699856bf8 100644 --- a/lib/inets/src/http_lib/http_chunk.erl +++ b/lib/inets/src/http_lib/http_chunk.erl @@ -147,7 +147,7 @@ decode_size(Data = <>, HexList, AccHeaderSize, {MaxBodySize, Body, AccLength, MaxHeaderSize}) -> - try http_util:hexlist_to_integer(lists:reverse(HexList)) of + try http_util:hexlist_to_integer(lists:reverse(string:strip(HexList, left))) of 0 -> % Last chunk, there was no data ignore_extensions(Data, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize, {?MODULE, decode_trailer, diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl index a927adc75e..e977bd1b9b 100644 --- a/lib/inets/test/http_format_SUITE.erl +++ b/lib/inets/test/http_format_SUITE.erl @@ -38,6 +38,7 @@ groups() -> [chunk_decode, chunk_encode, chunk_extensions_otp_6005, chunk_decode_otp_6264, chunk_decode_empty_chunk_otp_6511, + chunk_whitespace_suffix, chunk_decode_trailer, chunk_max_headersize, chunk_max_bodysize, chunk_not_hex]}]. init_per_suite(Config) -> @@ -156,6 +157,21 @@ chunk_decode_empty_chunk_otp_6511(Config) when is_list(Config) -> http_chunk:decode(list_to_binary(ChunkedBody), ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE). +%%------------------------------------------------------------------------- +chunk_whitespace_suffix() -> + [{doc, "Test whitespace after chunked length header"}]. +chunk_whitespace_suffix(Config) when is_list(Config) -> + ChunkedBody = "1a ; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10 " ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0 " ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + {ok, {["content-length:42", "another-footer:another-value", + "some-footer:some-value", ""], + <<"abcdefghijklmnopqrstuvwxyz1234567890abcdef">>}} = + http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE). + %%------------------------------------------------------------------------- chunk_decode_trailer() -> [{doc,"Make sure trailers are handled correctly. Trailers should" -- cgit v1.2.3 From 25c9d0c38d659cc00db461d760f66369e9024c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Wei=C3=9Fl?= Date: Sat, 14 Nov 2015 16:29:13 +0100 Subject: inets: Terminate really gracefully on bad chunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this fix, httpc:request/1 crashes the httpc_handler when an invalid chunked length header is encountered (since 77acb47): =ERROR REPORT==== 14-Nov-2015::17:19:30 === ** Generic server <0.651.0> terminating ** Last message in was {tcp,#Port<0.5714>, <<"HTTP/1.1 200 ok\r\nTransfer-Encoding:chunked\r\n\r\nåäö\r\n">>} ** When Server state == {state, [...] ** Reason for termination == ** {bad_return_value,{error,{chunk_size,"åäö"}}} --- lib/inets/src/http_client/httpc_handler.erl | 11 +++++++++-- lib/inets/test/httpc_SUITE.erl | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 1044cffe6f..e6dcfee818 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1113,8 +1113,8 @@ handle_http_body(Body, #state{headers = Headers, case case_insensitive_header(TransferEnc) of "chunked" -> ?hcrt("handle_http_body - chunked", []), - case http_chunk:decode(Body, State#state.max_body_size, - State#state.max_header_size) of + try http_chunk:decode(Body, State#state.max_body_size, + State#state.max_header_size) of {Module, Function, Args} -> ?hcrt("handle_http_body - new mfa", [{module, Module}, @@ -1139,6 +1139,13 @@ handle_http_body(Body, #state{headers = Headers, handle_response(State#state{headers = NewHeaders, body = NewBody2}) end + catch throw:{error, Reason} -> + NewState = + answer_request(Request, + httpc_response:error(Request, + Reason), + State), + {stop, normal, NewState} end; Enc when Enc =:= "identity"; Enc =:= undefined -> ?hcrt("handle_http_body - identity", []), diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 989563cdbc..c6c59ab1af 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -106,6 +106,7 @@ only_simulated() -> bad_response, internal_server_error, invalid_http, + invalid_chunk_size, headers_dummy, headers_with_obs_fold, empty_response_header, @@ -765,6 +766,22 @@ invalid_http(Config) when is_list(Config) -> ct:print("Parse error: ~p ~n", [Reason]). %%------------------------------------------------------------------------- + +invalid_chunk_size(doc) -> + ["Test parse error of HTTP chunk size"]; +invalid_chunk_size(suite) -> + []; +invalid_chunk_size(Config) when is_list(Config) -> + + URL = url(group_name(Config), "/invalid_chunk_size.html", Config), + + {error, {chunk_size, _} = Reason} = + httpc:request(get, {URL, []}, [], []), + + ct:print("Parse error: ~p ~n", [Reason]). + +%%------------------------------------------------------------------------- + emulate_lower_versions(doc) -> [{doc, "Perform request as 0.9 and 1.0 clients."}]; emulate_lower_versions(Config) when is_list(Config) -> @@ -1876,6 +1893,10 @@ handle_uri(_,"/invalid_http.html",_,_,_,_) -> "HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++ "Transfer-Encoding:chunked\r\n\r\n"; +handle_uri(_,"/invalid_chunk_size.html",_,_,_,_) -> + "HTTP/1.1 200 ok\r\n" ++ + "Transfer-Encoding:chunked\r\n\r\nåäö\r\n"; + handle_uri(_,"/missing_reason_phrase.html",_,_,_,_) -> "HTTP/1.1 200\r\n" ++ "Content-Length: 32\r\n\r\n" -- cgit v1.2.3 From 0a1150e85bd23b2dbf116454d4d0207b7c54974a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 18:19:45 +0100 Subject: beam_validator: Remove obsolete DEBUG support No one has used the debug support in many years. Also, the debug support is not free. There are calls to lists:foreach/2 that will be executed even when debug support is turned off. --- lib/compiler/src/beam_validator.erl | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index cdace42a68..5944746edc 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -31,13 +31,6 @@ -import(lists, [reverse/1,foldl/3,foreach/2,dropwhile/2]). -%%-define(DEBUG, 1). --ifdef(DEBUG). --define(DBG_FORMAT(F, D), (io:format((F), (D)))). --else. --define(DBG_FORMAT(F, D), ok). --endif. - %% To be called by the compiler. module({Mod,Exp,Attr,Fs,Lc}=Code, _Opts) when is_atom(Mod), is_list(Exp), is_list(Attr), is_integer(Lc) -> @@ -168,27 +161,16 @@ validate_0(Module, [{function,Name,Ar,Entry,Code}|Fs], Ft) -> % in the module (those that start with bs_start_match2). }). --ifdef(DEBUG). -print_st(#st{x=Xs,y=Ys,numy=NumY,h=H,ct=Ct}) -> - io:format(" #st{x=~p~n" - " y=~p~n" - " numy=~p,h=~p,ct=~w~n", - [gb_trees:to_list(Xs),gb_trees:to_list(Ys),NumY,H,Ct]). --endif. - validate_1(Is, Name, Arity, Entry, Ft) -> validate_2(labels(Is), Name, Arity, Entry, Ft). validate_2({Ls1,[{func_info,{atom,Mod},{atom,Name},Arity}=_F|Is]}, Name, Arity, Entry, Ft) -> - lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [{label,_L}]) end, Ls1), - ?DBG_FORMAT(" ~p.~n", [_F]), validate_3(labels(Is), Name, Arity, Entry, Mod, Ls1, Ft); validate_2({Ls1,Is}, Name, Arity, _Entry, _Ft) -> error({{'_',Name,Arity},{first(Is),length(Ls1),illegal_instruction}}). validate_3({Ls2,Is}, Name, Arity, Entry, Mod, Ls1, Ft) -> - lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [{label,_L}]) end, Ls2), Offset = 1 + length(Ls1) + 1 + length(Ls2), EntryOK = (Entry =:= undefined) orelse lists:member(Entry, Ls2), if @@ -258,7 +240,6 @@ valfun([], MFA, _Offset, #vst{branched=Targets0,labels=Labels0}=Vst) -> error({MFA,Error}) end; valfun([I|Is], MFA, Offset, Vst0) -> - ?DBG_FORMAT(" ~p.\n", [I]), valfun(Is, MFA, Offset+1, try Vst = val_dsetel(I, Vst0), @@ -276,7 +257,6 @@ valfun_1({label,Lbl}, #vst{current=St0,branched=B,labels=Lbls}=Vst) -> valfun_1(_I, #vst{current=none}=Vst) -> %% Ignore instructions after erlang:error/1,2, which %% the original R10B compiler thought would return. - ?DBG_FORMAT("Ignoring ~p\n", [_I]), Vst; valfun_1({badmatch,Src}, Vst) -> assert_term(Src, Vst), @@ -1626,8 +1606,4 @@ min(A, B) when is_integer(A), is_integer(B) -> B. gb_trees_from_list(L) -> gb_trees:from_orddict(lists:sort(L)). --ifdef(DEBUG). -error(Error) -> exit(Error). --else. error(Error) -> throw(Error). --endif. -- cgit v1.2.3 From 0a94d155e0197121fac63c8fb8ae0f7bc942dcc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 Nov 2015 18:29:32 +0100 Subject: beam_validator: Don't allow an 'undefined' entry label in a function Before 912fea0b beam_validator could validate disassembled files. That's probably why the entry label was allowed to be 'undefined'. --- lib/compiler/src/beam_validator.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 5944746edc..fd38fc0095 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -172,7 +172,7 @@ validate_2({Ls1,Is}, Name, Arity, _Entry, _Ft) -> validate_3({Ls2,Is}, Name, Arity, Entry, Mod, Ls1, Ft) -> Offset = 1 + length(Ls1) + 1 + length(Ls2), - EntryOK = (Entry =:= undefined) orelse lists:member(Entry, Ls2), + EntryOK = lists:member(Entry, Ls2), if EntryOK -> St = init_state(Arity), -- cgit v1.2.3 From b99d992454d0ffded5b18907ff905c214fcccc9c Mon Sep 17 00:00:00 2001 From: Zandra Date: Mon, 16 Nov 2015 15:10:27 +0100 Subject: fix 24h macro in test suite Needed after the fix in 120975c4fcb57ecd14031ac046f483e56a3daa4d. --- lib/ssl/test/ssl_basic_SUITE.erl | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 6f6107de2c..f032c769e2 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -35,7 +35,6 @@ -include("tls_record.hrl"). -include("tls_handshake.hrl"). --define('24H_in_sec', 86400). -define(TIMEOUT, 20000). -define(EXPIRE, 10). -define(SLEEP, 500). -- cgit v1.2.3 From 7fc200b2f54d0c4b1dbc9edaee1fa6005a230d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 16 Nov 2015 15:34:32 +0100 Subject: epp_SUITE: Add test of -extends() --- lib/stdlib/test/epp_SUITE.erl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 199d2f193d..d2715216d3 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -27,7 +27,7 @@ pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1, otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1, otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1, - otp_11728/1, encoding/1]). + otp_11728/1, encoding/1, extends/1]). -export([epp_parse_erl_form/2]). @@ -70,7 +70,7 @@ all() -> not_circular, skip_header, otp_6277, otp_7702, otp_8130, overload_mac, otp_8388, otp_8470, otp_8503, otp_8562, otp_8665, otp_8911, otp_10302, otp_10820, otp_11728, - encoding]. + encoding, extends]. groups() -> [{upcase_mac, [], [upcase_mac_1, upcase_mac_2]}, @@ -1476,6 +1476,20 @@ encoding(Config) when is_list(Config) -> epp_parse_file(ErlFile, [{default_encoding,utf8},extra]), ok. +extends(Config) -> + Cs = [{extends_c1, + <<"-extends(some.other.module).\n">>, + {errors,[{1,erl_parse,["syntax error before: ","'.'"]}],[]}}], + [] = compile(Config, Cs), + + Ts = [{extends_1, + <<"-extends(some_other_module).\n" + "t() -> {?BASE_MODULE,?BASE_MODULE_STRING}.\n">>, + {some_other_module,"some_other_module"}}], + + [] = run(Config, Ts), + ok. + check(Config, Tests) -> eval_tests(Config, fun check_test/2, Tests). -- cgit v1.2.3 From 7bfba5dfb5ec581880290b3fea8645504064dd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Nov 2015 07:42:24 +0100 Subject: epp_SUITE: Extend smoke and cover test of format_error/1 30a4adb7 added smoke and cover test of format_error/1, but did not catch calls that went through check/2. --- lib/stdlib/test/epp_SUITE.erl | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index d2715216d3..abd2501ce7 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -1518,15 +1518,17 @@ eval_tests(Config, Fun, Tests) -> check_test(Config, Test) -> Filename = "epp_test.erl", - ?line PrivDir = ?config(priv_dir, Config), - ?line File = filename:join(PrivDir, Filename), - ?line ok = file:write_file(File, Test), - ?line case epp:parse_file(File, [PrivDir], []) of - {ok,Forms} -> - [E || E={error,_} <- Forms]; - {error,Error} -> - Error - end. + PrivDir = ?config(priv_dir, Config), + File = filename:join(PrivDir, Filename), + ok = file:write_file(File, Test), + case epp:parse_file(File, [PrivDir], []) of + {ok,Forms} -> + Errors = [E || E={error,_} <- Forms], + call_format_error([E || {error,E} <- Errors]), + Errors; + {error,Error} -> + Error + end. compile_test(Config, Test0) -> Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0], -- cgit v1.2.3 From a1a45183b4c88dd2f68a010cbe537d387d364aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Nov 2015 07:44:17 +0100 Subject: epp_SUITE: Improve coverage of epp --- lib/stdlib/test/epp_SUITE.erl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index abd2501ce7..90642b2dca 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -621,6 +621,10 @@ otp_8130(Config) when is_list(Config) -> " 2 end,\n" " 7),\n" " {2,7} =\n" + " ?M1(begin 1 = fun _Name () -> 1 end(),\n" + " 2 end,\n" + " 7),\n" + " {2,7} =\n" " ?M1(begin 1 = fun t0/0(),\n" " 2 end,\n" " 7),\n" @@ -645,6 +649,9 @@ otp_8130(Config) when is_list(Config) -> " ?M1(begin yes = try 1 of 1 -> yes after foo end,\n" " 2 end,\n" " 7),\n" + " {[42],7} =\n" + " ?M1([42],\n" + " 7),\n" "ok.\n">>, ok}, @@ -728,11 +735,16 @@ otp_8130(Config) when is_list(Config) -> {errors,[{{2,2},epp,{include,lib,"$apa/foo.hrl"}}],[]}}, - {otp_8130_c9, + {otp_8130_c9a, <<"-define(S, ?S).\n" "t() -> ?S.\n">>, {errors,[{{2,9},epp,{circular,'S', none}}],[]}}, + {otp_8130_c9b, + <<"-define(S(), ?S()).\n" + "t() -> ?S().\n">>, + {errors,[{{2,9},epp,{circular,'S', 0}}],[]}}, + {otp_8130_c10, <<"\n-file.">>, {errors,[{{2,2},epp,{bad,file}}],[]}}, -- cgit v1.2.3 From c1a6beef36bd89b7e50efa8df1ef71f33272de12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 16 Nov 2015 15:37:27 +0100 Subject: epp: Remove vestigial support for packages Packages were removed in 34d865a7dfdb33 (R16), but the 'epp' module was forgotten. --- lib/stdlib/src/epp.erl | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index c8bba579cc..46c23fd0e0 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -797,35 +797,26 @@ scan_toks(Toks0, From, St) -> end. scan_module([{'-',_Lh},{atom,_Lm,module},{'(',_Ll}|Ts], Ms) -> - scan_module_1(Ts, [], Ms); + scan_module_1(Ts, Ms); scan_module([{'-',_Lh},{atom,_Lm,extends},{'(',_Ll}|Ts], Ms) -> - scan_extends(Ts, [], Ms); + scan_extends(Ts, Ms); scan_module(_Ts, Ms) -> Ms. -scan_module_1([{atom,_,_}=A,{',',L}|Ts], As, Ms) -> +scan_module_1([{atom,_,_}=A,{',',L}|Ts], Ms) -> %% Parameterized modules. - scan_module_1([A,{')',L}|Ts], As, Ms); -scan_module_1([{atom,Ln,A},{')',_Lr}|_Ts], As, Ms0) -> - Mod = lists:concat(lists:reverse([A|As])), - Ms = dict:store({atom,'MODULE'}, - {none,[{atom,Ln,list_to_atom(Mod)}]}, Ms0), - dict:store({atom,'MODULE_STRING'}, {none,[{string,Ln,Mod}]}, Ms); -scan_module_1([{atom,_Ln,A},{'.',_Lr}|Ts], As, Ms) -> - scan_module_1(Ts, [".",A|As], Ms); -scan_module_1([{'.',_Lr}|Ts], As, Ms) -> - scan_module_1(Ts, As, Ms); -scan_module_1(_Ts, _As, Ms) -> Ms. - -scan_extends([{atom,Ln,A},{')',_Lr}|_Ts], As, Ms0) -> - Mod = lists:concat(lists:reverse([A|As])), - Ms = dict:store({atom,'BASE_MODULE'}, - {none,[{atom,Ln,list_to_atom(Mod)}]}, Ms0), - dict:store({atom,'BASE_MODULE_STRING'}, {none,[{string,Ln,Mod}]}, Ms); -scan_extends([{atom,_Ln,A},{'.',_Lr}|Ts], As, Ms) -> - scan_extends(Ts, [".",A|As], Ms); -scan_extends([{'.',_Lr}|Ts], As, Ms) -> - scan_extends(Ts, As, Ms); -scan_extends(_Ts, _As, Ms) -> Ms. + scan_module_1([A,{')',L}|Ts], Ms); +scan_module_1([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) -> + ModString = atom_to_list(A), + Ms = dict:store({atom,'MODULE'}, {none,[ModAtom]}, Ms0), + dict:store({atom,'MODULE_STRING'}, {none,[{string,Ln,ModString}]}, Ms); +scan_module_1(_Ts, Ms) -> Ms. + +scan_extends([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) -> + ModString = atom_to_list(A), + Ms = dict:store({atom,'BASE_MODULE'}, {none,[ModAtom]}, Ms0), + dict:store({atom,'BASE_MODULE_STRING'}, + {none,[{string,Ln,ModString}]}, Ms); +scan_extends(_Ts, Ms) -> Ms. %% scan_define(Tokens, DefineToken, From, EppState) -- cgit v1.2.3 From 57c53b4918bafc72097315d980fea2d0f296b1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 16 Nov 2015 14:38:15 +0100 Subject: epp: Refactor scan_define() Refactor scan_define() in order to share more between macros without any arguments and macros with arguments. --- lib/stdlib/src/epp.erl | 79 ++++++++++++++++++------------------------- lib/stdlib/test/epp_SUITE.erl | 4 +++ 2 files changed, 37 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 46c23fd0e0..d9a579ebc6 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -820,59 +820,26 @@ scan_extends(_Ts, Ms) -> Ms. %% scan_define(Tokens, DefineToken, From, EppState) -scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_}=Comma|Toks], _Def, From, St) +scan_define([{'(',_Lp},{Type,_Lm,_}=Mac|Toks], Def, From, St) when Type =:= atom; Type =:= var -> + scan_define_1(Toks, Mac, Def, From, St); +scan_define(_Toks, Def, From, St) -> + epp_reply(From, {error,{loc(Def),epp,{bad,define}}}), + wait_req_scan(St). + +scan_define_1([{',',_}=Comma|Toks], Mac,_Def, From, St) -> case catch macro_expansion(Toks, Comma) of Expansion when is_list(Expansion) -> - case dict:find({atom,M}, St#epp.macs) of - {ok, Defs} when is_list(Defs) -> - %% User defined macros: can be overloaded - case proplists:is_defined(none, Defs) of - true -> - epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}), - wait_req_scan(St); - false -> - scan_define_cont(From, St, - {atom, M}, - {none, {none,Expansion}}) - end; - {ok, _PreDef} -> - %% Predefined macros: cannot be overloaded - epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}), - wait_req_scan(St); - error -> - scan_define_cont(From, St, - {atom, M}, - {none, {none,Expansion}}) - end; + scan_define_2(none, {none,Expansion}, Mac, From, St); {error,ErrL,What} -> epp_reply(From, {error,{ErrL,epp,What}}), wait_req_scan(St) end; -scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) - when Type =:= atom; Type =:= var -> +scan_define_1([{'(',_Lc}|Toks], Mac, Def, From, St) -> case catch macro_pars(Toks, []) of - {ok, {As,Me}} -> + {ok,{As,_}=MacroDef} -> Len = length(As), - case dict:find({atom,M}, St#epp.macs) of - {ok, Defs} when is_list(Defs) -> - %% User defined macros: can be overloaded - case proplists:is_defined(Len, Defs) of - true -> - epp_reply(From,{error,{loc(Mac),epp,{redefine,M}}}), - wait_req_scan(St); - false -> - scan_define_cont(From, St, {atom, M}, - {Len, {As, Me}}) - end; - {ok, _PreDef} -> - %% Predefined macros: cannot be overloaded - %% (There are currently no predefined F(...) macros.) - epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}), - wait_req_scan(St); - error -> - scan_define_cont(From, St, {atom, M}, {Len, {As, Me}}) - end; + scan_define_2(Len, MacroDef, Mac, From, St); {error,ErrL,What} -> epp_reply(From, {error,{ErrL,epp,What}}), wait_req_scan(St); @@ -880,10 +847,30 @@ scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) epp_reply(From, {error,{loc(Def),epp,{bad,define}}}), wait_req_scan(St) end; -scan_define(_Toks, Def, From, St) -> +scan_define_1(_Toks, _Mac, Def, From, St) -> epp_reply(From, {error,{loc(Def),epp,{bad,define}}}), wait_req_scan(St). +scan_define_2(Arity, Def, {_,_,M}=Mac, From, St) -> + Key = {atom,M}, + case dict:find(Key, St#epp.macs) of + {ok,Defs} when is_list(Defs) -> + %% User defined macros: can be overloaded + case proplists:is_defined(Arity, Defs) of + true -> + epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}), + wait_req_scan(St); + false -> + scan_define_cont(From, St, Key, Arity, Def) + end; + {ok,_PreDef} -> + %% Predefined macros: cannot be overloaded + epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}), + wait_req_scan(St); + error -> + scan_define_cont(From, St, Key, Arity, Def) + end. + %%% Detection of circular macro expansions (which would either keep %%% the compiler looping forever, or run out of memory): %%% When a macro is defined, we store the names of other macros it @@ -893,7 +880,7 @@ scan_define(_Toks, Def, From, St) -> %%% the information from St#epp.uses is traversed, and if a circularity %%% is detected, an error message is thrown. -scan_define_cont(F, St, M, {Arity, Def}) -> +scan_define_cont(F, St, M, Arity, Def) -> Ms = dict:append_list(M, [{Arity, Def}], St#epp.macs), try dict:append_list(M, [{Arity, macro_uses(Def)}], St#epp.uses) of U -> diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 90642b2dca..4c007e76ad 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -811,6 +811,10 @@ otp_8130(Config) when is_list(Config) -> <<"\n-include(\"no such file.erl\").\n">>, {errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}}, + {otp_8130_c25, + <<"\n-define(A.\n">>, + {errors,[{{2,2},epp,{bad,define}}],[]}}, + {otp_8130_7, <<"-record(b, {b}).\n" "-define(A, {{a,#b.b.\n" -- cgit v1.2.3 From da6d480a65cce9392d4da80d142600f941d52881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Nov 2015 09:16:24 +0100 Subject: epp: Refactor user_predef/2 to share more code --- lib/stdlib/src/epp.erl | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index d9a579ebc6..87cffc9e16 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -593,16 +593,7 @@ user_predef([{M,Val}|Pdm], Ms) when is_atom(M) -> user_predef(Pdm, dict:store({atom,M}, [{none, {none,Exp}}], Ms)) end; user_predef([M|Pdm], Ms) when is_atom(M) -> - case dict:find({atom,M}, Ms) of - {ok,_Defs} when is_list(_Defs) -> %% User defined macros - {error,{redefine,M}}; - {ok,_Def} -> %% Predefined macros - {error,{redefine_predef,M}}; - error -> - A = line1(), - user_predef(Pdm, - dict:store({atom,M}, [{none, {none,[{atom,A,true}]}}], Ms)) - end; + user_predef([{M,true}|Pdm], Ms); user_predef([Md|_Pdm], _Ms) -> {error,{bad,Md}}; user_predef([], Ms) -> {ok,Ms}. -- cgit v1.2.3 From b6bbd00d6cdcc8418ee2385d719b0f12b7586198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Nov 2015 09:47:20 +0100 Subject: epp: Eliminate the Type argument from expand_macros/5 The Type argument is always 'atom', so there is no need for the argument. --- lib/stdlib/src/epp.erl | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 87cffc9e16..1d9762cfc7 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -1160,25 +1160,24 @@ macro_expansion([], Anno0) -> throw({error,loc(Anno0),premature_end}). %% Expand the macros in a list of tokens, making sure that an expansion %% gets the same location as the macro call. -expand_macros(Type, MacT, M, Toks, Ms0) -> - %% (Type will always be 'atom') +expand_macros(MacT, M, Toks, Ms0) -> {Ms, U} = Ms0, Lm = loc(MacT), Tinfo = element(2, MacT), - case expand_macro1(Type, Lm, M, Toks, Ms) of + case expand_macro1(Lm, M, Toks, Ms) of {ok,{none,Exp}} -> - check_uses([{{Type,M}, none}], [], U, Lm), + check_uses([{{atom,M}, none}], [], U, Lm), Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], dict:new()), Ms0), expand_macros(Toks1++Toks, Ms0); {ok,{As,Exp}} -> - check_uses([{{Type,M}, length(As)}], [], U, Lm), + check_uses([{{atom,M}, length(As)}], [], U, Lm), {Bs,Toks1} = bind_args(Toks, Lm, M, As, dict:new()), expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0) end. -expand_macro1(Type, Lm, M, Toks, Ms) -> +expand_macro1(Lm, M, Toks, Ms) -> Arity = count_args(Toks, Lm, M), - case dict:find({Type,M}, Ms) of + case dict:find({atom,M}, Ms) of error -> %% macro not found throw({error,Lm,{undefined,M,Arity}}); {ok, undefined} -> %% Predefined macro without definition @@ -1220,13 +1219,13 @@ get_macro_uses({M,Arity}, U) -> %% Macro expansion %% Note: io:scan_erl_form() does not return comments or white spaces. expand_macros([{'?',_Lq},{atom,_Lm,M}=MacT|Toks], Ms) -> - expand_macros(atom, MacT, M, Toks, Ms); + expand_macros(MacT, M, Toks, Ms); %% Special macros expand_macros([{'?',_Lq},{var,Lm,'LINE'}=Tok|Toks], Ms) -> Line = erl_scan:line(Tok), [{integer,Lm,Line}|expand_macros(Toks, Ms)]; expand_macros([{'?',_Lq},{var,_Lm,M}=MacT|Toks], Ms) -> - expand_macros(atom, MacT, M, Toks, Ms); + expand_macros(MacT, M, Toks, Ms); %% Illegal macros expand_macros([{'?',_Lq},Token|_Toks], _Ms) -> T = case erl_scan:text(Token) of -- cgit v1.2.3 From eefc4f1b40c8d1bd01abe3687c5f343cb838b0d5 Mon Sep 17 00:00:00 2001 From: Nico Kruber Date: Mon, 9 Nov 2015 20:35:26 +0100 Subject: jinterface: fix writing small compressed values This is a regression of 4390e43558 in the OtpOutputStream class. We can not call java.util.zip.DeflaterOutputStream.close() in the finally block of the OtpOutputStream.write_compressed(OtpErlangObject, int) method. This leads to a NullPointerException when encoding "{}" which is caused by the DeflaterOutputStream trying to write bytes to the deflater which was "destroyed" by calling java.util.zip.Deflater.end(). Further possibilities to call close() in the finally block are not suitable either (see the comment in the source). This leaves no choice but to revert the change from 4390e43558 in this class (and add an appropriate test case). --- .../com/ericsson/otp/erlang/OtpOutputStream.java | 23 +++++++++++++++------- lib/jinterface/test/nc_SUITE.erl | 2 ++ 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java index 2830a7842e..4faae2a157 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java @@ -922,8 +922,22 @@ public class OtpOutputStream extends ByteArrayOutputStream { oos.writeTo(dos); dos.close(); // note: closes this, too! } catch (final IllegalArgumentException e) { - // discard further un-compressed data - // -> if not called, there may be memory leaks! + /* + * Discard further un-compressed data (if not called, there may + * be memory leaks). + * + * After calling java.util.zip.Deflater.end(), the deflater + * should not be used anymore, not even the close() method of + * dos. Calling dos.close() before def.end() is prevented since + * an unfinished DeflaterOutputStream will try to deflate its + * unprocessed data to the (fixed) byte array which is prevented + * by ensureCapacity() and would also unnecessarily process + * further data that is discarded anyway. + * + * Since we are re-using the byte array of this object below, we + * must not call close() in e.g. a finally block either (with or + * without a call to def.end()). + */ def.end(); // could not make the value smaller than originally // -> reset to starting count, write uncompressed @@ -942,11 +956,6 @@ public class OtpOutputStream extends ByteArrayOutputStream { "Intermediate stream failed for Erlang object " + o); } finally { fixedSize = Integer.MAX_VALUE; - try { - dos.close(); - } catch (final IOException e) { - // ignore - } } } } diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl index 9679b90a0d..c5f3198c21 100644 --- a/lib/jinterface/test/nc_SUITE.erl +++ b/lib/jinterface/test/nc_SUITE.erl @@ -215,6 +215,7 @@ decompress_roundtrip(Config) when is_list(Config) -> 0.0, math:sqrt(2), <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>, + "{}", RandomBin1k, RandomBin1M, RandomBin10M, @@ -244,6 +245,7 @@ compress_roundtrip(Config) when is_list(Config) -> 0.0, math:sqrt(2), <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>, + "{}", RandomBin1k, RandomBin1M, RandomBin10M, -- cgit v1.2.3 From cfc8f82f1f39da114574a28c57f5d4a29ebbafaf Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 16 Nov 2015 19:40:24 +0100 Subject: crypto: Refactor nif code to use EVP interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the generic EVP_* API makes it possible to unify algorithm-specific nif functions to a single generic function. Effectively the same change that took place on the Erlang API in R16B01 is now applied to the C code. The old implementation using the low-level API is kept for compiling against old OpenSSL, as parts of the EVP API were introduced in OpenSSL 1.0.0. There are various minor improvements as well: - supported algorithms are now provided by the nif code (not a mix of the C and Erlang code) - remove unnecessary variables and macro definitions Most of the changes in this commit comes from Dániel Szoboszlay https://github.com/dszoboszlay/otp/commit/07f7056f955b324df4ace which is part of his 'fips' branch. Now also rebased on master branch. --- lib/crypto/c_src/crypto.c | 2532 +++++++++++++----------------------- lib/crypto/c_src/crypto_callback.c | 4 +- lib/crypto/src/crypto.erl | 849 ++++-------- 3 files changed, 1123 insertions(+), 2262 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index e9cac30c9c..595ee65415 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -193,57 +193,20 @@ static void unload(ErlNifEnv* env, void* priv_data); /* The NIFs: */ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -252,13 +215,10 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -270,10 +230,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -291,32 +247,7 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER /* helpers */ static void init_algorithms_types(ErlNifEnv*); static void init_digest_types(ErlNifEnv* env); -static void hmac_md5(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf); -static void hmac_sha1(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf); -#ifdef HAVE_SHA224 -static void hmac_sha224(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf); -#endif -#ifdef HAVE_SHA256 -static void hmac_sha256(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf); -#endif -#ifdef HAVE_SHA384 -static void hmac_sha384(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf); -#endif -#ifdef HAVE_SHA512 -static void hmac_sha512(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf); -#endif +static void init_cipher_types(ErlNifEnv* env); #ifdef HAVE_EC static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg); static int term2point(ErlNifEnv* env, ERL_NIF_TERM term, @@ -328,60 +259,25 @@ static int library_refc = 0; /* number of users of this dynamic library */ static ErlNifFunc nif_funcs[] = { {"info_lib", 0, info_lib}, {"algorithms", 0, algorithms}, - {"md5", 1, md5}, - {"md5_init", 0, md5_init}, - {"md5_update", 2, md5_update}, - {"md5_final", 1, md5_final}, - {"ripemd160", 1, ripemd160}, - {"ripemd160_init", 0, ripemd160_init}, - {"ripemd160_update", 2, ripemd160_update}, - {"ripemd160_final", 1, ripemd160_final}, - {"sha", 1, sha}, - {"sha_init", 0, sha_init}, - {"sha_update", 2, sha_update}, - {"sha_final", 1, sha_final}, - {"sha224_nif", 1, sha224_nif}, - {"sha224_init_nif", 0, sha224_init_nif}, - {"sha224_update_nif", 2, sha224_update_nif}, - {"sha224_final_nif", 1, sha224_final_nif}, - {"sha256_nif", 1, sha256_nif}, - {"sha256_init_nif", 0, sha256_init_nif}, - {"sha256_update_nif", 2, sha256_update_nif}, - {"sha256_final_nif", 1, sha256_final_nif}, - {"sha384_nif", 1, sha384_nif}, - {"sha384_init_nif", 0, sha384_init_nif}, - {"sha384_update_nif", 2, sha384_update_nif}, - {"sha384_final_nif", 1, sha384_final_nif}, - {"sha512_nif", 1, sha512_nif}, - {"sha512_init_nif", 0, sha512_init_nif}, - {"sha512_update_nif", 2, sha512_update_nif}, - {"sha512_final_nif", 1, sha512_final_nif}, - {"md4", 1, md4}, - {"md4_init", 0, md4_init}, - {"md4_update", 2, md4_update}, - {"md4_final", 1, md4_final}, - {"md5_mac_n", 3, md5_mac_n}, - {"sha_mac_n", 3, sha_mac_n}, - {"sha224_mac_nif", 3, sha224_mac_nif}, - {"sha256_mac_nif", 3, sha256_mac_nif}, - {"sha384_mac_nif", 3, sha384_mac_nif}, - {"sha512_mac_nif", 3, sha512_mac_nif}, - {"hmac_init", 2, hmac_init}, - {"hmac_update", 2, hmac_update}, - {"hmac_final", 1, hmac_final}, - {"hmac_final_n", 2, hmac_final}, - {"des_cbc_crypt", 4, des_cbc_crypt}, - {"des_cfb_crypt", 4, des_cfb_crypt}, - {"des_ecb_crypt", 3, des_ecb_crypt}, - {"des_ede3_cbc_crypt", 6, des_ede3_cbc_crypt}, - {"des_ede3_cfb_crypt_nif", 6, des_ede3_cfb_crypt_nif}, - {"aes_cfb_8_crypt", 4, aes_cfb_8_crypt}, - {"aes_cfb_128_crypt", 4, aes_cfb_128_crypt}, + {"hash_nif", 2, hash_nif}, + {"hash_init_nif", 1, hash_init_nif}, + {"hash_update_nif", 2, hash_update_nif}, + {"hash_final_nif", 1, hash_final_nif}, + {"hmac_nif", 3, hmac_nif}, + {"hmac_nif", 4, hmac_nif}, + {"hmac_init_nif", 2, hmac_init_nif}, + {"hmac_update_nif", 2, hmac_update_nif}, + {"hmac_final_nif", 1, hmac_final_nif}, + {"hmac_final_nif", 2, hmac_final_nif}, + {"block_crypt_nif", 5, block_crypt_nif}, + {"block_crypt_nif", 4, block_crypt_nif}, + {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif}, + {"aes_ctr_encrypt", 3, aes_ctr_encrypt}, {"aes_ctr_decrypt", 3, aes_ctr_encrypt}, + {"aes_ctr_stream_init", 2, aes_ctr_stream_init}, {"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt}, {"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt}, - {"aes_ecb_crypt", 3, aes_ecb_crypt}, {"rand_bytes", 1, rand_bytes_1}, {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif}, {"rand_bytes", 3, rand_bytes_3}, @@ -390,13 +286,10 @@ static ErlNifFunc nif_funcs[] = { {"mod_exp_nif", 4, mod_exp_nif}, {"dss_verify_nif", 4, dss_verify_nif}, {"rsa_verify_nif", 4, rsa_verify_nif}, - {"aes_cbc_crypt", 4, aes_cbc_crypt}, - {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif}, {"do_exor", 2, do_exor}, {"rc4_encrypt", 2, rc4_encrypt}, {"rc4_set_key", 1, rc4_set_key}, {"rc4_encrypt_with_state", 2, rc4_encrypt_with_state}, - {"rc2_cbc_crypt", 4, rc2_cbc_crypt}, {"rsa_sign_nif", 3, rsa_sign_nif}, {"dss_sign_nif", 3, dss_sign_nif}, {"rsa_public_crypt", 4, rsa_public_crypt}, @@ -408,10 +301,6 @@ static ErlNifFunc nif_funcs[] = { {"srp_value_B_nif", 5, srp_value_B_nif}, {"srp_user_secret_nif", 7, srp_user_secret_nif}, {"srp_host_secret_nif", 5, srp_host_secret_nif}, - {"bf_cfb64_crypt", 4, bf_cfb64_crypt}, - {"bf_cbc_crypt", 4, bf_cbc_crypt}, - {"bf_ecb_crypt", 3, bf_ecb_crypt}, - {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt}, {"ec_key_generate", 2, ec_key_generate}, {"ecdsa_sign_nif", 4, ecdsa_sign_nif}, @@ -432,37 +321,14 @@ static ErlNifFunc nif_funcs[] = { ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) -#define MD5_CTX_LEN (sizeof(MD5_CTX)) -#define MD5_LEN 16 -#define MD5_LEN_96 12 -#define MD4_CTX_LEN (sizeof(MD4_CTX)) -#define MD4_LEN 16 +#define MD5_CTX_LEN (sizeof(MD5_CTX)) +#define MD4_CTX_LEN (sizeof(MD4_CTX)) #define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX)) -#define RIPEMD160_LEN 20 -#define SHA_CTX_LEN (sizeof(SHA_CTX)) -#define SHA_LEN 20 -#define SHA_LEN_96 12 -#define SHA224_LEN (224/8) -#define SHA256_LEN (256/8) -#define SHA384_LEN (384/8) -#define SHA512_LEN (512/8) -#define HMAC_INT_LEN 64 -#define HMAC_INT2_LEN 128 - -#define HMAC_IPAD 0x36 -#define HMAC_OPAD 0x5c static ERL_NIF_TERM atom_true; static ERL_NIF_TERM atom_false; static ERL_NIF_TERM atom_sha; -static ERL_NIF_TERM atom_sha224; -static ERL_NIF_TERM atom_sha256; -static ERL_NIF_TERM atom_sha384; -static ERL_NIF_TERM atom_sha512; -static ERL_NIF_TERM atom_md5; -static ERL_NIF_TERM atom_md4; -static ERL_NIF_TERM atom_ripemd160; static ERL_NIF_TERM atom_error; static ERL_NIF_TERM atom_rsa_pkcs1_padding; static ERL_NIF_TERM atom_rsa_pkcs1_oaep_padding; @@ -489,6 +355,9 @@ static ERL_NIF_TERM atom_ppbasis; static ERL_NIF_TERM atom_onbasis; #endif +static ERL_NIF_TERM atom_aes_cfb8; +static ERL_NIF_TERM atom_aes_cfb128; + static ErlNifResourceType* hmac_context_rtype; struct hmac_context { @@ -498,6 +367,87 @@ struct hmac_context }; static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*); +struct digest_type_t { + const char* type_str; + const EVP_MD* (*md_func)(void); /* NULL if notsup */ + ERL_NIF_TERM type_atom; +}; + +struct digest_type_t digest_types[] = +{ + {"md4", &EVP_md4}, + {"md5", &EVP_md5}, + {"ripemd160", &EVP_ripemd160}, + {"sha", &EVP_sha1}, + {"sha224", +#ifdef HAVE_SHA224 + &EVP_sha224 +#else + NULL +#endif + }, + {"sha256", +#ifdef HAVE_SHA256 + &EVP_sha256 +#else + NULL +#endif + }, + {"sha384", +#ifdef HAVE_SHA384 + &EVP_sha384 +#else + NULL +#endif + }, + {"sha512", +#ifdef HAVE_SHA512 + &EVP_sha512 +#else + NULL +#endif + }, + {NULL} +}; + +static struct digest_type_t* get_digest_type(ERL_NIF_TERM type); + +struct cipher_type_t { + const char* type_str; + const EVP_CIPHER* (*cipher_func)(void); /* NULL if notsup */ + const size_t key_len; /* != 0 to also match on key_len */ + ERL_NIF_TERM type_atom; +}; + +struct cipher_type_t cipher_types[] = +{ + {"rc2_cbc", &EVP_rc2_cbc}, + {"des_cbc", &EVP_des_cbc}, + {"des_cfb", &EVP_des_cfb8}, + {"des_ecb", &EVP_des_ecb}, + {"des_ede3_cbc", &EVP_des_ede3_cbc}, + {"des_ede3_cbf", +#ifdef HAVE_DES_ede3_cfb_encrypt + &EVP_des_ede3_cfb8 +#else + NULL +#endif + }, + {"blowfish_cbc", &EVP_bf_cbc}, + {"blowfish_cfb64", &EVP_bf_cfb64}, + {"blowfish_ofb64", &EVP_bf_ofb}, + {"blowfish_ecb", &EVP_bf_ecb}, + {"aes_cbc128", &EVP_aes_128_cbc}, + {"aes_cbc256", &EVP_aes_256_cbc}, + {"aes_cfb8", &EVP_aes_128_cfb8}, + {"aes_cfb128", &EVP_aes_128_cfb128}, + {"aes_ecb", &EVP_aes_128_ecb, 16}, + {"aes_ecb", &EVP_aes_256_ecb, 32}, + {NULL} +}; + +static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len); + /* #define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n") #define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1) @@ -507,6 +457,19 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*); #define PRINTF_ERR1(FMT,A1) #define PRINTF_ERR2(FMT,A1,A2) +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL +/* Define resource types for OpenSSL context structures. */ +static ErlNifResourceType* evp_md_ctx_rtype; +static void evp_md_ctx_dtor(ErlNifEnv* env, EVP_MD_CTX* ctx) { + EVP_MD_CTX_cleanup(ctx); +} + +static ErlNifResourceType* evp_cipher_ctx_rtype; +static void evp_cipher_ctx_dtor(ErlNifEnv* env, EVP_CIPHER_CTX* ctx) { + EVP_CIPHER_CTX_cleanup(ctx); +} +#endif + static int verify_lib_version(void) { const unsigned long libv = SSLeay(); @@ -522,7 +485,6 @@ static int verify_lib_version(void) return 1; } - #ifdef HAVE_DYNAMIC_CRYPTO_LIB # if defined(DEBUG) @@ -558,7 +520,9 @@ static void error_handler(void* null, const char* errstr) static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) { +#ifdef OPENSSL_THREADS ErlNifSysInfo sys_info; +#endif get_crypto_callbacks_t* funcp; struct crypto_callbacks* ccb; int nlocks = 0; @@ -590,7 +554,24 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'"); return 0; } - +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX", + (ErlNifResourceDtor*) evp_md_ctx_dtor, + ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, + NULL); + if (!evp_md_ctx_rtype) { + PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'"); + return 0; + } + evp_cipher_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_CIPHER_CTX", + (ErlNifResourceDtor*) evp_cipher_ctx_dtor, + ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, + NULL); + if (!evp_cipher_ctx_rtype) { + PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'"); + return 0; + } +#endif if (library_refc > 0) { /* Repeated loading of this library (module upgrade). * Atoms and callbacks are already set, we are done. @@ -598,16 +579,9 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) return 1; } - atom_true = enif_make_atom(env,"true"); + atom_true = enif_make_atom(env,"true"); atom_false = enif_make_atom(env,"false"); atom_sha = enif_make_atom(env,"sha"); - atom_sha224 = enif_make_atom(env,"sha224"); - atom_sha256 = enif_make_atom(env,"sha256"); - atom_sha384 = enif_make_atom(env,"sha384"); - atom_sha512 = enif_make_atom(env,"sha512"); - atom_md4 = enif_make_atom(env,"md4"); - atom_md5 = enif_make_atom(env,"md5"); - atom_ripemd160 = enif_make_atom(env,"ripemd160"); atom_error = enif_make_atom(env,"error"); atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding"); atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding"); @@ -632,8 +606,11 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) atom_ppbasis = enif_make_atom(env,"ppbasis"); atom_onbasis = enif_make_atom(env,"onbasis"); #endif + atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8"); + atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128"); init_digest_types(env); + init_cipher_types(env); init_algorithms_types(env); #ifdef HAVE_DYNAMIC_CRYPTO_LIB @@ -718,46 +695,66 @@ static void unload(ErlNifEnv* env, void* priv_data) static int algo_hash_cnt; static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */ static int algo_pubkey_cnt; -static ERL_NIF_TERM algo_pubkey[3]; /* increase when extending the list */ +static ERL_NIF_TERM algo_pubkey[7]; /* increase when extending the list */ static int algo_cipher_cnt; -static ERL_NIF_TERM algo_cipher[4]; /* increase when extending the list */ +static ERL_NIF_TERM algo_cipher[20]; /* increase when extending the list */ static void init_algorithms_types(ErlNifEnv* env) { algo_hash_cnt = 0; - algo_hash[algo_hash_cnt++] = atom_md4; - algo_hash[algo_hash_cnt++] = atom_md5; algo_hash[algo_hash_cnt++] = atom_sha; - algo_hash[algo_hash_cnt++] = atom_ripemd160; #ifdef HAVE_SHA224 - algo_hash[algo_hash_cnt++] = atom_sha224; + algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha224"); #endif #ifdef HAVE_SHA256 - algo_hash[algo_hash_cnt++] = atom_sha256; + algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha256"); #endif #ifdef HAVE_SHA384 - algo_hash[algo_hash_cnt++] = atom_sha384; + algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha384"); #endif #ifdef HAVE_SHA512 - algo_hash[algo_hash_cnt++] = atom_sha512; + algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512"); #endif + algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4"); + algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md5"); + algo_hash[algo_hash_cnt++] = enif_make_atom(env, "ripemd160"); algo_pubkey_cnt = 0; + algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "rsa"); + algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dss"); + algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dh"); #if defined(HAVE_EC) #if !defined(OPENSSL_NO_EC2M) - algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ec_gf2m"); + algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ec_gf2m"); #endif - algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdsa"); - algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdh"); + algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdsa"); + algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdh"); #endif + algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp"); algo_cipher_cnt = 0; + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbc"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des_ede3"); #ifdef HAVE_DES_ede3_cfb_encrypt algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbf"); #endif + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc128"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc256"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ctr"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ecb"); #ifdef HAVE_AES_IGE algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ige256"); #endif + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cbc"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cfb"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cbc"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cfb64"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ofb64"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ecb"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc2_cbc"); + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc4"); #if defined(HAVE_GCM) algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm"); #endif @@ -772,10 +769,13 @@ static void init_algorithms_types(ErlNifEnv* env) static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + int hash_cnt = algo_hash_cnt; + int pubkey_cnt = algo_pubkey_cnt; + int cipher_cnt = algo_cipher_cnt; return enif_make_tuple3(env, - enif_make_list_from_array(env, algo_hash, algo_hash_cnt), - enif_make_list_from_array(env, algo_pubkey, algo_pubkey_cnt), - enif_make_list_from_array(env, algo_cipher, algo_cipher_cnt)); + enif_make_list_from_array(env, algo_hash, hash_cnt), + enif_make_list_from_array(env, algo_pubkey, pubkey_cnt), + enif_make_list_from_array(env, algo_cipher, cipher_cnt)); } static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -805,564 +805,383 @@ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] ver_term)); } -static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); - } - MD5((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,MD5_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -} -static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ - ERL_NIF_TERM ret; - MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret)); - return ret; -} -static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context, Data) */ - MD5_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) - || ctx_bin.size != MD5_CTX_LEN - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { +static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type, Data) */ + struct digest_type_t *digp = NULL; + const EVP_MD *md; + ErlNifBinary data; + ERL_NIF_TERM ret; + unsigned ret_size; + + digp = get_digest_type(argv[0]); + if (!digp || + !enif_inspect_iolist_as_binary(env, argv[1], &data)) { return enif_make_badarg(env); } - new_ctx = (MD5_CTX*) enif_make_new_binary(env,MD5_CTX_LEN, &ret); - memcpy(new_ctx, ctx_bin.data, MD5_CTX_LEN); - MD5_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env,data_bin); - return ret; -} -static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context) */ - ErlNifBinary ctx_bin; - MD5_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) { - return enif_make_badarg(env); + if (!digp->md_func) { + return atom_notsup; } - memcpy(&ctx_clone, ctx_bin.data, MD5_CTX_LEN); /* writable */ - MD5_Final(enif_make_new_binary(env, MD5_LEN, &ret), &ctx_clone); - return ret; -} -static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); + md = digp->md_func(); + ret_size = (unsigned)EVP_MD_size(md); + ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE); + if (!EVP_Digest(data.data, data.size, + enif_make_new_binary(env, ret_size, &ret), &ret_size, + md, NULL)) { + return atom_notsup; } - RIPEMD160((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,RIPEMD160_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -} -static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ - ERL_NIF_TERM ret; - RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret)); + ASSERT(ret_size == (unsigned)EVP_MD_size(md)); + + CONSUME_REDS(env, data); return ret; } -static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context, Data) */ - RIPEMD160_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) - || ctx_bin.size != RIPEMD160_CTX_LEN - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { + +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + +static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type) */ + struct digest_type_t *digp = NULL; + EVP_MD_CTX *ctx; + ERL_NIF_TERM ret; + + digp = get_digest_type(argv[0]); + if (!digp) { return enif_make_badarg(env); } - new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret); - memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN); - RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env, data_bin); - return ret; -} -static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context) */ - ErlNifBinary ctx_bin; - RIPEMD160_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) { - return enif_make_badarg(env); + if (!digp->md_func) { + return atom_notsup; } - memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */ - RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone); - return ret; -} - -static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); + ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX)); + if (!EVP_DigestInit(ctx, digp->md_func())) { + enif_release_resource(ctx); + return atom_notsup; } - SHA1((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,SHA_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -} -static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ - ERL_NIF_TERM ret; - SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret)); + ret = enif_make_resource(env, ctx); + enif_release_resource(ctx); return ret; } -static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context, Data) */ - SHA_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; + EVP_MD_CTX *ctx, *new_ctx; + ErlNifBinary data; ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); + + if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx) || + !enif_inspect_iolist_as_binary(env, argv[1], &data)) { + return enif_make_badarg(env); } - new_ctx = (SHA_CTX*) enif_make_new_binary(env,SHA_CTX_LEN, &ret); - memcpy(new_ctx, ctx_bin.data, SHA_CTX_LEN); - SHA1_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env,data_bin); + + new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX)); + if (!EVP_MD_CTX_copy(new_ctx, ctx) || + !EVP_DigestUpdate(new_ctx, data.data, data.size)) { + enif_release_resource(new_ctx); + return atom_notsup; + } + + ret = enif_make_resource(env, new_ctx); + enif_release_resource(new_ctx); + CONSUME_REDS(env, data); return ret; } -static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context) */ - ErlNifBinary ctx_bin; - SHA_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) { - return enif_make_badarg(env); + EVP_MD_CTX *ctx, new_ctx; + ERL_NIF_TERM ret; + unsigned ret_size; + + if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) { + return enif_make_badarg(env); } - memcpy(&ctx_clone, ctx_bin.data, SHA_CTX_LEN); /* writable */ - SHA1_Final(enif_make_new_binary(env, SHA_LEN, &ret), &ctx_clone); - return ret; -} -static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ -#ifdef HAVE_SHA224 - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); + ret_size = (unsigned)EVP_MD_CTX_size(ctx); + ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE); + + if (!EVP_MD_CTX_copy(&new_ctx, ctx) || + !EVP_DigestFinal(&new_ctx, + enif_make_new_binary(env, ret_size, &ret), + &ret_size)) { + return atom_notsup; } - SHA224((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,SHA224_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -#else - return atom_notsup; -#endif -} -static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ -#ifdef HAVE_SHA224 - ERL_NIF_TERM ret; - SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); + ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx)); + return ret; -#else - return atom_notsup; -#endif } -static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context, Data) */ -#ifdef HAVE_SHA224 - SHA256_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { + +#else /* if OPENSSL_VERSION_NUMBER < 1.0 */ + +static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type) */ + typedef int (*init_fun)(unsigned char*); + struct digest_type_t *digp = NULL; + ERL_NIF_TERM ctx; + size_t ctx_size = 0; + init_fun ctx_init = 0; + + digp = get_digest_type(argv[0]); + if (!digp) { return enif_make_badarg(env); } - new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret); - memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX)); - SHA224_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env,data_bin); - return ret; -#else - return atom_notsup; -#endif -} -static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context) */ -#ifdef HAVE_SHA224 - ErlNifBinary ctx_bin; - SHA256_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { - return enif_make_badarg(env); + if (!digp->md_func) { + return atom_notsup; } - memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */ - SHA224_Final(enif_make_new_binary(env, SHA224_LEN, &ret), &ctx_clone); - return ret; -#else - return atom_notsup; -#endif -} -static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ -#ifdef HAVE_SHA256 - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); - } - SHA256((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,SHA256_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -#else - return atom_notsup; + switch (EVP_MD_type(digp->md_func())) + { + case NID_md4: + ctx_size = MD4_CTX_LEN; + ctx_init = (init_fun)(&MD4_Init); + break; + case NID_md5: + ctx_size = MD5_CTX_LEN; + ctx_init = (init_fun)(&MD5_Init); + break; + case NID_ripemd160: + ctx_size = RIPEMD160_CTX_LEN; + ctx_init = (init_fun)(&RIPEMD160_Init); + break; + case NID_sha1: + ctx_size = sizeof(SHA_CTX); + ctx_init = (init_fun)(&SHA1_Init); + break; +#ifdef HAVE_SHA224 + case NID_sha224: + ctx_size = sizeof(SHA256_CTX); + ctx_init = (init_fun)(&SHA224_Init); + break; #endif -} -static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ #ifdef HAVE_SHA256 - ERL_NIF_TERM ret; - SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); - return ret; -#else - return atom_notsup; + case NID_sha256: + ctx_size = sizeof(SHA256_CTX); + ctx_init = (init_fun)(&SHA256_Init); + break; #endif -} -static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context, Data) */ -#ifdef HAVE_SHA256 - SHA256_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); +#ifdef HAVE_SHA384 + case NID_sha384: + ctx_size = sizeof(SHA512_CTX); + ctx_init = (init_fun)(&SHA384_Init); + break; +#endif +#ifdef HAVE_SHA512 + case NID_sha512: + ctx_size = sizeof(SHA512_CTX); + ctx_init = (init_fun)(&SHA512_Init); + break; +#endif + default: + return atom_notsup; + } + ASSERT(ctx_size); + ASSERT(ctx_init); + + ctx_init(enif_make_new_binary(env, ctx_size, &ctx)); + return enif_make_tuple2(env, argv[0], ctx); +} +static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* ({Type, Context}, Data) */ + typedef int (*update_fun)(unsigned char*, const unsigned char*, size_t); + ERL_NIF_TERM new_ctx; + ErlNifBinary ctx, data; + const ERL_NIF_TERM *tuple; + int arity; + struct digest_type_t *digp = NULL; + unsigned char *ctx_buff; + size_t ctx_size = 0; + update_fun ctx_update = 0; + + if (!enif_get_tuple(env, argv[0], &arity, &tuple) || + arity != 2 || + !(digp = get_digest_type(tuple[0])) || + !enif_inspect_binary(env, tuple[1], &ctx) || + !enif_inspect_iolist_as_binary(env, argv[1], &data)) { + return enif_make_badarg(env); } - new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret); - memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX)); - SHA256_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env,data_bin); - return ret; -#else - return atom_notsup; + if (!digp->md_func) { + return atom_notsup; + } + + switch (EVP_MD_type(digp->md_func())) + { + case NID_md4: + ctx_size = MD4_CTX_LEN; + ctx_update = (update_fun)(&MD4_Update); + break; + case NID_md5: + ctx_size = MD5_CTX_LEN; + ctx_update = (update_fun)(&MD5_Update); + break; + case NID_ripemd160: + ctx_size = RIPEMD160_CTX_LEN; + ctx_update = (update_fun)(&RIPEMD160_Update); + break; + case NID_sha1: + ctx_size = sizeof(SHA_CTX); + ctx_update = (update_fun)(&SHA1_Update); + break; +#ifdef HAVE_SHA224 + case NID_sha224: + ctx_size = sizeof(SHA256_CTX); + ctx_update = (update_fun)(&SHA224_Update); + break; #endif -} -static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context) */ #ifdef HAVE_SHA256 - ErlNifBinary ctx_bin; - SHA256_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) { - return enif_make_badarg(env); - } - memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */ - SHA256_Final(enif_make_new_binary(env, SHA256_LEN, &ret), &ctx_clone); - return ret; -#else - return atom_notsup; + case NID_sha256: + ctx_size = sizeof(SHA256_CTX); + ctx_update = (update_fun)(&SHA256_Update); + break; #endif -} - -static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ #ifdef HAVE_SHA384 - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); - } - SHA384((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,SHA384_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -#else - return atom_notsup; + case NID_sha384: + ctx_size = sizeof(SHA512_CTX); + ctx_update = (update_fun)(&SHA384_Update); + break; #endif -} -static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ -#ifdef HAVE_SHA384 - ERL_NIF_TERM ret; - SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret)); - return ret; -#else - return atom_notsup; +#ifdef HAVE_SHA512 + case NID_sha512: + ctx_size = sizeof(SHA512_CTX); + ctx_update = (update_fun)(&SHA512_Update); + break; #endif -} -static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context, Data) */ -#ifdef HAVE_SHA384 - SHA512_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); + default: + return atom_notsup; } - new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret); - memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX)); - SHA384_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env,data_bin); - return ret; -#else - return atom_notsup; -#endif -} -static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context) */ -#ifdef HAVE_SHA384 - ErlNifBinary ctx_bin; - SHA512_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { - return enif_make_badarg(env); + ASSERT(ctx_size); + ASSERT(ctx_update); + + if (ctx.size != ctx_size) { + return enif_make_badarg(env); } - memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */ - SHA384_Final(enif_make_new_binary(env, SHA384_LEN, &ret), &ctx_clone); - return ret; -#else - return atom_notsup; -#endif -} -static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ -#ifdef HAVE_SHA512 - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); + ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx); + memcpy(ctx_buff, ctx.data, ctx_size); + ctx_update(ctx_buff, data.data, data.size); + + CONSUME_REDS(env, data); + return enif_make_tuple2(env, tuple[0], new_ctx); +} +static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* ({Type, Context}) */ + typedef int (*final_fun)(unsigned char*, void*); + ERL_NIF_TERM ret; + ErlNifBinary ctx; + const ERL_NIF_TERM *tuple; + int arity; + struct digest_type_t *digp = NULL; + const EVP_MD *md; + void *new_ctx; + size_t ctx_size = 0; + final_fun ctx_final = 0; + + if (!enif_get_tuple(env, argv[0], &arity, &tuple) || + arity != 2 || + !(digp = get_digest_type(tuple[0])) || + !enif_inspect_binary(env, tuple[1], &ctx)) { + return enif_make_badarg(env); } - SHA512((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,SHA512_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -#else - return atom_notsup; + if (!digp->md_func) { + return atom_notsup; + } + + md = digp->md_func(); + + switch (EVP_MD_type(md)) + { + case NID_md4: + ctx_size = MD4_CTX_LEN; + ctx_final = (final_fun)(&MD4_Final); + break; + case NID_md5: + ctx_size = MD5_CTX_LEN; + ctx_final = (final_fun)(&MD5_Final); + break; + case NID_ripemd160: + ctx_size = RIPEMD160_CTX_LEN; + ctx_final = (final_fun)(&RIPEMD160_Final); + break; + case NID_sha1: + ctx_size = sizeof(SHA_CTX); + ctx_final = (final_fun)(&SHA1_Final); + break; +#ifdef HAVE_SHA224 + case NID_sha224: + ctx_size = sizeof(SHA256_CTX); + ctx_final = (final_fun)(&SHA224_Final); + break; #endif -} -static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ -#ifdef HAVE_SHA512 - ERL_NIF_TERM ret; - SHA512_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret)); - return ret; -#else - return atom_notsup; +#ifdef HAVE_SHA256 + case NID_sha256: + ctx_size = sizeof(SHA256_CTX); + ctx_final = (final_fun)(&SHA256_Final); + break; #endif -} -static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context, Data) */ -#ifdef HAVE_SHA512 - SHA512_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); - } - new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret); - memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX)); - SHA512_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env,data_bin); - return ret; -#else - return atom_notsup; +#ifdef HAVE_SHA384 + case NID_sha384: + ctx_size = sizeof(SHA512_CTX); + ctx_final = (final_fun)(&SHA384_Final); + break; #endif -} -static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context) */ #ifdef HAVE_SHA512 - ErlNifBinary ctx_bin; - SHA512_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) { - return enif_make_badarg(env); - } - memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */ - SHA512_Final(enif_make_new_binary(env, SHA512_LEN, &ret), &ctx_clone); - return ret; -#else - return atom_notsup; + case NID_sha512: + ctx_size = sizeof(SHA512_CTX); + ctx_final = (final_fun)(&SHA512_Final); + break; #endif -} - - -static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Data) */ - ErlNifBinary ibin; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { - return enif_make_badarg(env); + default: + return atom_notsup; } - MD4((unsigned char *) ibin.data, ibin.size, - enif_make_new_binary(env,MD4_LEN, &ret)); - CONSUME_REDS(env,ibin); - return ret; -} -static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* () */ - ERL_NIF_TERM ret; - MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret)); - return ret; -} -static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context, Data) */ - MD4_CTX* new_ctx; - ErlNifBinary ctx_bin, data_bin; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); - } - new_ctx = (MD4_CTX*) enif_make_new_binary(env,MD4_CTX_LEN, &ret); - memcpy(new_ctx, ctx_bin.data, MD4_CTX_LEN); - MD4_Update(new_ctx, data_bin.data, data_bin.size); - CONSUME_REDS(env,data_bin); - return ret; -} -static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Context) */ - ErlNifBinary ctx_bin; - MD4_CTX ctx_clone; - ERL_NIF_TERM ret; - if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) { - return enif_make_badarg(env); - } - memcpy(&ctx_clone, ctx_bin.data, MD4_CTX_LEN); /* writable */ - MD4_Final(enif_make_new_binary(env, MD4_LEN, &ret), &ctx_clone); - return ret; -} + ASSERT(ctx_size); + ASSERT(ctx_final); -static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, MacSize) */ - unsigned char hmacbuf[SHA_DIGEST_LENGTH]; - ErlNifBinary key, data; - unsigned mac_sz; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !enif_inspect_iolist_as_binary(env, argv[1], &data) - || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) { - return enif_make_badarg(env); + if (ctx.size != ctx_size) { + return enif_make_badarg(env); } - hmac_md5(key.data, key.size, data.data, data.size, hmacbuf); - memcpy(enif_make_new_binary(env, mac_sz, &ret), hmacbuf, mac_sz); - CONSUME_REDS(env,data); - return ret; -} -static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, MacSize) */ - unsigned char hmacbuf[SHA_DIGEST_LENGTH]; - ErlNifBinary key, data; - unsigned mac_sz; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !enif_inspect_iolist_as_binary(env, argv[1], &data) - || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) { - return enif_make_badarg(env); - } - hmac_sha1(key.data, key.size, data.data, data.size, hmacbuf); - memcpy(enif_make_new_binary(env, mac_sz, &ret), - hmacbuf, mac_sz); - CONSUME_REDS(env,data); - return ret; -} + new_ctx = enif_alloc(ctx_size); + memcpy(new_ctx, ctx.data, ctx_size); + ctx_final(enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret), + new_ctx); + enif_free(new_ctx); -static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, MacSize) */ -#ifdef HAVE_SHA224 - unsigned char hmacbuf[SHA224_DIGEST_LENGTH]; - ErlNifBinary key, data; - unsigned mac_sz; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !enif_inspect_iolist_as_binary(env, argv[1], &data) - || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) { - return enif_make_badarg(env); - } - hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf); - memcpy(enif_make_new_binary(env, mac_sz, &ret), - hmacbuf, mac_sz); - CONSUME_REDS(env,data); return ret; -#else - return atom_notsup; -#endif } +#endif /* OPENSSL_VERSION_NUMBER < 1.0 */ -static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, MacSize) */ -#ifdef HAVE_SHA256 - unsigned char hmacbuf[SHA256_DIGEST_LENGTH]; - ErlNifBinary key, data; - unsigned mac_sz; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !enif_inspect_iolist_as_binary(env, argv[1], &data) - || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) { - return enif_make_badarg(env); - } - hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf); - memcpy(enif_make_new_binary(env, mac_sz, &ret), - hmacbuf, mac_sz); - CONSUME_REDS(env,data); - return ret; -#else - return atom_notsup; -#endif -} +static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type, Key, Data) or (Type, Key, Data, MacSize) */ + struct digest_type_t *digp = NULL; + ErlNifBinary key, data; + unsigned char buff[EVP_MAX_MD_SIZE]; + unsigned size = 0, req_size = 0; + ERL_NIF_TERM ret; -static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, MacSize) */ -#ifdef HAVE_SHA384 - unsigned char hmacbuf[SHA384_DIGEST_LENGTH]; - ErlNifBinary key, data; - unsigned mac_sz; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !enif_inspect_iolist_as_binary(env, argv[1], &data) - || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) { - return enif_make_badarg(env); + digp = get_digest_type(argv[0]); + if (!digp || + !enif_inspect_iolist_as_binary(env, argv[1], &key) || + !enif_inspect_iolist_as_binary(env, argv[2], &data) || + (argc == 4 && !enif_get_uint(env, argv[3], &req_size))) { + return enif_make_badarg(env); } - hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf); - memcpy(enif_make_new_binary(env, mac_sz, &ret), - hmacbuf, mac_sz); - CONSUME_REDS(env,data); - return ret; -#else - return atom_notsup; -#endif -} + if (!digp->md_func || + !HMAC(digp->md_func(), + key.data, key.size, + data.data, data.size, + buff, &size)) { + return atom_notsup; + } + ASSERT(0 < size && size <= EVP_MAX_MD_SIZE); + CONSUME_REDS(env, data); -static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, MacSize) */ -#ifdef HAVE_SHA512 - unsigned char hmacbuf[SHA512_DIGEST_LENGTH]; - ErlNifBinary key, data; - unsigned mac_sz; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !enif_inspect_iolist_as_binary(env, argv[1], &data) - || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) { - return enif_make_badarg(env); + if (argc == 4) { + if (req_size <= size) { + size = req_size; + } + else { + return enif_make_badarg(env); + } } - hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf); - memcpy(enif_make_new_binary(env, mac_sz, &ret), - hmacbuf, mac_sz); - CONSUME_REDS(env,data); + memcpy(enif_make_new_binary(env, size, &ret), buff, size); return ret; -#else - return atom_notsup; -#endif } static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj) @@ -1374,53 +1193,46 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj) enif_mutex_destroy(obj->mtx); } -static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Type, Key) */ - ErlNifBinary key; - struct hmac_context* obj; - const EVP_MD *md; - ERL_NIF_TERM ret; - + struct digest_type_t *digp = NULL; + ErlNifBinary key; + ERL_NIF_TERM ret; + struct hmac_context *obj; - if (argv[0] == atom_sha) md = EVP_sha1(); -#ifdef HAVE_SHA224 - else if (argv[0] == atom_sha224) md = EVP_sha224(); -#endif -#ifdef HAVE_SHA256 - else if (argv[0] == atom_sha256) md = EVP_sha256(); -#endif -#ifdef HAVE_SHA384 - else if (argv[0] == atom_sha384) md = EVP_sha384(); -#endif -#ifdef HAVE_SHA512 - else if (argv[0] == atom_sha512) md = EVP_sha512(); -#endif - else if (argv[0] == atom_md5) md = EVP_md5(); - else if (argv[0] == atom_ripemd160) md = EVP_ripemd160(); - else goto badarg; - - if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) { - badarg: - return enif_make_badarg(env); + digp = get_digest_type(argv[0]); + if (!digp || + !enif_inspect_iolist_as_binary(env, argv[1], &key)) { + return enif_make_badarg(env); + } + if (!digp->md_func) { + return atom_notsup; } obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context)); obj->mtx = enif_mutex_create("crypto.hmac"); obj->alive = 1; - HMAC_CTX_init(&obj->ctx); - HMAC_Init(&obj->ctx, key.data, key.size, md); +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + // Check the return value of HMAC_Init: it may fail in FIPS mode + // for disabled algorithms + if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func())) { + enif_release_resource(obj); + return atom_notsup; + } +#else + HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func()); +#endif ret = enif_make_resource(env, obj); enif_release_resource(obj); return ret; } -static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context, Data) */ ErlNifBinary data; struct hmac_context* obj; - if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj) || !enif_inspect_iolist_as_binary(env, argv[1], &data)) { return enif_make_badarg(env); @@ -1437,7 +1249,7 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg return argv[0]; } -static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context) or (Context, HashLen) */ ERL_NIF_TERM ret; struct hmac_context* obj; @@ -1446,7 +1258,6 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv unsigned int req_len = 0; unsigned int mac_len; - if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj) || (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) { return enif_make_badarg(env); @@ -1473,199 +1284,185 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv return ret; } -static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Ivec, Text, IsEncrypt) */ - ErlNifBinary key, ivec, text; - DES_key_schedule schedule; - DES_cblock ivec_clone; /* writable copy */ - ERL_NIF_TERM ret; - +static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */ + struct cipher_type_t *cipherp = NULL; + const EVP_CIPHER *cipher; + ErlNifBinary key, ivec, text; + EVP_CIPHER_CTX ctx; + ERL_NIF_TERM ret; + unsigned char *out; + int ivec_size, out_size = 0; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 - || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &text) - || text.size % 8 != 0) { - return enif_make_badarg(env); + if (!enif_inspect_iolist_as_binary(env, argv[1], &key) + || !(cipherp = get_cipher_type(argv[0], key.size)) + || !enif_inspect_iolist_as_binary(env, argv[argc - 2], &text)) { + return enif_make_badarg(env); } - memcpy(&ivec_clone, ivec.data, 8); - DES_set_key((const_DES_cblock*)key.data, &schedule); - DES_ncbc_encrypt(text.data, enif_make_new_binary(env, text.size, &ret), - text.size, &schedule, &ivec_clone, (argv[3] == atom_true)); - CONSUME_REDS(env,text); - return ret; -} - -static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Ivec, Text, IsEncrypt) */ - ErlNifBinary key, ivec, text; - DES_key_schedule schedule; - DES_cblock ivec_clone; /* writable copy */ - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 - || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { - return enif_make_badarg(env); + if (!cipherp->cipher_func) { + return enif_raise_exception(env, atom_notsup); } - memcpy(&ivec_clone, ivec.data, 8); - DES_set_key((const_DES_cblock*)key.data, &schedule); - DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret), - 8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true)); - CONSUME_REDS(env,text); - return ret; -} -static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Text/Cipher, IsEncrypt) */ - ErlNifBinary key, text; - DES_key_schedule schedule; - ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 || - !enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) { - return enif_make_badarg(env); + if ((argv[0] == atom_aes_cfb8 || argv[0] == atom_aes_cfb128) + && (key.size == 24 || key.size == 32)) { + /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes? + * Fall back on low level API + */ + return aes_cfb_8_crypt(env, argc-1, argv+1); } - DES_set_key((const_DES_cblock*)key.data, &schedule); - DES_ecb_encrypt((const_DES_cblock*)text.data, - (DES_cblock*)enif_make_new_binary(env, 8, &ret), - &schedule, (argv[2] == atom_true)); - CONSUME_REDS(env,text); - return ret; -} - -static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */ - ErlNifBinary key1, key2, key3, ivec, text; - DES_key_schedule schedule1, schedule2, schedule3; - DES_cblock ivec_clone; /* writable copy */ - ERL_NIF_TERM ret; + cipher = cipherp->cipher_func(); + ivec_size = EVP_CIPHER_iv_length(cipher); - if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8 - || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[4], &text) - || text.size % 8 != 0) { - return enif_make_badarg(env); + if (text.size % EVP_CIPHER_block_size(cipher) != 0 || + (ivec_size == 0 ? argc != 4 + : (argc != 5 || + !enif_inspect_iolist_as_binary(env, argv[2], &ivec) || + ivec.size != ivec_size))) { + return enif_make_badarg(env); } - memcpy(&ivec_clone, ivec.data, 8); - DES_set_key((const_DES_cblock*)key1.data, &schedule1); - DES_set_key((const_DES_cblock*)key2.data, &schedule2); - DES_set_key((const_DES_cblock*)key3.data, &schedule3); - DES_ede3_cbc_encrypt(text.data, enif_make_new_binary(env,text.size,&ret), - text.size, &schedule1, &schedule2, &schedule3, - &ivec_clone, (argv[5] == atom_true)); - CONSUME_REDS(env,text); - return ret; -} - -static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */ -#ifdef HAVE_DES_ede3_cfb_encrypt - ErlNifBinary key1, key2, key3, ivec, text; - DES_key_schedule schedule1, schedule2, schedule3; - DES_cblock ivec_clone; /* writable copy */ - ERL_NIF_TERM ret; - + out = enif_make_new_binary(env, text.size, &ret); - if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8 - || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[4], &text)) { - return enif_make_badarg(env); - } + EVP_CIPHER_CTX_init(&ctx); + if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL, + (argv[argc - 1] == atom_true)) || + !EVP_CIPHER_CTX_set_key_length(&ctx, key.size) || + !(EVP_CIPHER_type(cipher) != NID_rc2_cbc || + EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) || + !EVP_CipherInit_ex(&ctx, NULL, NULL, + key.data, ivec_size ? ivec.data : NULL, -1) || + !EVP_CIPHER_CTX_set_padding(&ctx, 0) || + !EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size) || + (ASSERT(out_size == text.size), 0) || + !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size)) { + + EVP_CIPHER_CTX_cleanup(&ctx); + return enif_raise_exception(env, atom_notsup); + } + ASSERT(out_size == 0); + EVP_CIPHER_CTX_cleanup(&ctx); + CONSUME_REDS(env, text); - memcpy(&ivec_clone, ivec.data, 8); - DES_set_key((const_DES_cblock*)key1.data, &schedule1); - DES_set_key((const_DES_cblock*)key2.data, &schedule2); - DES_set_key((const_DES_cblock*)key3.data, &schedule3); - DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret), - 8, text.size, &schedule1, &schedule2, &schedule3, - &ivec_clone, (argv[5] == atom_true)); - CONSUME_REDS(env,text); return ret; -#else - return atom_notsup; -#endif } static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, IVec, Data, IsEncrypt) */ - ErlNifBinary key, ivec, text; - AES_KEY aes_key; - unsigned char ivec_clone[16]; /* writable copy */ - int new_ivlen = 0; - ERL_NIF_TERM ret; - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !(key.size == 16 || key.size == 24 || key.size == 32) - || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 - || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { - return enif_make_badarg(env); - } - - memcpy(ivec_clone, ivec.data, 16); - AES_set_encrypt_key(key.data, key.size * 8, &aes_key); - AES_cfb8_encrypt((unsigned char *) text.data, - enif_make_new_binary(env, text.size, &ret), - text.size, &aes_key, ivec_clone, &new_ivlen, - (argv[3] == atom_true)); - CONSUME_REDS(env,text); - return ret; +{/* (Key, IVec, Data, IsEncrypt) */ + ErlNifBinary key, ivec, text; + AES_KEY aes_key; + unsigned char ivec_clone[16]; /* writable copy */ + int new_ivlen = 0; + ERL_NIF_TERM ret; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &key) + || !(key.size == 16 || key.size == 24 || key.size == 32) + || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 + || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { + return enif_make_badarg(env); + } + + memcpy(ivec_clone, ivec.data, 16); + AES_set_encrypt_key(key.data, key.size * 8, &aes_key); + AES_cfb8_encrypt((unsigned char *) text.data, + enif_make_new_binary(env, text.size, &ret), + text.size, &aes_key, ivec_clone, &new_ivlen, + (argv[3] == atom_true)); + CONSUME_REDS(env,text); + return ret; } -static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, IVec, Data, IsEncrypt) */ - ErlNifBinary key, ivec, text; +static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Key, IVec, Data, IsEncrypt) */ +#ifdef HAVE_AES_IGE + ErlNifBinary key_bin, ivec_bin, data_bin; AES_KEY aes_key; - unsigned char ivec_clone[16]; /* writable copy */ - int new_ivlen = 0; + unsigned char ivec[32]; + int i; + unsigned char* ret_ptr; ERL_NIF_TERM ret; + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) + || (key_bin.size != 16 && key_bin.size != 32) + || !enif_inspect_binary(env, argv[1], &ivec_bin) + || ivec_bin.size != 32 + || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin) + || data_bin.size % 16 != 0) { - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || !(key.size == 16 || key.size == 24 || key.size == 32) - || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 - || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { - return enif_make_badarg(env); + return enif_make_badarg(env); } - memcpy(ivec_clone, ivec.data, 16); - AES_set_encrypt_key(key.data, key.size * 8, &aes_key); - AES_cfb128_encrypt((unsigned char *) text.data, - enif_make_new_binary(env, text.size, &ret), - text.size, &aes_key, ivec_clone, &new_ivlen, - (argv[3] == atom_true)); - CONSUME_REDS(env,text); + if (argv[3] == atom_true) { + i = AES_ENCRYPT; + AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key); + } + else { + i = AES_DECRYPT; + AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key); + } + + ret_ptr = enif_make_new_binary(env, data_bin.size, &ret); + memcpy(ivec, ivec_bin.data, 32); /* writable copy */ + AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i); + CONSUME_REDS(env,data_bin); return ret; +#else + return atom_notsup; +#endif } /* Common for both encrypt and decrypt */ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, IVec, Data) */ - ErlNifBinary key, ivec, text; - AES_KEY aes_key; - unsigned char ivec_clone[16]; /* writable copy */ - unsigned char ecount_buf[AES_BLOCK_SIZE]; - unsigned int num = 0; - ERL_NIF_TERM ret; - + ErlNifBinary key, ivec, text; +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + const EVP_CIPHER *cipher; + EVP_CIPHER_CTX ctx; + unsigned char *out; + int outl = 0; +#else + AES_KEY aes_key; + unsigned char ivec_clone[16]; /* writable copy */ + unsigned char ecount_buf[AES_BLOCK_SIZE]; + unsigned int num = 0; +#endif + ERL_NIF_TERM ret; if (!enif_inspect_iolist_as_binary(env, argv[0], &key) +#if OPENSSL_VERSION_NUMBER < 0x1000000fL || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 +#endif || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { return enif_make_badarg(env); } +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + switch (key.size) + { + case 16: cipher = EVP_aes_128_ctr(); break; + case 24: cipher = EVP_aes_192_ctr(); break; + case 32: cipher = EVP_aes_256_ctr(); break; + default: return enif_make_badarg(env); + } + + out = enif_make_new_binary(env,text.size,&ret); + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, cipher, NULL, + key.data, ivec.data, (argv[3] == atom_true)); + EVP_CIPHER_CTX_set_padding(&ctx, 0); + EVP_CipherUpdate(&ctx, out, &outl, text.data, text.size); + ASSERT(outl == text.size); + EVP_CipherFinal_ex(&ctx, out + outl, &outl); + ASSERT(outl == 0); + EVP_CIPHER_CTX_cleanup(&ctx); +#else memcpy(ivec_clone, ivec.data, 16); memset(ecount_buf, 0, sizeof(ecount_buf)); AES_ctr128_encrypt((unsigned char *) text.data, enif_make_new_binary(env, text.size, &ret), text.size, &aes_key, ivec_clone, ecount_buf, &num); +#endif CONSUME_REDS(env,text); /* To do an incremental {en|de}cryption, the state to to keep between calls @@ -1675,6 +1472,81 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM /* Initializes state for ctr streaming (de)encryption */ +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL +static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Key, IVec) */ + ErlNifBinary key_bin, ivec_bin; + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher; + ERL_NIF_TERM ret; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) + || !enif_inspect_binary(env, argv[1], &ivec_bin) + || ivec_bin.size != 16) { + return enif_make_badarg(env); + } + + switch (key_bin.size) + { + case 16: cipher = EVP_aes_128_ctr(); break; + case 24: cipher = EVP_aes_192_ctr(); break; + case 32: cipher = EVP_aes_256_ctr(); break; + default: return enif_make_badarg(env); + } + + ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX)); + EVP_CIPHER_CTX_init(ctx); + EVP_CipherInit_ex(ctx, cipher, NULL, + key_bin.data, ivec_bin.data, 1); + EVP_CIPHER_CTX_set_padding(ctx, 0); + ret = enif_make_resource(env, ctx); + enif_release_resource(ctx); + return ret; +} +static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Context, Data) */ + EVP_CIPHER_CTX *ctx, *new_ctx; + ErlNifBinary data_bin; + ERL_NIF_TERM ret, cipher_term; + unsigned char *out; + int outl = 0; + + if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx) + || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { + return enif_make_badarg(env); + } + new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX)); + EVP_CIPHER_CTX_init(new_ctx); + EVP_CIPHER_CTX_copy(new_ctx, ctx); + out = enif_make_new_binary(env, data_bin.size, &cipher_term); + EVP_CipherUpdate(new_ctx, out, &outl, data_bin.data, data_bin.size); + ASSERT(outl == data_bin.size); + + ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term); + enif_release_resource(new_ctx); + CONSUME_REDS(env,data_bin); + return ret; +} + +#else /* if OPENSSL_VERSION_NUMBER < 1.0 */ + +static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Key, IVec) */ + ErlNifBinary key_bin, ivec_bin; + ERL_NIF_TERM ecount_bin; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) + || !enif_inspect_binary(env, argv[1], &ivec_bin) + || !(key_bin.size == 16 || key_bin.size == 24 || key_bin.size ==32) + || ivec_bin.size != 16) { + return enif_make_badarg(env); + } + + memset(enif_make_new_binary(env, AES_BLOCK_SIZE, &ecount_bin), + 0, AES_BLOCK_SIZE); + return enif_make_tuple4(env, argv[0], argv[1], ecount_bin, enif_make_int(env, 0)); +} + static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* ({Key, IVec, ECount, Num}, Data) */ ErlNifBinary key_bin, ivec_bin, text_bin, ecount_bin; @@ -1686,7 +1558,6 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N unsigned char * ivec2_buf; unsigned char * ecount2_buf; - if (!enif_get_tuple(env, argv[0], &state_arity, &state_term) || state_arity != 4 || !enif_inspect_iolist_as_binary(env, state_term[0], &key_bin) @@ -1714,6 +1585,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N CONSUME_REDS(env,text_bin); return ret; } +#endif /* OPENSSL_VERSION_NUMBER < 1.0 */ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key,Iv,AAD,In) */ @@ -1724,7 +1596,6 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *outp; ERL_NIF_TERM out, out_tag; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 @@ -1760,7 +1631,7 @@ out_err: return atom_error; #else - return atom_notsup; + return enif_raise_exception(env, atom_notsup); #endif } @@ -1773,7 +1644,6 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned char *outp; ERL_NIF_TERM out; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 @@ -1810,7 +1680,7 @@ out_err: CRYPTO_gcm128_release(ctx); return atom_error; #else - return atom_notsup; + return enif_raise_exception(env, atom_notsup); #endif } @@ -1843,7 +1713,6 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER unsigned char poly1305_key[32]; poly1305_state poly1305; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN || !enif_inspect_iolist_as_binary(env, argv[2], &aad) @@ -1881,7 +1750,7 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER return enif_make_tuple2(env, out, out_tag); #else - return atom_notsup; + return enif_raise_exception(env, atom_notsup); #endif } @@ -1896,7 +1765,6 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER unsigned char mac[POLY1305_TAG_LEN]; poly1305_state poly1305; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN || !enif_inspect_iolist_as_binary(env, argv[2], &aad) @@ -1937,46 +1805,16 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER return out; #else - return atom_notsup; + return enif_raise_exception(env, atom_notsup); #endif } -static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, IsEncrypt) */ - ErlNifBinary key_bin, data_bin; - AES_KEY aes_key; - int i; - unsigned char* ret_ptr; - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || (key_bin.size != 16 && key_bin.size != 32) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin) - || data_bin.size % 16 != 0) { - return enif_make_badarg(env); - } - - if (argv[2] == atom_true) { - i = AES_ENCRYPT; - AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key); - } - else { - i = AES_DECRYPT; - AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key); - } - - ret_ptr = enif_make_new_binary(env, data_bin.size, &ret); - AES_ecb_encrypt(data_bin.data, ret_ptr, &aes_key, i); - CONSUME_REDS(env,data_bin); - return ret; -} - static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Bytes) */ unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; + if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -1990,6 +1828,7 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned bytes; unsigned char* data; ERL_NIF_TERM ret; + if (!enif_get_uint(env, argv[0], &bytes)) { return enif_make_badarg(env); } @@ -2007,6 +1846,7 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar unsigned char* data; unsigned top_mask, bot_mask; ERL_NIF_TERM ret; + if (!enif_get_uint(env, argv[0], &bytes) || !enif_get_uint(env, argv[1], &top_mask) || !enif_get_uint(env, argv[2], &bot_mask)) { @@ -2030,7 +1870,6 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI unsigned dlen; ERL_NIF_TERM ret; - if (!enif_get_uint(env, argv[0], &bits) || !enif_get_int(env, argv[1], &top) || !enif_get_int(env, argv[2], &bottom)) { @@ -2099,7 +1938,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER unsigned dlen; ERL_NIF_TERM ret; - if (!get_bn_from_mpint(env, argv[0], &bn_from) || !get_bn_from_mpint(env, argv[1], &bn_rand)) { if (bn_from) BN_free(bn_from); @@ -2131,7 +1969,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg unsigned extra_byte; ERL_NIF_TERM ret; - if (!get_bn_from_bin(env, argv[0], &bn_base) || !get_bn_from_bin(env, argv[1], &bn_exponent) || !get_bn_from_bin(env, argv[2], &bn_modulo) @@ -2163,45 +2000,17 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg } static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (DigestType|none, Data|{digest,Digest}, Signature,Key=[P, Q, G, Y]) */ - ErlNifBinary data_bin, sign_bin; +{/* (sha, Digest, Signature,Key=[P, Q, G, Y]) */ + ErlNifBinary digest_bin, sign_bin; BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL; - unsigned char hmacbuf[SHA_DIGEST_LENGTH]; - unsigned char* digest; ERL_NIF_TERM head, tail; - const ERL_NIF_TERM* tpl_terms; - int tpl_arity; DSA *dsa; int i; - - if (argv[0] == atom_sha) { - if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { - if (tpl_arity != 2 || tpl_terms[0] != atom_digest - || !enif_inspect_binary(env, tpl_terms[1], &data_bin) - || data_bin.size != SHA_DIGEST_LENGTH) { - - return enif_make_badarg(env); - } - digest = data_bin.data; - } - else { - if (!enif_inspect_binary(env, argv[1], &data_bin)) { - return enif_make_badarg(env); - } - SHA1(data_bin.data, data_bin.size, hmacbuf); - digest = hmacbuf; - } - } - else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin) - && data_bin.size == SHA_DIGEST_LENGTH) { - digest = data_bin.data; - } - else { - return enif_make_badarg(env); - } - - if (!enif_inspect_binary(env, argv[2], &sign_bin) + if (!argv[0] == atom_sha + || !enif_inspect_binary(env, argv[1], &digest_bin) + || digest_bin.size != SHA_DIGEST_LENGTH + || !enif_inspect_binary(env, argv[2], &sign_bin) || !enif_get_list_cell(env, argv[3], &head, &tail) || !get_bn_from_bin(env, head, &dsa_p) || !enif_get_list_cell(env, tail, &head, &tail) @@ -2225,94 +2034,27 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM dsa->g = dsa_g; dsa->priv_key = NULL; dsa->pub_key = dsa_y; - i = DSA_verify(0, digest, SHA_DIGEST_LENGTH, + i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH, sign_bin.data, sign_bin.size, dsa); DSA_free(dsa); return(i > 0) ? atom_true : atom_false; } - -static void md5_digest(unsigned char* in, unsigned int in_len, unsigned char* out) -{ - MD5(in, in_len, out); -} -static void sha1_digest(unsigned char* in, unsigned int in_len, unsigned char* out) -{ - SHA1(in, in_len, out); -} -#ifdef HAVE_SHA224 -static void sha224_digest(unsigned char* in, unsigned int in_len, unsigned char* out) -{ - SHA224(in, in_len, out); -} -#endif -#ifdef HAVE_SHA256 -static void sha256_digest(unsigned char* in, unsigned int in_len, unsigned char* out) -{ - SHA256(in, in_len, out); -} -#endif -#ifdef HAVE_SHA384 -static void sha384_digest(unsigned char* in, unsigned int in_len, unsigned char* out) -{ - SHA384(in, in_len, out); -} -#endif -#ifdef HAVE_SHA512 -static void sha512_digest(unsigned char* in, unsigned int in_len, unsigned char* out) +static void init_digest_types(ErlNifEnv* env) { - SHA512(in, in_len, out); -} -#endif + struct digest_type_t* p = digest_types; -struct digest_type_t { - const char* type_str; - unsigned len; /* 0 if notsup */ - int NID_type; - void (*funcp)(unsigned char* in, unsigned int in_len, unsigned char* out); - ERL_NIF_TERM type_atom; -}; + for (p = digest_types; p->type_str; p++) { + p->type_atom = enif_make_atom(env, p->type_str); + } -struct digest_type_t digest_types[] = -{ - {"md5", MD5_DIGEST_LENGTH, NID_md5, md5_digest}, - {"sha", SHA_DIGEST_LENGTH, NID_sha1, sha1_digest}, - {"sha224", -#ifdef HAVE_SHA224 - SHA224_LEN, NID_sha224, sha224_digest -#else - 0 -#endif - }, - {"sha256", -#ifdef HAVE_SHA256 - SHA256_LEN, NID_sha256, sha256_digest -#else - 0 -#endif - }, - {"sha384", -#ifdef HAVE_SHA384 - SHA384_LEN, NID_sha384, sha384_digest -#else - 0 -#endif - }, - {"sha512", -#ifdef HAVE_SHA512 - SHA512_LEN, NID_sha512, sha512_digest -#else - 0 -#endif - }, - {NULL} -}; +} -static void init_digest_types(ErlNifEnv* env) +static void init_cipher_types(ErlNifEnv* env) { - struct digest_type_t* p = digest_types; + struct cipher_type_t* p = cipher_types; - for (p = digest_types; p->type_str; p++) { + for (p = cipher_types; p->type_str; p++) { p->type_atom = enif_make_atom(env, p->type_str); } @@ -2329,31 +2071,45 @@ static struct digest_type_t* get_digest_type(ERL_NIF_TERM type) return NULL; } -static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type, Data|{digest,Digest}, Signature, Key=[E,N]) */ - ErlNifBinary data_bin, sign_bin; - unsigned char hmacbuf[SHA512_LEN]; - ERL_NIF_TERM head, tail, ret; - int i; - RSA* rsa; - const ERL_NIF_TERM type = argv[0]; - const ERL_NIF_TERM* tpl_terms; - int tpl_arity; - struct digest_type_t* digp = NULL; - unsigned char* digest = NULL; +static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len) +{ + struct cipher_type_t* p = NULL; + for (p = cipher_types; p->type_str; p++) { + if (type == p->type_atom && (!p->key_len || key_len == p->key_len)) { + return p; + } + } + return NULL; +} +static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type, Digest, Signature, Key=[E,N]) */ + ErlNifBinary digest_bin, sign_bin; + ERL_NIF_TERM head, tail, ret; + int i; + RSA *rsa; +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + EVP_PKEY *pkey; + EVP_PKEY_CTX *ctx; +#endif + const EVP_MD *md; + const ERL_NIF_TERM type = argv[0]; + struct digest_type_t *digp = NULL; digp = get_digest_type(type); if (!digp) { return enif_make_badarg(env); } - if (!digp->len) { + if (!digp->md_func) { return atom_notsup; } rsa = RSA_new(); + md = digp->md_func(); - if (!enif_inspect_binary(env, argv[2], &sign_bin) + if (!enif_inspect_binary(env, argv[1], &digest_bin) + || digest_bin.size != EVP_MD_size(md) + || !enif_inspect_binary(env, argv[2], &sign_bin) || !enif_get_list_cell(env, argv[3], &head, &tail) || !get_bn_from_bin(env, head, &rsa->e) || !enif_get_list_cell(env, tail, &head, &tail) @@ -2363,27 +2119,24 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ret = enif_make_badarg(env); goto done; } - if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { - if (tpl_arity != 2 || tpl_terms[0] != atom_digest - || !enif_inspect_binary(env, tpl_terms[1], &data_bin) - || data_bin.size != digp->len) { - - ret = enif_make_badarg(env); - goto done; - } - digest = data_bin.data; - } - else if (enif_inspect_binary(env, argv[1], &data_bin)) { - digest = hmacbuf; - digp->funcp(data_bin.data, data_bin.size, digest); - } - else { - ret = enif_make_badarg(env); - goto done; - } - i = RSA_verify(digp->NID_type, digest, digp->len, +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + pkey = EVP_PKEY_new(); + EVP_PKEY_set1_RSA(pkey, rsa); + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + EVP_PKEY_verify_init(ctx); + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); + EVP_PKEY_CTX_set_signature_md(ctx, md); + + i = EVP_PKEY_verify(ctx, sign_bin.data, sign_bin.size, + digest_bin.data, digest_bin.size); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); +#else + i = RSA_verify(md->type, digest_bin.data, EVP_MD_size(md), sign_bin.data, sign_bin.size, rsa); +#endif ret = (i==1 ? atom_true : atom_false); @@ -2392,107 +2145,6 @@ done: return ret; } - -static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, IVec, Data, IsEncrypt) */ - ErlNifBinary key_bin, ivec_bin, data_bin; - unsigned char ivec[16]; - int enc, i = 0, outlen = 0; - EVP_CIPHER_CTX ctx; - const EVP_CIPHER *cipher = NULL; - unsigned char* ret_ptr; - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || (key_bin.size != 16 && key_bin.size != 32) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 16 - || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin) - || data_bin.size % 16 != 0) { - - return enif_make_badarg(env); - } - - if (argv[3] == atom_true) - enc = 1; - else - enc = 0; - - EVP_CIPHER_CTX_init(&ctx); - - if (key_bin.size == 16) - cipher = EVP_aes_128_cbc(); - else if (key_bin.size == 32) - cipher = EVP_aes_256_cbc(); - - memcpy(ivec, ivec_bin.data, 16); /* writeable copy */ - - /* openssl docs say we need to leave at least 3 blocks available - at the end of the buffer for EVP calls. let's be safe */ - ret_ptr = enif_make_new_binary(env, data_bin.size + 16*3, &ret); - - if (EVP_CipherInit_ex(&ctx, cipher, NULL, key_bin.data, ivec, enc) != 1) - return enif_make_badarg(env); - - /* disable padding, we only handle whole blocks */ - EVP_CIPHER_CTX_set_padding(&ctx, 0); - - if (EVP_CipherUpdate(&ctx, ret_ptr, &i, data_bin.data, data_bin.size) != 1) - return enif_make_badarg(env); - outlen += i; - if (EVP_CipherFinal_ex(&ctx, ret_ptr + outlen, &i) != 1) - return enif_make_badarg(env); - outlen += i; - - EVP_CIPHER_CTX_cleanup(&ctx); - - CONSUME_REDS(env,data_bin); - - /* the garbage collector is going to love this */ - return enif_make_sub_binary(env, ret, 0, outlen); -} - -static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, IVec, Data, IsEncrypt) */ -#ifdef HAVE_AES_IGE - ErlNifBinary key_bin, ivec_bin, data_bin; - AES_KEY aes_key; - unsigned char ivec[32]; - int i; - unsigned char* ret_ptr; - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || (key_bin.size != 16 && key_bin.size != 32) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 32 - || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin) - || data_bin.size % 16 != 0) { - - return enif_make_badarg(env); - } - - if (argv[3] == atom_true) { - i = AES_ENCRYPT; - AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key); - } - else { - i = AES_DECRYPT; - AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key); - } - - ret_ptr = enif_make_new_binary(env, data_bin.size, &ret); - memcpy(ivec, ivec_bin.data, 32); /* writable copy */ - AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i); - CONSUME_REDS(env,data_bin); - return ret; -#else - return atom_notsup; -#endif -} - static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data1, Data2) */ ErlNifBinary d1, d2; @@ -2500,7 +2152,6 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) int i; ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env,argv[0], &d1) || !enif_inspect_iolist_as_binary(env,argv[1], &d2) || d1.size != d2.size) { @@ -2521,7 +2172,6 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg RC4_KEY rc4_key; ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env,argv[0], &key) || !enif_inspect_iolist_as_binary(env,argv[1], &data)) { return enif_make_badarg(env); @@ -2538,7 +2188,6 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ErlNifBinary key; ERL_NIF_TERM ret; - if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) { return enif_make_badarg(env); } @@ -2554,7 +2203,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N RC4_KEY* rc4_key; ERL_NIF_TERM new_state, new_data; - if (!enif_inspect_iolist_as_binary(env,argv[0], &state) || state.size != sizeof(RC4_KEY) || !enif_inspect_iolist_as_binary(env,argv[1], &data)) { @@ -2568,34 +2216,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N return enif_make_tuple2(env,new_state,new_data); } -static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key,IVec,Data,IsEncrypt) */ - ErlNifBinary key_bin, ivec_bin, data_bin; - RC2_KEY rc2_key; - ERL_NIF_TERM ret; - unsigned char iv_copy[8]; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin) - || data_bin.size % 8 != 0) { - return enif_make_badarg(env); - } - - RC2_set_key(&rc2_key, key_bin.size, key_bin.data, key_bin.size*8); - memcpy(iv_copy, ivec_bin.data, 8); - RC2_cbc_encrypt(data_bin.data, - enif_make_new_binary(env, data_bin.size, &ret), - data_bin.size, &rc2_key, - iv_copy, - (argv[3] == atom_true)); - CONSUME_REDS(env,data_bin); - return ret; -} - static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa) { /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */ @@ -2625,41 +2245,32 @@ static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa) } static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type, Data|{digest,Digest}, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */ - ErlNifBinary data_bin, ret_bin; - unsigned char hmacbuf[SHA512_LEN]; - unsigned rsa_s_len; - RSA* rsa; - int i; - const ERL_NIF_TERM* tpl_terms; - int tpl_arity; +{/* (Type, Digest, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */ + ErlNifBinary digest_bin, ret_bin; +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + EVP_PKEY *pkey; + EVP_PKEY_CTX *ctx; + size_t rsa_s_len; +#else + unsigned rsa_s_len, len; +#endif + RSA *rsa; + int i; struct digest_type_t *digp; - unsigned char* digest; - + const EVP_MD *md; digp = get_digest_type(argv[0]); if (!digp) { return enif_make_badarg(env); } - if (!digp->len) { + if (!digp->md_func) { return atom_notsup; } + md = digp->md_func(); - if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { - if (tpl_arity != 2 || tpl_terms[0] != atom_digest - || !enif_inspect_binary(env, tpl_terms[1], &data_bin) - || data_bin.size != digp->len) { - - return enif_make_badarg(env); - } - digest = data_bin.data; - } - else { - if (!enif_inspect_binary(env,argv[1],&data_bin)) { - return enif_make_badarg(env); - } - digest = hmacbuf; - digp->funcp(data_bin.data, data_bin.size, digest); + if (!enif_inspect_binary(env,argv[1],&digest_bin) + || digest_bin.size != EVP_MD_size(md)) { + return enif_make_badarg(env); } rsa = RSA_new(); @@ -2669,14 +2280,33 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar } +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + pkey = EVP_PKEY_new(); + EVP_PKEY_set1_RSA(pkey, rsa); + rsa_s_len=(size_t)EVP_PKEY_size(pkey); + enif_alloc_binary(rsa_s_len, &ret_bin); + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + EVP_PKEY_sign_init(ctx); + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); + EVP_PKEY_CTX_set_signature_md(ctx, md); + + i = EVP_PKEY_sign(ctx, ret_bin.data, &rsa_s_len, + digest_bin.data, digest_bin.size); + ASSERT(i<=0 || rsa_s_len <= ret_bin.size); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); +#else enif_alloc_binary(RSA_size(rsa), &ret_bin); + len = EVP_MD_size(md); - ERL_VALGRIND_ASSERT_MEM_DEFINED(digest, digp->len); - i = RSA_sign(digp->NID_type, digest, digp->len, + ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len); + i = RSA_sign(md->type, digest_bin.data, len, ret_bin.data, &rsa_s_len, rsa); +#endif RSA_free(rsa); - if (i) { + if (i > 0) { ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len); if (rsa_s_len != ret_bin.size) { enif_realloc_binary(&ret_bin, rsa_s_len); @@ -2692,43 +2322,16 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (DigesType|none, Data|{digest,Digest}, Key=[P,Q,G,PrivKey]) */ - ErlNifBinary data_bin, ret_bin; +{/* (sha, Digest, Key=[P,Q,G,PrivKey]) */ + ErlNifBinary digest_bin, ret_bin; ERL_NIF_TERM head, tail; - unsigned char hmacbuf[SHA_DIGEST_LENGTH]; unsigned int dsa_s_len; - const ERL_NIF_TERM* tpl_terms; - int tpl_arity; - unsigned char* digest = NULL; DSA* dsa; int i; - - if (argv[0] == atom_sha) { - if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { - if (tpl_arity != 2 || tpl_terms[0] != atom_digest - || !enif_inspect_binary(env, tpl_terms[1], &data_bin) - || data_bin.size != SHA_DIGEST_LENGTH) { - - return enif_make_badarg(env); - } - digest = data_bin.data; - } - else { - if (!enif_inspect_binary(env,argv[1],&data_bin)) { - return enif_make_badarg(env); - } - SHA1(data_bin.data, data_bin.size, hmacbuf); - digest = hmacbuf; - } - } - else if (argv[0] == atom_none - && enif_inspect_binary(env,argv[1],&data_bin) - && data_bin.size == SHA_DIGEST_LENGTH) { - - digest = data_bin.data; - } - else { + if (!argv[0] == atom_sha + || !enif_inspect_binary(env, argv[1], &digest_bin) + || digest_bin.size != SHA_DIGEST_LENGTH) { return enif_make_badarg(env); } @@ -2749,7 +2352,7 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar } enif_alloc_binary(DSA_size(dsa), &ret_bin); - i = DSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH, + i = DSA_sign(NID_sha1, digest_bin.data, SHA_DIGEST_LENGTH, ret_bin.data, &dsa_s_len, dsa); DSA_free(dsa); if (i) { @@ -2789,7 +2392,6 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER int padding, i; RSA* rsa; - rsa = RSA_new(); if (!enif_inspect_binary(env, argv[0], &data_bin) @@ -2838,7 +2440,6 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE int padding, i; RSA* rsa; - rsa = RSA_new(); if (!enif_inspect_binary(env, argv[0], &data_bin) @@ -2885,7 +2486,6 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E unsigned char *p_ptr, *g_ptr; ERL_NIF_TERM ret_p, ret_g; - if (!enif_get_int(env, argv[0], &prime_len) || !enif_get_int(env, argv[1], &generator)) { @@ -2913,7 +2513,6 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] int i; ERL_NIF_TERM ret, head, tail; - dh_params = DH_new(); if (!enif_get_list_cell(env, argv[0], &head, &tail) @@ -2948,7 +2547,6 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail; int mpint; /* 0 or 4 */ - dh_params = DH_new(); if (!(get_bn_from_bin(env, argv[0], &dh_params->priv_key) @@ -2993,7 +2591,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ErlNifBinary ret_bin; ERL_NIF_TERM ret, head, tail; - dh_params = DH_new(); if (!get_bn_from_bin(env, argv[0], &pubkey) @@ -3016,7 +2613,7 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ret = enif_make_binary(env, &ret_bin); } else { - enif_release_binary(&ret_bin); + enif_release_binary(&ret_bin); ret = atom_error; } } @@ -3034,7 +2631,6 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM unsigned dlen; ERL_NIF_TERM ret; - if (!get_bn_from_bin(env, argv[0], &bn_multiplier) || !get_bn_from_bin(env, argv[1], &bn_verifier) || !get_bn_from_bin(env, argv[2], &bn_generator) @@ -3095,7 +2691,6 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; - if (!get_bn_from_bin(env, argv[0], &bn_a) || !get_bn_from_bin(env, argv[1], &bn_u) || !get_bn_from_bin(env, argv[2], &bn_B) @@ -3175,7 +2770,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ unsigned dlen; ERL_NIF_TERM ret; - if (!get_bn_from_bin(env, argv[0], &bn_verifier) || !get_bn_from_bin(env, argv[1], &bn_b) || !get_bn_from_bin(env, argv[2], &bn_u) @@ -3228,99 +2822,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_ return ret; } -static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Ivec, Data, IsEncrypt) */ - ErlNifBinary key_bin, ivec_bin, data_bin; - BF_KEY bf_key; /* blowfish key 8 */ - unsigned char bf_tkey[8]; /* blowfish ivec */ - int bf_n = 0; /* blowfish ivec pos */ - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) { - return enif_make_badarg(env); - } - - BF_set_key(&bf_key, key_bin.size, key_bin.data); - memcpy(bf_tkey, ivec_bin.data, 8); - BF_cfb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret), - data_bin.size, &bf_key, bf_tkey, &bf_n, - (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT)); - CONSUME_REDS(env,data_bin); - return ret; -} - -static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Ivec, Data, IsEncrypt) */ - ErlNifBinary key_bin, ivec_bin, data_bin; - BF_KEY bf_key; /* blowfish key 8 */ - unsigned char bf_tkey[8]; /* blowfish ivec */ - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin) - || data_bin.size % 8 != 0) { - return enif_make_badarg(env); - } - - BF_set_key(&bf_key, key_bin.size, key_bin.data); - memcpy(bf_tkey, ivec_bin.data, 8); - BF_cbc_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret), - data_bin.size, &bf_key, bf_tkey, - (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT)); - CONSUME_REDS(env,data_bin); - return ret; -} - -static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, Data, IsEncrypt) */ - ErlNifBinary key_bin, data_bin; - BF_KEY bf_key; /* blowfish key 8 */ - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin) - || data_bin.size < 8) { - return enif_make_badarg(env); - } - BF_set_key(&bf_key, key_bin.size, key_bin.data); - BF_ecb_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret), - &bf_key, (argv[2] == atom_true ? BF_ENCRYPT : BF_DECRYPT)); - CONSUME_REDS(env,data_bin); - return ret; -} - -static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key, IVec, Data) */ - ErlNifBinary key_bin, ivec_bin, data_bin; - BF_KEY bf_key; /* blowfish key 8 */ - unsigned char bf_tkey[8]; /* blowfish ivec */ - int bf_n = 0; /* blowfish ivec pos */ - ERL_NIF_TERM ret; - - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) - || !enif_inspect_binary(env, argv[1], &ivec_bin) - || ivec_bin.size != 8 - || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) { - return enif_make_badarg(env); - } - - BF_set_key(&bf_key, key_bin.size, key_bin.data); - memcpy(bf_tkey, ivec_bin.data, 8); - BF_ofb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret), - data_bin.size, &bf_key, bf_tkey, &bf_n); - CONSUME_REDS(env,data_bin); - return ret; -} - #if defined(HAVE_EC) static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) { @@ -3629,7 +3130,6 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM priv_key; ERL_NIF_TERM pub_key = atom_undefined; - if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key)) goto badarg; @@ -3659,50 +3159,33 @@ badarg: } static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type, Data|{digest,Digest}, Curve, Key) */ +{/* (Type, Digest, Curve, Key) */ #if defined(HAVE_EC) - ErlNifBinary data_bin, ret_bin; - unsigned char hmacbuf[SHA_DIGEST_LENGTH]; + ErlNifBinary digest_bin, ret_bin; unsigned int dsa_s_len; EC_KEY* key = NULL; - int i; - const ERL_NIF_TERM* tpl_terms; - int tpl_arity; + int i, len; struct digest_type_t *digp; - unsigned char* digest; - + const EVP_MD *md; digp = get_digest_type(argv[0]); if (!digp) { return enif_make_badarg(env); } - if (!digp->len) { + if (!digp->md_func) { return atom_notsup; } + md = digp->md_func(); + len = EVP_MD_size(md); - if (!get_ec_key(env, argv[2], argv[3], atom_undefined, &key)) + if (!enif_inspect_binary(env,argv[1],&digest_bin) + || digest_bin.size != len + || !get_ec_key(env, argv[2], argv[3], atom_undefined, &key)) goto badarg; - if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { - if (tpl_arity != 2 || tpl_terms[0] != atom_digest - || !enif_inspect_binary(env, tpl_terms[1], &data_bin) - || data_bin.size != digp->len) { - - goto badarg; - } - digest = data_bin.data; - } - else { - if (!enif_inspect_binary(env,argv[1],&data_bin)) { - goto badarg; - } - digest = hmacbuf; - digp->funcp(data_bin.data, data_bin.size, digest); - } - enif_alloc_binary(ECDSA_size(key), &ret_bin); - i = ECDSA_sign(digp->NID_type, digest, digp->len, + i = ECDSA_sign(md->type, digest_bin.data, len, ret_bin.data, &dsa_s_len, key); EC_KEY_free(key); @@ -3727,49 +3210,32 @@ badarg: } static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type, Data|{digest,Digest}, Signature, Curve, Key) */ +{/* (Type, Digest, Signature, Curve, Key) */ #if defined(HAVE_EC) - ErlNifBinary data_bin, sign_bin; - unsigned char hmacbuf[SHA512_LEN]; - int i; + ErlNifBinary digest_bin, sign_bin; + int i, len; EC_KEY* key = NULL; const ERL_NIF_TERM type = argv[0]; - const ERL_NIF_TERM* tpl_terms; - int tpl_arity; - struct digest_type_t* digp = NULL; - unsigned char* digest = NULL; - + struct digest_type_t *digp = NULL; + const EVP_MD *md; digp = get_digest_type(type); if (!digp) { return enif_make_badarg(env); } - if (!digp->len) { + if (!digp->md_func) { return atom_notsup; } + md = digp->md_func(); + len = EVP_MD_size(md); - if (!enif_inspect_binary(env, argv[2], &sign_bin) + if (!enif_inspect_binary(env, argv[1], &digest_bin) + || digest_bin.size != len + || !enif_inspect_binary(env, argv[2], &sign_bin) || !get_ec_key(env, argv[3], atom_undefined, argv[4], &key)) goto badarg; - if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { - if (tpl_arity != 2 || tpl_terms[0] != atom_digest - || !enif_inspect_binary(env, tpl_terms[1], &data_bin) - || data_bin.size != digp->len) { - - goto badarg; - } - digest = data_bin.data; - } - else if (enif_inspect_binary(env, argv[1], &data_bin)) { - digest = hmacbuf; - digp->funcp(data_bin.data, data_bin.size, digest); - } - else { - goto badarg; - } - - i = ECDSA_verify(digp->NID_type, digest, digp->len, + i = ECDSA_verify(md->type, digest_bin.data, len, sign_bin.data, sign_bin.size, key); EC_KEY_free(key); @@ -3803,7 +3269,6 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF EC_POINT *my_ecpoint; EC_KEY *other_ecdh = NULL; - if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) return enif_make_badarg(env); @@ -3847,252 +3312,9 @@ out_err: static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary seed_bin; + if (!enif_inspect_binary(env, argv[0], &seed_bin)) return enif_make_badarg(env); RAND_seed(seed_bin.data,seed_bin.size); return atom_ok; } - - -/* HMAC */ - -static void hmac_md5(unsigned char *key, int klen, unsigned char *dbuf, int dlen, - unsigned char *hmacbuf) -{ - MD5_CTX ctx; - char ipad[HMAC_INT_LEN]; - char opad[HMAC_INT_LEN]; - unsigned char nkey[MD5_LEN]; - int i; - - /* Change key if longer than 64 bytes */ - if (klen > HMAC_INT_LEN) { - MD5(key, klen, nkey); - key = nkey; - klen = MD5_LEN; - } - - memset(ipad, '\0', sizeof(ipad)); - memset(opad, '\0', sizeof(opad)); - memcpy(ipad, key, klen); - memcpy(opad, key, klen); - - for (i = 0; i < HMAC_INT_LEN; i++) { - ipad[i] ^= HMAC_IPAD; - opad[i] ^= HMAC_OPAD; - } - - /* inner MD5 */ - MD5_Init(&ctx); - MD5_Update(&ctx, ipad, HMAC_INT_LEN); - MD5_Update(&ctx, dbuf, dlen); - MD5_Final((unsigned char *) hmacbuf, &ctx); - /* outer MD5 */ - MD5_Init(&ctx); - MD5_Update(&ctx, opad, HMAC_INT_LEN); - MD5_Update(&ctx, hmacbuf, MD5_LEN); - MD5_Final((unsigned char *) hmacbuf, &ctx); -} - -static void hmac_sha1(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf) -{ - SHA_CTX ctx; - char ipad[HMAC_INT_LEN]; - char opad[HMAC_INT_LEN]; - unsigned char nkey[SHA_LEN]; - int i; - - /* Change key if longer than 64 bytes */ - if (klen > HMAC_INT_LEN) { - SHA1(key, klen, nkey); - key = nkey; - klen = SHA_LEN; - } - - memset(ipad, '\0', sizeof(ipad)); - memset(opad, '\0', sizeof(opad)); - memcpy(ipad, key, klen); - memcpy(opad, key, klen); - - for (i = 0; i < HMAC_INT_LEN; i++) { - ipad[i] ^= HMAC_IPAD; - opad[i] ^= HMAC_OPAD; - } - - /* inner SHA */ - SHA1_Init(&ctx); - SHA1_Update(&ctx, ipad, HMAC_INT_LEN); - SHA1_Update(&ctx, dbuf, dlen); - SHA1_Final((unsigned char *) hmacbuf, &ctx); - /* outer SHA */ - SHA1_Init(&ctx); - SHA1_Update(&ctx, opad, HMAC_INT_LEN); - SHA1_Update(&ctx, hmacbuf, SHA_LEN); - SHA1_Final((unsigned char *) hmacbuf, &ctx); -} - -#ifdef HAVE_SHA224 -static void hmac_sha224(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf) -{ - SHA256_CTX ctx; - char ipad[HMAC_INT_LEN]; - char opad[HMAC_INT_LEN]; - unsigned char nkey[SHA224_DIGEST_LENGTH]; - int i; - - /* Change key if longer than 64 bytes */ - if (klen > HMAC_INT_LEN) { - SHA224(key, klen, nkey); - key = nkey; - klen = SHA224_DIGEST_LENGTH; - } - - memset(ipad, '\0', sizeof(ipad)); - memset(opad, '\0', sizeof(opad)); - memcpy(ipad, key, klen); - memcpy(opad, key, klen); - - for (i = 0; i < HMAC_INT_LEN; i++) { - ipad[i] ^= HMAC_IPAD; - opad[i] ^= HMAC_OPAD; - } - - /* inner SHA */ - SHA224_Init(&ctx); - SHA224_Update(&ctx, ipad, HMAC_INT_LEN); - SHA224_Update(&ctx, dbuf, dlen); - SHA224_Final((unsigned char *) hmacbuf, &ctx); - /* outer SHA */ - SHA224_Init(&ctx); - SHA224_Update(&ctx, opad, HMAC_INT_LEN); - SHA224_Update(&ctx, hmacbuf, SHA224_DIGEST_LENGTH); - SHA224_Final((unsigned char *) hmacbuf, &ctx); -} -#endif - -#ifdef HAVE_SHA256 -static void hmac_sha256(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf) -{ - SHA256_CTX ctx; - char ipad[HMAC_INT_LEN]; - char opad[HMAC_INT_LEN]; - unsigned char nkey[SHA256_DIGEST_LENGTH]; - int i; - - /* Change key if longer than 64 bytes */ - if (klen > HMAC_INT_LEN) { - SHA256(key, klen, nkey); - key = nkey; - klen = SHA256_DIGEST_LENGTH; - } - - memset(ipad, '\0', sizeof(ipad)); - memset(opad, '\0', sizeof(opad)); - memcpy(ipad, key, klen); - memcpy(opad, key, klen); - - for (i = 0; i < HMAC_INT_LEN; i++) { - ipad[i] ^= HMAC_IPAD; - opad[i] ^= HMAC_OPAD; - } - - /* inner SHA */ - SHA256_Init(&ctx); - SHA256_Update(&ctx, ipad, HMAC_INT_LEN); - SHA256_Update(&ctx, dbuf, dlen); - SHA256_Final((unsigned char *) hmacbuf, &ctx); - /* outer SHA */ - SHA256_Init(&ctx); - SHA256_Update(&ctx, opad, HMAC_INT_LEN); - SHA256_Update(&ctx, hmacbuf, SHA256_DIGEST_LENGTH); - SHA256_Final((unsigned char *) hmacbuf, &ctx); -} -#endif - -#ifdef HAVE_SHA384 -static void hmac_sha384(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf) -{ - SHA512_CTX ctx; - char ipad[HMAC_INT2_LEN]; - char opad[HMAC_INT2_LEN]; - unsigned char nkey[SHA384_DIGEST_LENGTH]; - int i; - - /* Change key if longer than 64 bytes */ - if (klen > HMAC_INT2_LEN) { - SHA384(key, klen, nkey); - key = nkey; - klen = SHA384_DIGEST_LENGTH; - } - - memset(ipad, '\0', sizeof(ipad)); - memset(opad, '\0', sizeof(opad)); - memcpy(ipad, key, klen); - memcpy(opad, key, klen); - - for (i = 0; i < HMAC_INT2_LEN; i++) { - ipad[i] ^= HMAC_IPAD; - opad[i] ^= HMAC_OPAD; - } - - /* inner SHA */ - SHA384_Init(&ctx); - SHA384_Update(&ctx, ipad, HMAC_INT2_LEN); - SHA384_Update(&ctx, dbuf, dlen); - SHA384_Final((unsigned char *) hmacbuf, &ctx); - /* outer SHA */ - SHA384_Init(&ctx); - SHA384_Update(&ctx, opad, HMAC_INT2_LEN); - SHA384_Update(&ctx, hmacbuf, SHA384_DIGEST_LENGTH); - SHA384_Final((unsigned char *) hmacbuf, &ctx); -} -#endif - -#ifdef HAVE_SHA512 -static void hmac_sha512(unsigned char *key, int klen, - unsigned char *dbuf, int dlen, - unsigned char *hmacbuf) -{ - SHA512_CTX ctx; - char ipad[HMAC_INT2_LEN]; - char opad[HMAC_INT2_LEN]; - unsigned char nkey[SHA512_DIGEST_LENGTH]; - int i; - - /* Change key if longer than 64 bytes */ - if (klen > HMAC_INT2_LEN) { - SHA512(key, klen, nkey); - key = nkey; - klen = SHA512_DIGEST_LENGTH; - } - - memset(ipad, '\0', sizeof(ipad)); - memset(opad, '\0', sizeof(opad)); - memcpy(ipad, key, klen); - memcpy(opad, key, klen); - - for (i = 0; i < HMAC_INT2_LEN; i++) { - ipad[i] ^= HMAC_IPAD; - opad[i] ^= HMAC_OPAD; - } - - /* inner SHA */ - SHA512_Init(&ctx); - SHA512_Update(&ctx, ipad, HMAC_INT2_LEN); - SHA512_Update(&ctx, dbuf, dlen); - SHA512_Final((unsigned char *) hmacbuf, &ctx); - /* outer SHA */ - SHA512_Init(&ctx); - SHA512_Update(&ctx, opad, HMAC_INT2_LEN); - SHA512_Update(&ctx, hmacbuf, SHA512_DIGEST_LENGTH); - SHA512_Final((unsigned char *) hmacbuf, &ctx); -} -#endif diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index e0de16074c..aab43232c9 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -51,8 +51,6 @@ DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks); -static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */ - static void nomem(size_t size, const char* op) { fprintf(stderr, "Out of memory abort. Crypto failed to %s %zu bytes.\r\n", @@ -84,6 +82,8 @@ static void crypto_free(void* ptr) #ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */ +static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */ + #include static INLINE void locking(int mode, ErlNifRWLock* lock) diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 38e71591f3..8722e801a6 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -210,10 +210,8 @@ supports()-> {Hashs, PubKeys, Ciphers} = algorithms(), [{hashs, Hashs}, - {ciphers, [des_cbc, des_cfb, des3_cbc, des_ede3, blowfish_cbc, - blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb8, aes_cfb128, - aes_cbc256, rc2_cbc, aes_ctr, rc4, aes_ecb] ++ Ciphers}, - {public_keys, [rsa, dss, dh, srp] ++ PubKeys} + {ciphers, Ciphers}, + {public_keys, PubKeys} ]. info_lib() -> ?nif_stub. @@ -222,20 +220,14 @@ info_lib() -> ?nif_stub. hash(Hash, Data0) -> Data = iolist_to_binary(Data0), - MaxByts = max_bytes(), - hash(Hash, Data, erlang:byte_size(Data), MaxByts, initial). + MaxBytes = max_bytes(), + hash(Hash, Data, erlang:byte_size(Data), MaxBytes). -spec hash_init('md5'|'md4'|'ripemd160'| 'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any(). -hash_init(md5) -> {md5, md5_init()}; -hash_init(md4) -> {md4, md4_init()}; -hash_init(sha) -> {sha, sha_init()}; -hash_init(ripemd160) -> {ripemd160, ripemd160_init()}; -hash_init(sha224) -> {sha224, sha224_init()}; -hash_init(sha256) -> {sha256, sha256_init()}; -hash_init(sha384) -> {sha384, sha384_init()}; -hash_init(sha512) -> {sha512, sha512_init()}. +hash_init(Hash) -> + notsup_to_error(hash_init_nif(Hash)). -spec hash_update(_, iodata()) -> any(). @@ -246,14 +238,8 @@ hash_update(State, Data0) -> -spec hash_final(_) -> binary(). -hash_final({md5,Context}) -> md5_final(Context); -hash_final({md4,Context}) -> md4_final(Context); -hash_final({sha,Context}) -> sha_final(Context); -hash_final({ripemd160,Context}) -> ripemd160_final(Context); -hash_final({sha224,Context}) -> sha224_final(Context); -hash_final({sha256,Context}) -> sha256_final(Context); -hash_final({sha384,Context}) -> sha384_final(Context); -hash_final({sha512,Context}) -> sha512_final(Context). +hash_final(State) -> + notsup_to_error(hash_final_nif(State)). -spec hmac(_, iodata(), iodata()) -> binary(). @@ -265,151 +251,128 @@ hash_final({sha512,Context}) -> sha512_final(Context). hmac(Type, Key, Data0) -> Data = iolist_to_binary(Data0), - hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes(), initial). + hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()). hmac(Type, Key, Data0, MacSize) -> Data = iolist_to_binary(Data0), - hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes(), initial). + hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()). - -hmac_init(_Type, _Key) -> ?nif_stub. +hmac_init(Type, Key) -> + notsup_to_error(hmac_init_nif(Type, Key)). hmac_update(State, Data0) -> Data = iolist_to_binary(Data0), hmac_update(State, Data, erlang:byte_size(Data), max_bytes()). -hmac_final(_Context) -> ? nif_stub. -hmac_final_n(_Context, _HashLen) -> ? nif_stub. + +hmac_final(Context) -> + notsup_to_error(hmac_final_nif(Context)). +hmac_final_n(Context, HashLen) -> + notsup_to_error(hmac_final_nif(Context, HashLen)). %% Ecrypt/decrypt %%% --spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | - blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | rc2_cbc, +-spec block_encrypt(des_cbc | des_cfb | + des3_cbc | des3_cbf | des_ede3 | + blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 | + aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 | + rc2_cbc, Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(); (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()}. -block_encrypt(des_cbc, Key, Ivec, Data) -> - des_cbc_encrypt(Key, Ivec, Data); -block_encrypt(des_cfb, Key, Ivec, Data) -> - des_cfb_encrypt(Key, Ivec, Data); -block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) -> - des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data); -block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) -> - des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data); -block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) -> - des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data); -block_encrypt(blowfish_cbc, Key, Ivec, Data) -> - blowfish_cbc_encrypt(Key, Ivec, Data); -block_encrypt(blowfish_cfb64, Key, Ivec, Data) -> - blowfish_cfb64_encrypt(Key, Ivec, Data); -block_encrypt(blowfish_ofb64, Key, Ivec, Data) -> - blowfish_ofb64_encrypt(Key, Ivec, Data); -block_encrypt(aes_cbc128, Key, Ivec, Data) -> - aes_cbc_128_encrypt(Key, Ivec, Data); -block_encrypt(aes_cbc256, Key, Ivec, Data) -> - aes_cbc_256_encrypt(Key, Ivec, Data); +block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc; + Type =:= des_cfb; + Type =:= blowfish_cbc; + Type =:= blowfish_cfb64; + Type =:= blowfish_ofb64; + Type =:= aes_cbc128; + Type =:= aes_cfb8; + Type =:= aes_cfb128; + Type =:= aes_cbc256; + Type =:= rc2_cbc -> + block_crypt_nif(Type, Key, Ivec, Data, true); +block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc; + Type =:= des_ede3 -> + Key = check_des3_key(Key0), + block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true); +block_encrypt(des3_cbf, Key0, Ivec, Data) -> + Key = check_des3_key(Key0), + block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true); block_encrypt(aes_ige256, Key, Ivec, Data) -> - aes_ige_256_encrypt(Key, Ivec, Data); -block_encrypt(aes_cfb8, Key, Ivec, Data) -> - aes_cfb_8_encrypt(Key, Ivec, Data); -block_encrypt(aes_cfb128, Key, Ivec, Data) -> - aes_cfb_128_encrypt(Key, Ivec, Data); + aes_ige_crypt_nif(Key, Ivec, Data, true); block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) -> - case aes_gcm_encrypt(Key, Ivec, AAD, Data) of - notsup -> erlang:error(notsup); - Return -> Return - end; + aes_gcm_encrypt(Key, Ivec, AAD, Data); block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) -> - case chacha20_poly1305_encrypt(Key, Ivec, AAD, Data) of - notsup -> erlang:error(notsup); - Return -> Return - end; -block_encrypt(rc2_cbc, Key, Ivec, Data) -> - rc2_cbc_encrypt(Key, Ivec, Data). + chacha20_poly1305_encrypt(Key, Ivec, AAD, Data). --spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | - blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_ige256 | - aes_cfb8 | aes_cfb128 | rc2_cbc, +-spec block_decrypt(des_cbc | des_cfb | + des3_cbc | des3_cbf | des_ede3 | + blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 | + aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 | + rc2_cbc, Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(); (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error. -block_decrypt(des_cbc, Key, Ivec, Data) -> - des_cbc_decrypt(Key, Ivec, Data); -block_decrypt(des_cfb, Key, Ivec, Data) -> - des_cfb_decrypt(Key, Ivec, Data); -block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) -> - des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data); -block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) -> - des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data); -block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) -> - des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data); -block_decrypt(blowfish_cbc, Key, Ivec, Data) -> - blowfish_cbc_decrypt(Key, Ivec, Data); -block_decrypt(blowfish_cfb64, Key, Ivec, Data) -> - blowfish_cfb64_decrypt(Key, Ivec, Data); -block_decrypt(blowfish_ofb64, Key, Ivec, Data) -> - blowfish_ofb64_decrypt(Key, Ivec, Data); -block_decrypt(aes_cbc128, Key, Ivec, Data) -> - aes_cbc_128_decrypt(Key, Ivec, Data); -block_decrypt(aes_cbc256, Key, Ivec, Data) -> - aes_cbc_256_decrypt(Key, Ivec, Data); +block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc; + Type =:= des_cfb; + Type =:= blowfish_cbc; + Type =:= blowfish_cfb64; + Type =:= blowfish_ofb64; + Type =:= aes_cbc128; + Type =:= aes_cfb8; + Type =:= aes_cfb128; + Type =:= aes_cbc256; + Type =:= rc2_cbc -> + block_crypt_nif(Type, Key, Ivec, Data, false); +block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc; + Type =:= des_ede3 -> + Key = check_des3_key(Key0), + block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false); +block_decrypt(des3_cbf, Key0, Ivec, Data) -> + Key = check_des3_key(Key0), + block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false); block_decrypt(aes_ige256, Key, Ivec, Data) -> - aes_ige_256_decrypt(Key, Ivec, Data); -block_decrypt(aes_cfb8, Key, Ivec, Data) -> - aes_cfb_8_decrypt(Key, Ivec, Data); -block_decrypt(aes_cfb128, Key, Ivec, Data) -> - aes_cfb_128_decrypt(Key, Ivec, Data); + notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false)); block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) -> - case aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag) of - notsup -> erlang:error(notsup); - Return -> Return - end; + aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag); block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) -> - case chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag) of - notsup -> erlang:error(notsup); - Return -> Return - end; -block_decrypt(rc2_cbc, Key, Ivec, Data) -> - rc2_cbc_decrypt(Key, Ivec, Data). + chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag). -spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary(). -block_encrypt(des_ecb, Key, Data) -> - des_ecb_encrypt(Key, Data); -block_encrypt(blowfish_ecb, Key, Data) -> - blowfish_ecb_encrypt(Key, Data); -block_encrypt(aes_ecb, Key, Data) -> - aes_ecb_encrypt(Key, Data). +block_encrypt(Type, Key, Data) -> + block_crypt_nif(Type, Key, Data, true). -spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary(). -block_decrypt(des_ecb, Key, Data) -> - des_ecb_decrypt(Key, Data); -block_decrypt(blowfish_ecb, Key, Data) -> - blowfish_ecb_decrypt(Key, Data); -block_decrypt(aes_ecb, Key, Data) -> - aes_ecb_decrypt(Key, Data). +block_decrypt(Type, Key, Data) -> + block_crypt_nif(Type, Key, Data, false). -spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary(). -next_iv(des_cbc, Data) -> - des_cbc_ivec(Data); -next_iv(des3_cbc, Data) -> - des_cbc_ivec(Data); -next_iv(aes_cbc, Data) -> - aes_cbc_ivec(Data); -next_iv(aes_ige, Data) -> - aes_ige_ivec(Data). +next_iv(Type, Data) when is_binary(Data) -> + IVecSize = case Type of + des_cbc -> 8; + des3_cbc -> 8; + aes_cbc -> 16; + aes_ige -> 32 + end, + {_, IVec} = split_binary(Data, size(Data) - IVecSize), + IVec; +next_iv(Type, Data) when is_list(Data) -> + next_iv(Type, list_to_binary(Data)). -spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary(). -next_iv(des_cfb, Data, Ivec) -> - des_cfb_ivec(Ivec, Data); +next_iv(des_cfb, Data, IVec) -> + IVecAndData = list_to_binary([IVec, Data]), + {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8), + NewIVec; next_iv(Type, Data, _Ivec) -> next_iv(Type, Data). stream_init(aes_ctr, Key, Ivec) -> {aes_ctr, aes_ctr_stream_init(Key, Ivec)}. stream_init(rc4, Key) -> - {rc4, rc4_set_key(Key)}. + {rc4, notsup_to_error(rc4_set_key(Key))}. stream_encrypt(State, Data0) -> Data = iolist_to_binary(Data0), @@ -485,35 +448,31 @@ verify(dss, none, Data, Signature, Key) when is_binary(Data) -> verify(dss, sha, {digest, Data}, Signature, Key); verify(Alg, Type, Data, Signature, Key) when is_binary(Data) -> verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key); -verify(dss, Type, Data, Signature, Key) -> - dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key)); -verify(rsa, Type, DataOrDigest, Signature, Key) -> - case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of - notsup -> erlang:error(notsup); - Bool -> Bool - end; -verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) -> - case ecdsa_verify_nif(Type, DataOrDigest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key)) of - notsup -> erlang:error(notsup); - Bool -> Bool - end. +verify(dss, Type, {digest, Digest}, Signature, Key) -> + dss_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key)); +verify(rsa, Type, {digest, Digest}, Signature, Key) -> + notsup_to_error( + rsa_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key))); +verify(ecdsa, Type, {digest, Digest}, Signature, [Key, Curve]) -> + notsup_to_error( + ecdsa_verify_nif(Type, Digest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key))). sign(dss, none, Data, Key) when is_binary(Data) -> sign(dss, sha, {digest, Data}, Key); sign(Alg, Type, Data, Key) when is_binary(Data) -> sign(Alg, Type, {digest, hash(Type, Data)}, Key); -sign(rsa, Type, DataOrDigest, Key) -> - case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of - error -> erlang:error(badkey, [Type,DataOrDigest,Key]); +sign(rsa, Type, {digest, Digest}, Key) -> + case rsa_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of + error -> erlang:error(badkey, [Type,Digest,Key]); Sign -> Sign end; -sign(dss, Type, DataOrDigest, Key) -> - case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of - error -> erlang:error(badkey, [DataOrDigest, Key]); +sign(dss, Type, {digest, Digest}, Key) -> + case dss_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of + error -> erlang:error(badkey, [Digest, Key]); Sign -> Sign end; -sign(ecdsa, Type, DataOrDigest, [Key, Curve]) -> - case ecdsa_sign_nif(Type, DataOrDigest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of - error -> erlang:error(badkey, [Type,DataOrDigest,Key]); +sign(ecdsa, Type, {digest, Digest}, [Key, Curve]) -> + case ecdsa_sign_nif(Type, Digest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of + error -> erlang:error(badkey, [Type,Digest,Key]); Sign -> Sign end. @@ -618,8 +577,9 @@ compute_key(srp, HostPublic, {UserPublic, UserPrivate}, HostPubBin, Prime); [S] -> S end, + notsup_to_error( srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin, - Multiplier, Generator, DerivedKey, Prime); + Multiplier, Generator, DerivedKey, Prime)); compute_key(srp, UserPublic, {HostPublic, HostPrivate}, {host,[Verifier, Prime, Version | ScramblerArg]}) when @@ -631,8 +591,9 @@ compute_key(srp, UserPublic, {HostPublic, HostPrivate}, [] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime); [S] -> S end, + notsup_to_error( srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler, - UserPubBin, Prime); + UserPubBin, Prime)); compute_key(ecdh, Others, My, Curve) -> ecdh_compute_key_nif(ensure_int_as_bin(Others), @@ -677,7 +638,8 @@ on_load() -> end end, Lib = filename:join([PrivDir, "lib", LibName]), - Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,path2bin(Lib)}) of + LibBin = path2bin(Lib), + Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,LibBin}) of ok -> ok; {error, {load_failed, _}}=Error1 -> ArchLibDir = @@ -689,7 +651,8 @@ on_load() -> [] -> Error1; _ -> ArchLib = filename:join([ArchLibDir, LibName]), - erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,path2bin(ArchLib)}) + ArchBin = path2bin(ArchLib), + erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchBin}) end; Error1 -> Error1 end, @@ -714,46 +677,30 @@ path2bin(Path) when is_list(Path) -> max_bytes() -> ?MAX_BYTES_TO_NIF. +notsup_to_error(notsup) -> + erlang:error(notsup); +notsup_to_error(Other) -> + Other. + %% HASH -------------------------------------------------------------------- -hash(Hash, Data, Size, Max, initial) when Size =< Max -> - do_hash(Hash, Data); -hash(State0, Data, Size, Max, continue) when Size =< Max -> - State = do_hash_update(State0, Data), - hash_final(State); -hash(Hash, Data, _Size, Max, initial) -> - <> = Data, +hash(Hash, Data, Size, Max) when Size =< Max -> + notsup_to_error(hash_nif(Hash, Data)); +hash(Hash, Data, Size, Max) -> State0 = hash_init(Hash), - State = do_hash_update(State0, Increment), - hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue); -hash(State0, Data, _Size, MaxByts, continue) -> - <> = Data, - State = do_hash_update(State0, Increment), - hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue). - -do_hash(md5, Data) -> md5(Data); -do_hash(md4, Data) -> md4(Data); -do_hash(sha, Data) -> sha(Data); -do_hash(ripemd160, Data) -> ripemd160(Data); -do_hash(sha224, Data) -> sha224(Data); -do_hash(sha256, Data) -> sha256(Data); -do_hash(sha384, Data) -> sha384(Data); -do_hash(sha512, Data) -> sha512(Data). + State1 = hash_update(State0, Data, Size, Max), + hash_final(State1). hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes -> - do_hash_update(State, Data); + notsup_to_error(hash_update_nif(State, Data)); hash_update(State0, Data, _, MaxBytes) -> <> = Data, - State = do_hash_update(State0, Increment), + State = notsup_to_error(hash_update_nif(State0, Increment)), hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes). -do_hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)}; -do_hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)}; -do_hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)}; -do_hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)}; -do_hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)}; -do_hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)}; -do_hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)}; -do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}. +hash_nif(_Hash, _Data) -> ?nif_stub. +hash_init_nif(_Hash) -> ?nif_stub. +hash_update_nif(_State, _Data) -> ?nif_stub. +hash_final_nif(_State) -> ?nif_stub. %% @@ -765,10 +712,14 @@ do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data -spec md5_update(binary(), iodata()) -> binary(). -spec md5_final(binary()) -> binary(). -md5(_Data) -> ?nif_stub. -md5_init() -> ?nif_stub. -md5_update(_Context, _Data) -> ?nif_stub. -md5_final(_Context) -> ?nif_stub. +md5(Data) -> + hash(md5, Data). +md5_init() -> + hash_init(md5). +md5_update(Context, Data) -> + hash_update(Context, Data). +md5_final(Context) -> + hash_final(Context). %% %% MD4 @@ -778,24 +729,14 @@ md5_final(_Context) -> ?nif_stub. -spec md4_update(binary(), iodata()) -> binary(). -spec md4_final(binary()) -> binary(). -md4(_Data) -> ?nif_stub. -md4_init() -> ?nif_stub. -md4_update(_Context, _Data) -> ?nif_stub. -md4_final(_Context) -> ?nif_stub. - -%% -%% RIPEMD160 -%% - --spec ripemd160(iodata()) -> binary(). --spec ripemd160_init() -> binary(). --spec ripemd160_update(binary(), iodata()) -> binary(). --spec ripemd160_final(binary()) -> binary(). - -ripemd160(_Data) -> ?nif_stub. -ripemd160_init() -> ?nif_stub. -ripemd160_update(_Context, _Data) -> ?nif_stub. -ripemd160_final(_Context) -> ?nif_stub. +md4(Data) -> + hash(md4, Data). +md4_init() -> + hash_init(md4). +md4_update(Context, Data) -> + hash_update(Context, Data). +md4_final(Context) -> + hash_final(Context). %% %% SHA @@ -805,196 +746,44 @@ ripemd160_final(_Context) -> ?nif_stub. -spec sha_update(binary(), iodata()) -> binary(). -spec sha_final(binary()) -> binary(). -sha(_Data) -> ?nif_stub. -sha_init() -> ?nif_stub. -sha_update(_Context, _Data) -> ?nif_stub. -sha_final(_Context) -> ?nif_stub. - -% -%% SHA224 -%% --spec sha224(iodata()) -> binary(). --spec sha224_init() -> binary(). --spec sha224_update(binary(), iodata()) -> binary(). --spec sha224_final(binary()) -> binary(). - -sha224(Data) -> - case sha224_nif(Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha224_init() -> - case sha224_init_nif() of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha224_update(Context, Data) -> - case sha224_update_nif(Context, Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha224_final(Context) -> - case sha224_final_nif(Context) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -sha224_nif(_Data) -> ?nif_stub. -sha224_init_nif() -> ?nif_stub. -sha224_update_nif(_Context, _Data) -> ?nif_stub. -sha224_final_nif(_Context) -> ?nif_stub. - -% -%% SHA256 -%% --spec sha256(iodata()) -> binary(). --spec sha256_init() -> binary(). --spec sha256_update(binary(), iodata()) -> binary(). --spec sha256_final(binary()) -> binary(). - -sha256(Data) -> - case sha256_nif(Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha256_init() -> - case sha256_init_nif() of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha256_update(Context, Data) -> - case sha256_update_nif(Context, Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha256_final(Context) -> - case sha256_final_nif(Context) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -sha256_nif(_Data) -> ?nif_stub. -sha256_init_nif() -> ?nif_stub. -sha256_update_nif(_Context, _Data) -> ?nif_stub. -sha256_final_nif(_Context) -> ?nif_stub. - -% -%% SHA384 -%% --spec sha384(iodata()) -> binary(). --spec sha384_init() -> binary(). --spec sha384_update(binary(), iodata()) -> binary(). --spec sha384_final(binary()) -> binary(). - -sha384(Data) -> - case sha384_nif(Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha384_init() -> - case sha384_init_nif() of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha384_update(Context, Data) -> - case sha384_update_nif(Context, Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha384_final(Context) -> - case sha384_final_nif(Context) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -sha384_nif(_Data) -> ?nif_stub. -sha384_init_nif() -> ?nif_stub. -sha384_update_nif(_Context, _Data) -> ?nif_stub. -sha384_final_nif(_Context) -> ?nif_stub. - -% -%% SHA512 -%% --spec sha512(iodata()) -> binary(). --spec sha512_init() -> binary(). --spec sha512_update(binary(), iodata()) -> binary(). --spec sha512_final(binary()) -> binary(). - -sha512(Data) -> - case sha512_nif(Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha512_init() -> - case sha512_init_nif() of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha512_update(Context, Data) -> - case sha512_update_nif(Context, Data) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. -sha512_final(Context) -> - case sha512_final_nif(Context) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -sha512_nif(_Data) -> ?nif_stub. -sha512_init_nif() -> ?nif_stub. -sha512_update_nif(_Context, _Data) -> ?nif_stub. -sha512_final_nif(_Context) -> ?nif_stub. +sha(Data) -> + hash(sha, Data). +sha_init() -> + hash_init(sha). +sha_update(Context, Data) -> + hash_update(Context, Data). +sha_final(Context) -> + hash_final(Context). %% HMAC -------------------------------------------------------------------- -hmac(Type, Key, Data, MacSize, Size, MaxBytes, initial) when Size =< MaxBytes -> +hmac(Type, Key, Data, MacSize, Size, MaxBytes) when Size =< MaxBytes -> + notsup_to_error( case MacSize of - undefined -> - do_hmac(Type, Key, Data); - _ -> - do_hmac(Type, Key, Data, MacSize) - end; -hmac(Type, Key, Data, MacSize, _, MaxBytes, initial) -> - <> = Data, + undefined -> hmac_nif(Type, Key, Data); + _ -> hmac_nif(Type, Key, Data, MacSize) + end); +hmac(Type, Key, Data, MacSize, Size, MaxBytes) -> State0 = hmac_init(Type, Key), - State = hmac_update(State0, Increment), - hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue). -hmac(State0, Data, MacSize, Size, MaxBytes, continue) when Size =< MaxBytes -> - State = hmac_update(State0, Data), + State1 = hmac_update(State0, Data, Size, MaxBytes), case MacSize of - undefined -> - hmac_final(State); - _ -> - hmac_final_n(State, MacSize) - end; -hmac(State0, Data, MacSize, _Size, MaxBytes, continue) -> - <> = Data, - State = hmac_update(State0, Increment), - hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue). + undefined -> hmac_final(State1); + _ -> hmac_final_n(State1, MacSize) + end. hmac_update(State, Data, Size, MaxBytes) when Size =< MaxBytes -> - do_hmac_update(State, Data); + notsup_to_error(hmac_update_nif(State, Data)); hmac_update(State0, Data, _, MaxBytes) -> <> = Data, - State = do_hmac_update(State0, Increment), + State = notsup_to_error(hmac_update_nif(State0, Increment)), hmac_update(State, Rest, erlang:byte_size(Rest), MaxBytes). -do_hmac(md5, Key, Data) -> md5_mac(Key, Data); -do_hmac(sha, Key, Data) -> sha_mac(Key, Data); -do_hmac(sha224, Key, Data) -> sha224_mac(Key, Data); -do_hmac(sha256, Key, Data) -> sha256_mac(Key, Data); -do_hmac(sha384, Key, Data) -> sha384_mac(Key, Data); -do_hmac(sha512, Key, Data) -> sha512_mac(Key, Data). - -do_hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size); -do_hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size); -do_hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size); -do_hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size); -do_hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size); -do_hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size). - -do_hmac_update(_Context, _Data) -> ? nif_stub. +hmac_nif(_Type, _Key, _Data) -> ?nif_stub. +hmac_nif(_Type, _Key, _Data, _MacSize) -> ?nif_stub. +hmac_init_nif(_Type, _Key) -> ?nif_stub. +hmac_update_nif(_Context, _Data) -> ?nif_stub. +hmac_final_nif(_Context) -> ?nif_stub. +hmac_final_nif(_Context, _MacSize) -> ?nif_stub. %% %% MD5_MAC @@ -1002,97 +791,37 @@ do_hmac_update(_Context, _Data) -> ? nif_stub. -spec md5_mac(iodata(), iodata()) -> binary(). -spec md5_mac_96(iodata(), iodata()) -> binary(). -md5_mac(Key, Data) -> - md5_mac_n(Key,Data,16). +md5_mac(Key, Data) -> hmac(md5, Key, Data). -md5_mac_96(Key, Data) -> - md5_mac_n(Key,Data,12). +md5_mac_96(Key, Data) -> hmac(md5, Key, Data, 12). -md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub. - %% %% SHA_MAC %% -spec sha_mac(iodata(), iodata()) -> binary(). -spec sha_mac_96(iodata(), iodata()) -> binary(). -sha_mac(Key, Data) -> - sha_mac_n(Key,Data,20). - -sha_mac(Key, Data, Size) -> - sha_mac_n(Key, Data, Size). - -sha_mac_96(Key, Data) -> - sha_mac_n(Key,Data,12). - -sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub. - -%% -%% SHA224_MAC -%% --spec sha224_mac(iodata(), iodata()) -> binary(). - -sha224_mac(Key, Data) -> - sha224_mac(Key, Data, 224 div 8). - -sha224_mac(Key, Data, Size) -> - case sha224_mac_nif(Key, Data, Size) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -sha224_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub. - -%% -%% SHA256_MAC -%% --spec sha256_mac(iodata(), iodata()) -> binary(). - -sha256_mac(Key, Data) -> - sha256_mac(Key, Data, 256 div 8). - -sha256_mac(Key, Data, Size) -> - case sha256_mac_nif(Key, Data, Size) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -sha256_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub. - -%% -%% SHA384_MAC -%% --spec sha384_mac(iodata(), iodata()) -> binary(). - -sha384_mac(Key, Data) -> - sha384_mac(Key, Data, 384 div 8). +sha_mac(Key, Data) -> hmac(sha, Key, Data). -sha384_mac(Key, Data, Size) -> - case sha384_mac_nif(Key, Data, Size) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -sha384_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub. +sha_mac(Key, Data, Size) -> hmac(sha, Key, Data, Size). -%% -%% SHA512_MAC -%% --spec sha512_mac(iodata(), iodata()) -> binary(). +sha_mac_96(Key, Data) -> hmac(sha, Key, Data, 12). -sha512_mac(Key, Data) -> - sha512_mac(Key, Data, 512 div 8). +%% CIPHERS -------------------------------------------------------------------- -sha512_mac(Key, Data, MacSz) -> - case sha512_mac_nif(Key, Data, MacSz) of - notsup -> erlang:error(notsup); - Bin -> Bin +block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub. +block_crypt_nif(_Type, _Key, _Text, _IsEncrypt) -> ?nif_stub. + +check_des3_key(Key) -> + case lists:map(fun erlang:iolist_to_binary/1, Key) of + ValidKey = [B1, B2, B3] when byte_size(B1) =:= 8, + byte_size(B2) =:= 8, + byte_size(B3) =:= 8 -> + ValidKey; + _ -> + error(badarg) end. -sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub. - -%% CIPHERS -------------------------------------------------------------------- - %% %% DES - in electronic codebook mode (ECB) %% @@ -1100,10 +829,9 @@ sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub. -spec des_ecb_decrypt(iodata(), iodata()) -> binary(). des_ecb_encrypt(Key, Data) -> - des_ecb_crypt(Key, Data, true). + block_encrypt(des_ecb, Key, Data). des_ecb_decrypt(Key, Data) -> - des_ecb_crypt(Key, Data, false). -des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(des_ecb, Key, Data). %% %% DES3 - in cipher block chaining mode (CBC) @@ -1114,16 +842,14 @@ des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub. binary(). des3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) -> - des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true). + block_encrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data). des_ede3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) -> - des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true). + block_encrypt(des_ede3, [Key1, Key2, Key3], IVec, Data). des3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) -> - des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false). + block_decrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data). des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) -> - des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false). - -des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(des_ede3, [Key1, Key2, Key3], IVec, Data). %% %% DES3 - in 8-bits cipher feedback mode (CFB) @@ -1134,18 +860,10 @@ des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub. binary(). des3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) -> - des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, true). + block_encrypt(des3_cbf, [Key1, Key2, Key3], IVec, Data). des3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) -> - des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, false). - -des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, IsEncrypt) -> - case des_ede3_cfb_crypt_nif(Key1,Key2,Key3,IVec,Data,IsEncrypt) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - -des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(des3_cbf, [Key1, Key2, Key3], IVec, Data). %% %% Blowfish @@ -1159,49 +877,27 @@ des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_st -spec blowfish_ofb64_encrypt(iodata(), binary(), iodata()) -> binary(). blowfish_ecb_encrypt(Key, Data) -> - bf_ecb_crypt(Key,Data, true). + block_encrypt(blowfish_ecb, Key, Data). blowfish_ecb_decrypt(Key, Data) -> - bf_ecb_crypt(Key,Data, false). - -bf_ecb_crypt(_Key,_Data,_IsEncrypt) -> ?nif_stub. + block_decrypt(blowfish_ecb, Key, Data). blowfish_cbc_encrypt(Key, IVec, Data) -> - bf_cbc_crypt(Key,IVec,Data,true). + block_encrypt(blowfish_cbc, Key, IVec, Data). blowfish_cbc_decrypt(Key, IVec, Data) -> - bf_cbc_crypt(Key,IVec,Data,false). - -bf_cbc_crypt(_Key,_IVec,_Data,_IsEncrypt) -> ?nif_stub. + block_decrypt(blowfish_cbc, Key, IVec, Data). blowfish_cfb64_encrypt(Key, IVec, Data) -> - bf_cfb64_crypt(Key, IVec, Data, true). + block_encrypt(blowfish_cfb64, Key, IVec, Data). blowfish_cfb64_decrypt(Key, IVec, Data) -> - bf_cfb64_crypt(Key, IVec, Data, false). - -bf_cfb64_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. - -blowfish_ofb64_decrypt(Key, Ivec, Data) -> - blowfish_ofb64_encrypt(Key, Ivec, Data). + block_decrypt(blowfish_cfb64, Key, IVec, Data). -blowfish_ofb64_encrypt(_Key, _IVec, _Data) -> ?nif_stub. +blowfish_ofb64_encrypt(Key, IVec, Data) -> + block_encrypt(blowfish_ofb64, Key, IVec, Data). -%% -%% AES in cipher feedback mode (CFB) - 8 bit shift -%% --spec aes_cfb_8_encrypt(iodata(), binary(), iodata()) -> binary(). --spec aes_cfb_8_decrypt(iodata(), binary(), iodata()) -> binary(). - -aes_cfb_8_encrypt(Key, IVec, Data) -> - aes_cfb_8_crypt(Key, IVec, Data, true). - -aes_cfb_8_decrypt(Key, IVec, Data) -> - aes_cfb_8_crypt(Key, IVec, Data, false). - -aes_cfb_8_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. - %% %% AES in cipher feedback mode (CFB) - 128 bit shift %% @@ -1209,12 +905,10 @@ aes_cfb_8_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. -spec aes_cfb_128_decrypt(iodata(), binary(), iodata()) -> binary(). aes_cfb_128_encrypt(Key, IVec, Data) -> - aes_cfb_128_crypt(Key, IVec, Data, true). + block_encrypt(aes_cfb128, Key, IVec, Data). aes_cfb_128_decrypt(Key, IVec, Data) -> - aes_cfb_128_crypt(Key, IVec, Data, false). - -aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(aes_cfb128, Key, IVec, Data). %% %% AES - in Galois/Counter Mode (GCM) @@ -1235,12 +929,10 @@ chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub. -spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary(). des_cbc_encrypt(Key, IVec, Data) -> - des_cbc_crypt(Key, IVec, Data, true). + block_encrypt(des_cbc, Key, IVec, Data). des_cbc_decrypt(Key, IVec, Data) -> - des_cbc_crypt(Key, IVec, Data, false). - -des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(des_cbc, Key, IVec, Data). %% %% dec_cbc_ivec(Data) -> binary() @@ -1250,11 +942,8 @@ des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. %% -spec des_cbc_ivec(iodata()) -> binary(). -des_cbc_ivec(Data) when is_binary(Data) -> - {_, IVec} = split_binary(Data, size(Data) - 8), - IVec; -des_cbc_ivec(Data) when is_list(Data) -> - des_cbc_ivec(list_to_binary(Data)). +des_cbc_ivec(Data) -> + next_iv(des_cbc, Data). %% %% DES - in 8-bits cipher feedback mode (CFB) @@ -1263,12 +952,10 @@ des_cbc_ivec(Data) when is_list(Data) -> -spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary(). des_cfb_encrypt(Key, IVec, Data) -> - des_cfb_crypt(Key, IVec, Data, true). + block_encrypt(des_cfb, Key, IVec, Data). des_cfb_decrypt(Key, IVec, Data) -> - des_cfb_crypt(Key, IVec, Data, false). - -des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(des_cfb, Key, IVec, Data). %% %% dec_cfb_ivec(IVec, Data) -> binary() @@ -1280,9 +967,7 @@ des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. -spec des_cfb_ivec(iodata(), iodata()) -> binary(). des_cfb_ivec(IVec, Data) -> - IVecAndData = list_to_binary([IVec, Data]), - {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8), - NewIVec. + next_iv(des_cfb, Data, IVec). %% @@ -1298,18 +983,16 @@ des_cfb_ivec(IVec, Data) -> binary(). aes_cbc_128_encrypt(Key, IVec, Data) -> - aes_cbc_crypt(Key, IVec, Data, true). + block_encrypt(aes_cbc128, Key, IVec, Data). aes_cbc_128_decrypt(Key, IVec, Data) -> - aes_cbc_crypt(Key, IVec, Data, false). + block_decrypt(aes_cbc128, Key, IVec, Data). aes_cbc_256_encrypt(Key, IVec, Data) -> - aes_cbc_crypt(Key, IVec, Data, true). + block_encrypt(aes_cbc256, Key, IVec, Data). aes_cbc_256_decrypt(Key, IVec, Data) -> - aes_cbc_crypt(Key, IVec, Data, false). - -aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(aes_cbc256, Key, IVec, Data). %% %% aes_cbc_ivec(Data) -> binary() @@ -1318,47 +1001,15 @@ aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. %% aes_cbc_*_[encrypt|decrypt]. %% IVec size: 16 bytes %% -aes_cbc_ivec(Data) when is_binary(Data) -> - {_, IVec} = split_binary(Data, size(Data) - 16), - IVec; -aes_cbc_ivec(Data) when is_list(Data) -> - aes_cbc_ivec(list_to_binary(Data)). - +aes_cbc_ivec(Data) -> + next_iv(aes_cbc, Data). %% %% AES - with 256 bit key in infinite garble extension mode (IGE) %% --spec aes_ige_256_decrypt(iodata(), binary(), iodata()) -> - binary(). - -aes_ige_256_encrypt(Key, IVec, Data) -> - aes_ige_crypt(Key, IVec, Data, true). - -aes_ige_256_decrypt(Key, IVec, Data) -> - aes_ige_crypt(Key, IVec, Data, false). - -aes_ige_crypt(Key, IVec, Data, IsEncrypt) -> - case aes_ige_crypt_nif(Key,IVec,Data,IsEncrypt) of - notsup -> erlang:error(notsup); - Bin -> Bin - end. - aes_ige_crypt_nif(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. -%% -%% aes_ige_ivec(Data) -> binary() -%% -%% Returns the IVec to be used in the next iteration of -%% aes_ige_*_[encrypt|decrypt]. -%% IVec size: 32 bytes -%% -aes_ige_ivec(Data) when is_binary(Data) -> - {_, IVec} = split_binary(Data, size(Data) - 32), - IVec; -aes_ige_ivec(Data) when is_list(Data) -> - aes_ige_ivec(list_to_binary(Data)). - %% Stream ciphers -------------------------------------------------------------------- @@ -1397,22 +1048,11 @@ do_stream_decrypt({rc4, State0}, Data) -> aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub. aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub. -%% -%% AES - in electronic codebook mode (ECB) -%% -aes_ecb_encrypt(Key, Data) -> - aes_ecb_crypt(Key, Data, true). - -aes_ecb_decrypt(Key, Data) -> - aes_ecb_crypt(Key, Data, false). - -aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub. - %% %% AES - in counter mode (CTR) with state maintained for multi-call streaming %% --type ctr_state() :: { iodata(), binary(), binary(), integer() }. +-type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary(). -spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state(). -spec aes_ctr_stream_encrypt(ctr_state(), binary()) -> @@ -1420,10 +1060,9 @@ aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub. -spec aes_ctr_stream_decrypt(ctr_state(), binary()) -> { ctr_state(), binary() }. -aes_ctr_stream_init(Key, IVec) -> - {Key, IVec, << 0:128 >>, 0}. -aes_ctr_stream_encrypt({_Key, _IVec, _ECount, _Num}=_State, _Data) -> ?nif_stub. -aes_ctr_stream_decrypt({_Key, _IVec, _ECount, _Num}=_State, _Cipher) -> ?nif_stub. +aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub. +aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub. +aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub. %% %% RC4 - symmetric stream cipher @@ -1438,21 +1077,19 @@ rc4_encrypt_with_state(_State, _Data) -> ?nif_stub. %% RC2 block cipher rc2_cbc_encrypt(Key, IVec, Data) -> - rc2_cbc_crypt(Key,IVec,Data,true). + block_encrypt(rc2_cbc, Key, IVec, Data). rc2_cbc_decrypt(Key, IVec, Data) -> - rc2_cbc_crypt(Key,IVec,Data,false). - -rc2_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + block_decrypt(rc2_cbc, Key, IVec, Data). %% %% RC2 - 40 bits block cipher - Backwards compatibility not documented. %% rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 -> - rc2_cbc_crypt(Key,IVec,Data,true). + block_encrypt(rc2_cbc, Key, IVec, Data). rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 -> - rc2_cbc_crypt(Key,IVec,Data,false). + block_decrypt(rc2_cbc, Key, IVec, Data). %% Secure remote password ------------------------------------------------------------------- @@ -1470,16 +1107,18 @@ host_srp_gen_key(Private, Verifier, Generator, Prime, Version) -> case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of error -> error; + notsup -> + erlang:error(notsup); Public -> {Public, Private} end. srp_multiplier('6a', Generator, Prime) -> %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html - C0 = sha_init(), - C1 = sha_update(C0, Prime), - C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)), - sha_final(C2); + C0 = hash_init(sha), + C1 = hash_update(C0, Prime), + C2 = hash_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)), + hash_final(C2); srp_multiplier('6', _, _) -> <<3/integer>>; srp_multiplier('3', _, _) -> @@ -1488,10 +1127,10 @@ srp_multiplier('3', _, _) -> srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'-> %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html PadLength = erlang:byte_size(Prime), - C0 = sha_init(), - C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)), - C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)), - sha_final(C2); + C0 = hash_init(sha), + C1 = hash_update(C0, srp_pad_to(PadLength, UserPublic)), + C2 = hash_update(C1, srp_pad_to(PadLength, HostPublic)), + hash_final(C2); srp_scrambler('3', _, HostPublic, _Prime) -> %% The parameter u is a 32-bit unsigned integer which takes its value %% from the first 32 bits of the SHA1 hash of B, MSB first. @@ -1515,13 +1154,13 @@ srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_s %% Digital signatures -------------------------------------------------------------------- -rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub. -dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub. -ecdsa_sign_nif(_Type, _DataOrDigest, _Curve, _Key) -> ?nif_stub. +rsa_sign_nif(_Type,_Digest,_Key) -> ?nif_stub. +dss_sign_nif(_Type,_Digest,_Key) -> ?nif_stub. +ecdsa_sign_nif(_Type, _Digest, _Curve, _Key) -> ?nif_stub. -dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub. -rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub. -ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Curve, _Key) -> ?nif_stub. +dss_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub. +rsa_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub. +ecdsa_verify_nif(_Type, _Digest, _Signature, _Curve, _Key) -> ?nif_stub. %% Public Keys -------------------------------------------------------------------- %% DH Diffie-Hellman functions -- cgit v1.2.3 From 5e40dfbf957df2b64dc7e713c5c8fc83ea538f52 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 9 Jul 2015 16:41:53 +0200 Subject: Fix bug for aes_cfb_128_encrypt with empty binary causing OpenSSL 0.9.8h to crash with evp_enc.c(282): OpenSSL internal error, assertion failed: inl > 0 --- lib/crypto/c_src/crypto.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 595ee65415..3add54bcd3 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -1332,10 +1332,15 @@ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) || !EVP_CipherInit_ex(&ctx, NULL, NULL, key.data, ivec_size ? ivec.data : NULL, -1) || - !EVP_CIPHER_CTX_set_padding(&ctx, 0) || - !EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size) || - (ASSERT(out_size == text.size), 0) || - !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size)) { + !EVP_CIPHER_CTX_set_padding(&ctx, 0)) { + + return enif_raise_exception(env, atom_notsup); + } + + if (text.size > 0 && /* OpenSSL 0.9.8h asserts text.size > 0 */ + (!EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size) + || (ASSERT(out_size == text.size), 0) + || !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size))) { EVP_CIPHER_CTX_cleanup(&ctx); return enif_raise_exception(env, atom_notsup); -- cgit v1.2.3 From 929e12e6ed27f03cf91a6310bb996b87bc00e9b5 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 18 Aug 2015 16:47:19 +0200 Subject: Fix EVP_aes_???_ctr to demand OpenSSL 1.0.1 or later. --- lib/crypto/c_src/crypto.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 3add54bcd3..18aa8f19ed 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -91,6 +91,7 @@ #endif #if OPENSSL_VERSION_NUMBER >= 0x1000100fL +# define HAVE_EVP_AES_CTR # define HAVE_GCM #endif @@ -463,7 +464,9 @@ static ErlNifResourceType* evp_md_ctx_rtype; static void evp_md_ctx_dtor(ErlNifEnv* env, EVP_MD_CTX* ctx) { EVP_MD_CTX_cleanup(ctx); } +#endif +#ifdef HAVE_EVP_AES_CTR static ErlNifResourceType* evp_cipher_ctx_rtype; static void evp_cipher_ctx_dtor(ErlNifEnv* env, EVP_CIPHER_CTX* ctx) { EVP_CIPHER_CTX_cleanup(ctx); @@ -563,6 +566,8 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'"); return 0; } +#endif +#ifdef HAVE_EVP_AES_CTR evp_cipher_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_CIPHER_CTX", (ErlNifResourceDtor*) evp_cipher_ctx_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, @@ -1421,7 +1426,7 @@ static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, IVec, Data) */ ErlNifBinary key, ivec, text; -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL +#ifdef HAVE_EVP_AES_CTR const EVP_CIPHER *cipher; EVP_CIPHER_CTX ctx; unsigned char *out; @@ -1435,14 +1440,14 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM ret; if (!enif_inspect_iolist_as_binary(env, argv[0], &key) -#if OPENSSL_VERSION_NUMBER < 0x1000000fL +#ifndef HAVE_EVP_AES_CTR || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 #endif || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { return enif_make_badarg(env); } -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL +#ifdef HAVE_EVP_AES_CTR switch (key.size) { case 16: cipher = EVP_aes_128_ctr(); break; @@ -1477,7 +1482,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM /* Initializes state for ctr streaming (de)encryption */ -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL +#ifdef HAVE_EVP_AES_CTR static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, IVec) */ ErlNifBinary key_bin, ivec_bin; @@ -1533,7 +1538,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N return ret; } -#else /* if OPENSSL_VERSION_NUMBER < 1.0 */ +#else /* if not HAVE_EVP_AES_CTR */ static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, IVec) */ @@ -1590,7 +1595,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N CONSUME_REDS(env,text_bin); return ret; } -#endif /* OPENSSL_VERSION_NUMBER < 1.0 */ +#endif /* !HAVE_EVP_AES_CTR */ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key,Iv,AAD,In) */ -- cgit v1.2.3 From cfe998988c942bed0fbf026c00a2531fdf5aba7c Mon Sep 17 00:00:00 2001 From: "Nikolaos S. Papaspyrou" Date: Sat, 9 Jun 2012 00:19:28 +0300 Subject: Add the BIF size_shared/1 and debug cleanup --- lib/kernel/src/erts_debug.erl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 39308c0043..5e1cc09e7d 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -34,7 +34,8 @@ -export([breakpoint/2, disassemble/1, display/1, dist_ext_to_term/2, dump_monitors/1, dump_links/1, flat_size/1, get_internal_state/1, instructions/0, lock_counters/1, - map_info/1, same/2, set_internal_state/2]). + map_info/1, same/2, set_internal_state/2, + size_shared/1]). -spec breakpoint(MFA, Flag) -> non_neg_integer() when MFA :: {Module :: module(), @@ -86,6 +87,12 @@ dump_links(_) -> flat_size(_) -> erlang:nif_error(undef). +-spec size_shared(Term) -> non_neg_integer() when + Term :: term(). + +size_shared(_) -> + erlang:nif_error(undef). + -spec get_internal_state(W) -> term() when W :: reds_left | node_and_dist_references | monitoring_nodes | next_pid | 'DbTable_words' | check_io_debug -- cgit v1.2.3 From 8d02ad60c88aa060ff83ff3179bc8c0ab66868ee Mon Sep 17 00:00:00 2001 From: "Nikolaos S. Papaspyrou" Date: Fri, 14 Mar 2014 11:32:46 +0200 Subject: Add machinery to enable SHCOPY dynamically This commit is just for debugging purposes, will probably be reverted. It comes with a the erts_debug:copy_shared/1 BIF. If SHCOPY_DISABLE is defined, SHCOPY starts disabled and is dynamically enabled the first time that the BIF is called. --- lib/kernel/src/erts_debug.erl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 5e1cc09e7d..87f001fdf4 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -35,7 +35,7 @@ dump_monitors/1, dump_links/1, flat_size/1, get_internal_state/1, instructions/0, lock_counters/1, map_info/1, same/2, set_internal_state/2, - size_shared/1]). + size_shared/1, copy_shared/1]). -spec breakpoint(MFA, Flag) -> non_neg_integer() when MFA :: {Module :: module(), @@ -93,6 +93,12 @@ flat_size(_) -> size_shared(_) -> erlang:nif_error(undef). +-spec copy_shared(Term) -> term() when + Term :: term(). + +copy_shared(_) -> + erlang:nif_error(undef). + -spec get_internal_state(W) -> term() when W :: reds_left | node_and_dist_references | monitoring_nodes | next_pid | 'DbTable_words' | check_io_debug -- cgit v1.2.3 From 1993f0c858c2274c431c5f025c89e18d34282a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Nov 2015 10:38:07 +0100 Subject: epp: Modernize the internal data structures Use maps instead of 'dict'. Remove the {atom,MacroName} wrappers that were used for historical reasons. --- lib/stdlib/src/epp.erl | 211 +++++++++++++++++++++++++------------------------ 1 file changed, 107 insertions(+), 104 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 1d9762cfc7..0d3f725afe 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -40,7 +40,7 @@ -type ifdef() :: 'ifdef' | 'ifndef' | 'else'. --type name() :: {'atom', atom()}. +-type name() :: atom(). -type argspec() :: 'none' %No arguments | non_neg_integer(). %Number of arguments -type tokens() :: [erl_scan:token()]. @@ -58,21 +58,14 @@ istk=[] :: [ifdef()], %Ifdef stack sstk=[] :: [#epp{}], %State stack path=[] :: [file:name()], %Include-path - macs = dict:new() %Macros (don't care locations) - :: dict:dict(name(), {argspec(), tokens()}), - uses = dict:new() %Macro use structure - :: dict:dict(name(), [{argspec(), [used()]}]), + macs = #{} %Macros (don't care locations) + :: #{name() => {argspec(), tokens()}}, + uses = #{} %Macro use structure + :: #{name() => [{argspec(), [used()]}]}, default_encoding = ?DEFAULT_ENCODING :: source_encoding(), pre_opened = false :: boolean() }). -%%% Note on representation: as tokens, both {var, Location, Name} and -%%% {atom, Location, Name} can occur as macro identifiers. However, keeping -%%% this distinction here is done for historical reasons only: previously, -%%% ?FOO and ?'FOO' were not the same, but now they are. Removing the -%%% distinction in the internal representation would simplify the code -%%% a little. - %% open(Options) %% open(FileName, IncludePath) %% open(FileName, IncludePath, PreDefMacros) @@ -561,18 +554,18 @@ init_server(Pid, Name, Options, St0) -> %% FILE, LINE, MODULE as undefined, MACHINE and MACHINE value. predef_macros(File) -> - Machine = list_to_atom(erlang:system_info(machine)), - Anno = line1(), - dict:from_list([ - {{atom,'FILE'}, {none,[{string,Anno,File}]}}, - {{atom,'LINE'}, {none,[{integer,Anno,1}]}}, - {{atom,'MODULE'}, undefined}, - {{atom,'MODULE_STRING'}, undefined}, - {{atom,'BASE_MODULE'}, undefined}, - {{atom,'BASE_MODULE_STRING'}, undefined}, - {{atom,'MACHINE'}, {none,[{atom,Anno,Machine}]}}, - {{atom,Machine}, {none,[{atom,Anno,true}]}} - ]). + Machine = list_to_atom(erlang:system_info(machine)), + Anno = line1(), + Defs = [{'FILE', {none,[{string,Anno,File}]}}, + {'LINE', {none,[{integer,Anno,1}]}}, + {'MODULE', undefined}, + {'MODULE_STRING', undefined}, + {'BASE_MODULE', undefined}, + {'BASE_MODULE_STRING', undefined}, + {'MACHINE', {none,[{atom,Anno,Machine}]}}, + {Machine, {none,[{atom,Anno,true}]}} + ], + maps:from_list(Defs). %% user_predef(PreDefMacros, Macros) -> %% {ok,MacroDict} | {error,E} @@ -581,16 +574,18 @@ predef_macros(File) -> user_predef([{M,Val,redefine}|Pdm], Ms) when is_atom(M) -> Exp = erl_parse:tokens(erl_parse:abstract(Val)), - user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms)); + user_predef(Pdm, Ms#{M=>{none,Exp}}); user_predef([{M,Val}|Pdm], Ms) when is_atom(M) -> - case dict:find({atom,M}, Ms) of - {ok,_Defs} when is_list(_Defs) -> %% User defined macros + case Ms of + #{M:=Defs} when is_list(Defs) -> + %% User defined macros. {error,{redefine,M}}; - {ok,_Def} -> %% Predefined macros + #{M:=_Defs} -> + %% Predefined macros. {error,{redefine_predef,M}}; - error -> + _ -> Exp = erl_parse:tokens(erl_parse:abstract(Val)), - user_predef(Pdm, dict:store({atom,M}, [{none, {none,Exp}}], Ms)) + user_predef(Pdm, Ms#{M=>[{none,{none,Exp}}]}) end; user_predef([M|Pdm], Ms) when is_atom(M) -> user_predef([{M,true}|Pdm], Ms); @@ -607,7 +602,9 @@ wait_request(St) -> receive {epp_request,From,scan_erl_form} -> From; {epp_request,From,macro_defs} -> - epp_reply(From, dict:to_list(St#epp.macs)), + %% Return the old format to avoid any incompability issues. + Defs = [{{atom,K},V} || {K,V} <- maps:to_list(St#epp.macs)], + epp_reply(From, Defs), wait_request(St); {epp_request,From,close} -> close_file(St), @@ -659,7 +656,8 @@ enter_file(NewName, Inc, From, St) -> enter_file2(NewF, Pname, From, St0, AtLocation) -> Anno = erl_anno:new(AtLocation), enter_file_reply(From, Pname, Anno, AtLocation, code), - Ms = dict:store({atom,'FILE'}, {none,[{string,Anno,Pname}]}, St0#epp.macs), + Ms0 = St0#epp.macs, + Ms = Ms0#{'FILE':={none,[{string,Anno,Pname}]}}, %% update the head of the include path to be the directory of the new %% source file, so that an included file can always include other files %% relative to its current location (this is also how C does it); note @@ -711,9 +709,8 @@ leave_file(From, St) -> name2=OldName2} = OldSt, CurrLoc = add_line(OldLoc, Delta), Anno = erl_anno:new(CurrLoc), - Ms = dict:store({atom,'FILE'}, - {none,[{string,Anno,OldName2}]}, - St#epp.macs), + Ms0 = St#epp.macs, + Ms = Ms0#{'FILE':={none,[{string,Anno,OldName2}]}}, NextSt = OldSt#epp{sstk=Sts,macs=Ms,uses=St#epp.uses}, enter_file_reply(From, OldName, Anno, CurrLoc, code), case OldName2 =:= OldName of @@ -798,15 +795,14 @@ scan_module_1([{atom,_,_}=A,{',',L}|Ts], Ms) -> scan_module_1([A,{')',L}|Ts], Ms); scan_module_1([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) -> ModString = atom_to_list(A), - Ms = dict:store({atom,'MODULE'}, {none,[ModAtom]}, Ms0), - dict:store({atom,'MODULE_STRING'}, {none,[{string,Ln,ModString}]}, Ms); + Ms = Ms0#{'MODULE':={none,[ModAtom]}}, + Ms#{'MODULE_STRING':={none,[{string,Ln,ModString}]}}; scan_module_1(_Ts, Ms) -> Ms. scan_extends([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) -> ModString = atom_to_list(A), - Ms = dict:store({atom,'BASE_MODULE'}, {none,[ModAtom]}, Ms0), - dict:store({atom,'BASE_MODULE_STRING'}, - {none,[{string,Ln,ModString}]}, Ms); + Ms = Ms0#{'BASE_MODULE':={none,[ModAtom]}}, + Ms#{'BASE_MODULE_STRING':={none,[{string,Ln,ModString}]}}; scan_extends(_Ts, Ms) -> Ms. %% scan_define(Tokens, DefineToken, From, EppState) @@ -842,24 +838,23 @@ scan_define_1(_Toks, _Mac, Def, From, St) -> epp_reply(From, {error,{loc(Def),epp,{bad,define}}}), wait_req_scan(St). -scan_define_2(Arity, Def, {_,_,M}=Mac, From, St) -> - Key = {atom,M}, - case dict:find(Key, St#epp.macs) of - {ok,Defs} when is_list(Defs) -> +scan_define_2(Arity, Def, {_,_,Key}=Mac, From, #epp{macs=Ms}=St) -> + case Ms of + #{Key:=Defs} when is_list(Defs) -> %% User defined macros: can be overloaded case proplists:is_defined(Arity, Defs) of true -> - epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}), + epp_reply(From, {error,{loc(Mac),epp,{redefine,Key}}}), wait_req_scan(St); false -> - scan_define_cont(From, St, Key, Arity, Def) + scan_define_cont(From, St, Key, Defs, Arity, Def) end; - {ok,_PreDef} -> + #{Key:=_} -> %% Predefined macros: cannot be overloaded - epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}), + epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,Key}}}), wait_req_scan(St); - error -> - scan_define_cont(From, St, Key, Arity, Def) + _ -> + scan_define_cont(From, St, Key, [], Arity, Def) end. %%% Detection of circular macro expansions (which would either keep @@ -871,11 +866,17 @@ scan_define_2(Arity, Def, {_,_,M}=Mac, From, St) -> %%% the information from St#epp.uses is traversed, and if a circularity %%% is detected, an error message is thrown. -scan_define_cont(F, St, M, Arity, Def) -> - Ms = dict:append_list(M, [{Arity, Def}], St#epp.macs), - try dict:append_list(M, [{Arity, macro_uses(Def)}], St#epp.uses) of +scan_define_cont(F, #epp{macs=Ms0}=St, M, Defs, Arity, Def) -> + Ms = Ms0#{M=>[{Arity,Def}|Defs]}, + try macro_uses(Def) of U -> - scan_toks(F, St#epp{uses=U, macs=Ms}) + Uses0 = St#epp.uses, + Val = [{Arity,U}|case Uses0 of + #{M:=UseList} -> UseList; + _ -> [] + end], + Uses = Uses0#{M=>Val}, + scan_toks(F, St#epp{uses=Uses,macs=Ms}) catch {error, Line, Reason} -> epp_reply(F, {error,{Line,epp,Reason}}), @@ -893,23 +894,23 @@ macro_ref([{'?', _}, {'?', _} | Rest]) -> macro_ref([{'?', _}, {atom, _, A}=Atom | Rest]) -> Lm = loc(Atom), Arity = count_args(Rest, Lm, A), - [{{atom, A}, Arity} | macro_ref(Rest)]; + [{A,Arity} | macro_ref(Rest)]; macro_ref([{'?', _}, {var, _, A}=Var | Rest]) -> Lm = loc(Var), Arity = count_args(Rest, Lm, A), - [{{atom, A}, Arity} | macro_ref(Rest)]; + [{A,Arity} | macro_ref(Rest)]; macro_ref([_Token | Rest]) -> macro_ref(Rest). %% scan_undef(Tokens, UndefToken, From, EppState) scan_undef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From, St) -> - Macs = dict:erase({atom,M}, St#epp.macs), - Uses = dict:erase({atom,M}, St#epp.uses), + Macs = maps:remove(M, St#epp.macs), + Uses = maps:remove(M, St#epp.uses), scan_toks(From, St#epp{macs=Macs, uses=Uses}); scan_undef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From,St) -> - Macs = dict:erase({atom,M}, St#epp.macs), - Uses = dict:erase({atom,M}, St#epp.uses), + Macs = maps:remove(M, St#epp.macs), + Uses = maps:remove(M, St#epp.uses), scan_toks(From, St#epp{macs=Macs, uses=Uses}); scan_undef(_Toks, Undef, From, St) -> epp_reply(From, {error,{loc(Undef),epp,{bad,undef}}}), @@ -976,17 +977,17 @@ scan_include_lib(_Toks, Inc, From, St) -> %% Report a badly formed if[n]def test and then treat as undefined macro. scan_ifdef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfD, From, St) -> - case dict:find({atom,M}, St#epp.macs) of - {ok,_Def} -> + case St#epp.macs of + #{M:=_Def} -> scan_toks(From, St#epp{istk=[ifdef|St#epp.istk]}); - error -> + _ -> skip_toks(From, St, [ifdef]) end; scan_ifdef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfD, From, St) -> - case dict:find({atom,M}, St#epp.macs) of - {ok,_Def} -> + case St#epp.macs of + #{M:=_Def} -> scan_toks(From, St#epp{istk=[ifdef|St#epp.istk]}); - error -> + _ -> skip_toks(From, St, [ifdef]) end; scan_ifdef(_Toks, IfDef, From, St) -> @@ -994,17 +995,17 @@ scan_ifdef(_Toks, IfDef, From, St) -> wait_req_skip(St, [ifdef]). scan_ifndef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfnD, From, St) -> - case dict:find({atom,M}, St#epp.macs) of - {ok,_Def} -> + case St#epp.macs of + #{M:=_Def} -> skip_toks(From, St, [ifndef]); - error -> + _ -> scan_toks(From, St#epp{istk=[ifndef|St#epp.istk]}) end; scan_ifndef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfnD, From, St) -> - case dict:find({atom,M}, St#epp.macs) of - {ok,_Def} -> + case St#epp.macs of + #{M:=_Def} -> skip_toks(From, St, [ifndef]); - error -> + _ -> scan_toks(From, St#epp{istk=[ifndef|St#epp.istk]}) end; scan_ifndef(_Toks, IfnDef, From, St) -> @@ -1072,7 +1073,8 @@ scan_file([{'(',_Llp},{string,_Ls,Name},{',',_Lc},{integer,_Li,Ln},{')',_Lrp}, {dot,_Ld}], Tf, From, St) -> Anno = erl_anno:new(Ln), enter_file_reply(From, Name, Anno, loc(Tf), generated), - Ms = dict:store({atom,'FILE'}, {none,[{string,line1(),Name}]}, St#epp.macs), + Ms0 = St#epp.macs, + Ms = Ms0#{'FILE':={none,[{string,line1(),Name}]}}, Locf = loc(Tf), NewLoc = new_location(Ln, St#epp.location, Locf), Delta = get_line(element(2, Tf))-Ln + St#epp.delta, @@ -1161,38 +1163,41 @@ macro_expansion([], Anno0) -> throw({error,loc(Anno0),premature_end}). %% gets the same location as the macro call. expand_macros(MacT, M, Toks, Ms0) -> - {Ms, U} = Ms0, + {Ms,U} = Ms0, Lm = loc(MacT), Tinfo = element(2, MacT), case expand_macro1(Lm, M, Toks, Ms) of {ok,{none,Exp}} -> - check_uses([{{atom,M}, none}], [], U, Lm), - Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], dict:new()), Ms0), + check_uses([{M,none}], [], U, Lm), + Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], #{}), Ms0), expand_macros(Toks1++Toks, Ms0); {ok,{As,Exp}} -> - check_uses([{{atom,M}, length(As)}], [], U, Lm), - {Bs,Toks1} = bind_args(Toks, Lm, M, As, dict:new()), + check_uses([{M,length(As)}], [], U, Lm), + {Bs,Toks1} = bind_args(Toks, Lm, M, As, #{}), expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0) end. expand_macro1(Lm, M, Toks, Ms) -> Arity = count_args(Toks, Lm, M), - case dict:find({atom,M}, Ms) of - error -> %% macro not found - throw({error,Lm,{undefined,M,Arity}}); - {ok, undefined} -> %% Predefined macro without definition + case Ms of + #{M:=undefined} -> + %% Predefined macro without definition. throw({error,Lm,{undefined,M,Arity}}); - {ok, [{none, Def}]} -> - {ok, Def}; - {ok, Defs} when is_list(Defs) -> - case proplists:get_value(Arity, Defs) of + #{M:=[{none,Def}]} -> + {ok,Def}; + #{M:=Defs} when is_list(Defs) -> + case proplists:get_value(Arity, Defs) of undefined -> throw({error,Lm,{mismatch,M}}); Def -> - {ok, Def} + {ok,Def} end; - {ok, PreDef} -> %% Predefined macro - {ok, PreDef} + #{M:=PreDef} -> + %% Predefined macro. + {ok,PreDef}; + _ -> + %% Macro not found. + throw({error,Lm,{undefined,M,Arity}}) end. check_uses([], _Anc, _U, _Lm) -> @@ -1200,7 +1205,7 @@ check_uses([], _Anc, _U, _Lm) -> check_uses([M|Rest], Anc, U, Lm) -> case lists:member(M, Anc) of true -> - {{_, Name},Arity} = M, + {Name,Arity} = M, throw({error,Lm,{circular,Name,Arity}}); false -> L = get_macro_uses(M, U), @@ -1209,11 +1214,11 @@ check_uses([M|Rest], Anc, U, Lm) -> end. get_macro_uses({M,Arity}, U) -> - case dict:find(M, U) of - error -> - []; - {ok, L} -> - proplists:get_value(Arity, L, proplists:get_value(none, L, [])) + case U of + #{M:=L} -> + proplists:get_value(Arity, L, proplists:get_value(none, L, [])); + _ -> + [] end. %% Macro expansion @@ -1264,7 +1269,7 @@ macro_args(_Toks, Lm, M, _As, _Bs) -> store_arg(L, M, _A, [], _Bs) -> throw({error,L,{mismatch,M}}); store_arg(_L, _M, A, Arg, Bs) -> - dict:store(A, Arg, Bs). + Bs#{A=>Arg}. %% count_args(Tokens, MacroLine, MacroName) %% Count the number of arguments in a macro call. @@ -1337,19 +1342,17 @@ macro_arg([], _E, Arg) -> %% and then the macro arguments, i.e. simulate textual expansion. expand_macro([{var,_Lv,V}|Ts], L, Rest, Bs) -> - case dict:find(V, Bs) of - {ok,Val} -> - %% lists:append(Val, expand_macro(Ts, L, Rest, Bs)); + case Bs of + #{V:=Val} -> expand_arg(Val, Ts, L, Rest, Bs); - error -> + _ -> [{var,L,V}|expand_macro(Ts, L, Rest, Bs)] end; expand_macro([{'?', _}, {'?', _}, {var,_Lv,V}|Ts], L, Rest, Bs) -> - case dict:find(V, Bs) of - {ok,Val} -> - %% lists:append(Val, expand_macro(Ts, L, Rest, Bs)); + case Bs of + #{V:=Val} -> expand_arg(stringify(Val, L), Ts, L, Rest, Bs); - error -> + _ -> [{var,L,V}|expand_macro(Ts, L, Rest, Bs)] end; expand_macro([T|Ts], L, Rest, Bs) -> -- cgit v1.2.3 From 5de2c218a397d4243cdb0ec08cf300b2c12bf1aa Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 14 Oct 2015 13:56:12 +0200 Subject: [eunit] Correct documentation Fix mistakes found by 'xmllint'. --- lib/eunit/doc/overview.edoc | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc index 2789a05792..12ea02f442 100644 --- a/lib/eunit/doc/overview.edoc +++ b/lib/eunit/doc/overview.edoc @@ -907,7 +907,6 @@ the test set is finished, regardless of the outcome (success, failures, timeouts, etc.). To make the descriptions simpler, we first list some definitions: -
@@ -928,7 +927,6 @@ To make the descriptions simpler, we first list some definitions:
`Setup'`() -> (R::any())'`Where'`local | spawn | {spawn, Node::atom()}'
-
(these are explained in more detail further below.) The following representations specify fixture handling for test sets: -- cgit v1.2.3 From 7e6fc9adad9ceeda10b10f7b140702f097e5e6e4 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:02:27 +0200 Subject: [snmp] Correct documentation Fix mistakes found by 'xmllint'. --- lib/snmp/doc/src/snmp_agent_netif.xml | 3 +- lib/snmp/doc/src/snmp_app.xml | 276 +++++++++++++++---------------- lib/snmp/doc/src/snmp_config.xml | 280 ++++++++++++++++---------------- lib/snmp/doc/src/snmp_manager_netif.xml | 3 +- lib/snmp/doc/src/snmpa.xml | 4 +- lib/snmp/doc/src/snmpm.xml | 8 +- 6 files changed, 288 insertions(+), 286 deletions(-) (limited to 'lib') diff --git a/lib/snmp/doc/src/snmp_agent_netif.xml b/lib/snmp/doc/src/snmp_agent_netif.xml index 769fd23115..9583f1f521 100644 --- a/lib/snmp/doc/src/snmp_agent_netif.xml +++ b/lib/snmp/doc/src/snmp_agent_netif.xml @@ -76,8 +76,7 @@ {Domain, Addr} tuple where Domain is transportDomainUdpIpv4 or transportDomainUdpIpv4, and Addr is an - {IpAddr, - IpPort} tuple.

+ {IpAddr,IpPort} tuple.

diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml index 234a076eda..39aac8e7d7 100644 --- a/lib/snmp/doc/src/snmp_app.xml +++ b/lib/snmp/doc/src/snmp_app.xml @@ -135,16 +135,16 @@

Agent specific config options and types:

- - ]]> + + ]]>

If master, one master agent is started. Otherwise, no agents are started.

Default is master.

- - ]]> + + ]]>

agent_discovery_opt() = {terminating, agent_terminating_discovery_opts()} | @@ -156,8 +156,8 @@

For defaults see the options in agent_discovery_opt().

- - ]]> + + ]]>

agent_terminating_discovery_opt() = {enable, boolean()} | @@ -174,8 +174,8 @@ - - ]]> + + ]]>

agent_originating_discovery_opt() = {enable, boolean()}

@@ -188,38 +188,39 @@
- - ]]> + + ]]>

If true, the agent is multi-threaded, with one thread for each get request.

Default is false.

- - ]]> + + ]]>

Defines where the SNMP agent internal db files are stored.

- - ]]> + + + ]]>

Defines the maximum number of varbinds allowed in a Get-BULK response.

Default is 1000.

- - ]]> + + ]]>

local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}

Defines options specific for the SNMP agent local database.

For defaults see the options in local_db_opt().

- - ]]> + + ]]>

When starting snmpa_local_db it always tries to open an existing database. If false, and some errors occur, a new @@ -229,16 +230,16 @@

Default is true.

- - ]]> + + ]]>

The auto save interval. The table is flushed to disk whenever not accessed for this amount of time.

Default is 5000.

- - ]]> + + ]]>

agent_net_if_opt() = {module, agent_net_if_module()} | {verbosity, verbosity()} | {options, agent_net_if_options()}

Defines options specific for the SNMP agent network interface @@ -246,8 +247,8 @@

For defaults see the options in agent_net_if_opt().

- - ]]> + + ]]>

Module which handles the network interface part for the SNMP agent. Must implement the @@ -255,8 +256,8 @@

Default is snmpa_net_if.

- - ]]> + + ]]>

agent_net_if_option() = {bind_to, bind_to()} | {sndbuf, sndbuf()} | @@ -270,15 +271,15 @@

For defaults see the options in agent_net_if_option().

- - ]]> + + ]]>

Max number of simultaneous requests handled by the agent.

Default is infinity.

- - ]]> + + ]]>

agent_net_if_filter_option() = {module, agent_net_if_filter_module()}

These options are actually specific to the used module. @@ -288,8 +289,8 @@ agent_net_if_filter_option().

- - ]]> + + ]]>

Module which handles the network interface filter part for the SNMP agent. Must implement the @@ -297,8 +298,8 @@

Default is snmpa_net_if_filter.

- - ]]> + + ]]>

Specifies a list of MIBs (including path) that defines which MIBs are initially loaded into the SNMP master agent.

@@ -312,8 +313,8 @@

Default is [].

- - ]]> + + ]]>

mib_storage_opt() = {module, mib_storage_module()} | {options, mib_storage_options()}

This option specifies how basic mib data is stored. @@ -322,8 +323,8 @@

Default is [{module, snmpa_mib_storage_ets}].

- - + +

Defines the mib storage module of the SNMP agent as defined by the snmpa_mib_storage @@ -337,8 +338,8 @@

Default module is snmpa_mib_storage_ets.

- - ]]> + + ]]>

This is implementattion depended. That is, it depends on the module. For each module a specific set of options are valid. @@ -427,16 +428,16 @@ - - ]]> + + ]]>

mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()} | {data_module, mib_server_data_module()}

Defines options specific for the SNMP agent mib server.

For defaults see the options in mib_server_opt().

- - ]]> + + ]]>

If this value is false, then when loading a mib each mib- entry is checked prior to installation of the mib. @@ -445,8 +446,8 @@

Default is false.

- - ]]> + + ]]>

If this value is false, then when loading a mib each trap is checked prior to installation of the mib. @@ -455,11 +456,12 @@

Default is false.

- - ]]> + + ]]>

Defines the backend data module of the SNMP agent mib-server as defined by the @@ -476,24 +478,24 @@

Default module is snmpa_mib_data_tttn.

- - ]]> + + ]]>

Shall the agent utilize the mib server lookup cache or not.

Default is true (in which case the mibs_cache_opts() default values apply).

- - ]]> + + ]]>

mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}

Defines options specific for the SNMP agent mib server cache.

For defaults see the options in mibs_cache_opt().

- - ]]> + + ]]>

Defines if the mib server shall perform cache gc automatically or leave it to the user (see @@ -501,8 +503,8 @@

Default is true.

- - 0 ]]> + + 0 ]]>

Defines how old the entries in the cache will be allowed to become before they are GC'ed (assuming GC is performed). @@ -511,8 +513,8 @@

Default is 10 timutes.

- - 0 | infinity ]]> + + 0 | infinity ]]>

When performing a GC, this is the max number of cache entries that will be deleted from the cache.

@@ -522,8 +524,8 @@

Default is 100.

- - ]]> + + ]]>

Defines an error report module, implementing the snmpa_error_report @@ -532,38 +534,38 @@

Default is snmpa_error_logger.

- - symbolic_store() = [symbolic_store_opt()] + + symbolic_store() = [symbolic_store_opt()]

symbolic_store_opt() = {verbosity, verbosity()}

Defines options specific for the SNMP agent symbolic store.

For defaults see the options in symbolic_store_opt().

- - target_cache() = [target_cache_opt()] + + target_cache() = [target_cache_opt()]

target_cache_opt() = {verbosity, verbosity()}

Defines options specific for the SNMP agent target cache.

For defaults see the options in target_cache_opt().

- - ]]> + + ]]>

agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}

Defines specific config related options for the SNMP agent.

For defaults see the options in agent_config_opt().

- - ]]> + + ]]>

Defines where the SNMP agent configuration files are stored.

- - ]]> + + ]]>

If true the configuration files are re-read during start-up, and the contents of the configuration @@ -577,16 +579,16 @@

Manager specific config options and types:

- - ]]> + + ]]>

server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}

Specifies the options for the manager server process.

Default is silence.

- - ]]> + + ]]>

Asynchronous request cleanup time. For every requests, some info is stored internally, in order to be able to @@ -606,44 +608,44 @@

Default is 30000.

- - ]]> + + ]]>

manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}

Defines specific config related options for the SNMP manager.

For defaults see the options in manager_config_opt().

- - ]]> + + ]]>

Defines where the SNMP manager configuration files are stored.

- - ]]> + + ]]>

Defines where the SNMP manager store persistent data.

- - ]]> + + ]]>

Defines the repair option for the persistent database (if and how the table is repaired when opened).

Default is true.

- - ]]> + + ]]>

The auto save interval. The table is flushed to disk whenever not accessed for this amount of time.

Default is 5000.

- - ]]> + + ]]>

This option defines how the manager will handle the sending of response (acknowledgment) to received inform-requests.

@@ -672,16 +674,16 @@

Default is auto.

- - ]]> + + ]]>

Specifies a list of MIBs (including path) and defines which MIBs are initially loaded into the SNMP manager.

Default is [].

- - ]]> + + ]]>

manager_net_if_opt() = {module, manager_net_if_module()} | {verbosity, verbosity()} | @@ -691,8 +693,8 @@

For defaults see the options in manager_net_if_opt().

- - ]]> + + ]]>

manager_net_if_option() = {bind_to, bind_to()} | {sndbuf, sndbuf()} | @@ -705,8 +707,8 @@

For defaults see the options in manager_net_if_option().

- - ]]> + + ]]>

The module which handles the network interface part for the SNMP manager. It must implement the @@ -714,8 +716,8 @@

Default is snmpm_net_if.

- - ]]> + + ]]>

manager_net_if_filter_option() = {module, manager_net_if_filter_module()}

These options are actually specific to the used module. @@ -725,8 +727,8 @@ manager_net_if_filter_option().

- - ]]> + + ]]>

Module which handles the network interface filter part for the SNMP manager. Must implement the @@ -734,16 +736,16 @@

Default is snmpm_net_if_filter.

- - ]]> + + ]]>

The module implementing the default user. See the snmpm_user behaviour.

Default is snmpm_user_default.

- - ]]> + + ]]>

Data for the default user. Passed to the user module when calling the callback functions.

@@ -754,8 +756,8 @@

Common config types:

- - restart_type() = permanent | transient | temporary + + restart_type() = permanent | transient | temporary

See supervisor documentation for more info.

@@ -763,8 +765,8 @@ for the manager.

- - db_init_error() = terminate | create | create_db_and_dir + + db_init_error() = terminate | create | create_db_and_dir

Defines what to do if the agent or manager is unable to open an existing database file. terminate means that the @@ -776,31 +778,31 @@

Default is terminate.

- - ]]> + + ]]>

Defines the Erlang priority for all SNMP processes.

Default is normal.

- - ]]> + + ]]>

version() = v1 | v2 | v3

Which SNMP versions shall be accepted/used.

Default is [v1,v2,v3].

- - ]]> + + ]]>

Verbosity for a SNMP process. This specifies now much debug info is printed.

Default is silence.

- - ]]> + + ]]>

If true, net_if binds to the IP address. If false, net_if listens on any IP address on the host @@ -808,8 +810,8 @@

Default is false.

- - ]]> + + ]]>

If true, net_if does not specify that the IP and port address should be reusable. If false, @@ -817,30 +819,30 @@

Default is false.

- - ]]> + + ]]>

Receive buffer size.

Default value is defined by gen_udp.

- - ]]> + + ]]>

Send buffer size.

Default value is defined by gen_udp.

- - ]]> + + ]]>

note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}

Specifies the start-up verbosity for the SNMP note store.

For defaults see the options in note_store_opt().

- - ]]> + + ]]>

Note cleanup time. When storing a note in the note store, each note is given lifetime. Every timeout the note_store @@ -850,8 +852,8 @@ - - ]]> + + ]]>

audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}

If present, this option specifies the options for the @@ -861,8 +863,8 @@

If not present, audit trail logging is not used.

- - ]]> + + ]]>

Specifies what type of an audit trail log should be used. The effect of the type is actually different for the the agent @@ -883,16 +885,16 @@

Default is read_write.

- - ]]> + + ]]>

Specifies where the audit trail log should be stored.

If audit_trail_log specifies that logging should take place, this parameter must be defined.

- - ]]> + + ]]>

Specifies the size of the audit trail log. This parameter is sent to disk_log.

@@ -900,8 +902,8 @@ take place, this parameter must be defined.

- - ]]> + + ]]>

Specifies if and how the audit trail log shall be repaired when opened. Unless this parameter has the value snmp_repair @@ -913,8 +915,8 @@

Default is true.

- - ]]> + + ]]>

Specifies if the audit trail log entries will be (sequence) numbered or not. The range of the sequence numbers are according diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index f10574a2a9..a085252d90 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -130,16 +130,16 @@

Agent specific config options and types:

- - ]]> + + ]]>

If master, one master agent is started. Otherwise, no agents are started.

Default is master.

- - ]]> + + ]]>

agent_discovery_opt() = {terminating, agent_terminating_discovery_opts()} | @@ -151,8 +151,8 @@

For defaults see the options in agent_discovery_opt().

- - ]]> + + ]]>

agent_terminating_discovery_opt() = {enable, boolean()} | @@ -169,8 +169,8 @@ - - ]]> + + ]]>

agent_originating_discovery_opt() = {enable, boolean()}

@@ -183,38 +183,38 @@
- - ]]> + + ]]>

If true, the agent is multi-threaded, with one thread for each get request.

Default is false.

- - ]]> + + ]]>

Defines where the SNMP agent internal db files are stored.

- - ]]> + + ]]>

Defines the maximum number of varbinds allowed in a Get-BULK response.

Default is 1000.

- - ]]> + + ]]>

local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}

Defines options specific for the SNMP agent local database.

For defaults see the options in local_db_opt().

- - ]]> + + ]]>

When starting snmpa_local_db it always tries to open an existing database. If false, and some errors occur, a new @@ -224,16 +224,16 @@

Default is true.

- - ]]> + + ]]>

The auto save interval. The table is flushed to disk whenever not accessed for this amount of time.

Default is 5000.

- - ]]> + + ]]>

agent_net_if_option() = {module, agent_net_if_module()} | {verbosity, verbosity()} | @@ -243,8 +243,8 @@

For defaults see the options in agent_net_if_opt().

- - ]]> + + ]]>

Module which handles the network interface part for the SNMP agent. Must implement the @@ -252,8 +252,8 @@

Default is snmpa_net_if.

- - ]]> + + ]]>

agent_net_if_option() = {bind_to, bind_to()} | {sndbuf, sndbuf()} | @@ -267,15 +267,15 @@

For defaults see the options in agent_net_if_option().

- - ]]> + + ]]>

Max number of simultaneous requests handled by the agent.

Default is infinity.

- - ]]> + + ]]>

These options are actually specific to the used module. @@ -284,8 +284,8 @@

For defaults see the options in agent_net_if_filter_option().

- - ]]> + + ]]>

Module which handles the network interface filter part for the SNMP agent. Must implement the @@ -294,8 +294,8 @@

Default is snmpa_net_if_filter.

- - ]]> + + ]]>

Specifies a list of MIBs (including path) that defines which MIBs are initially loaded into the SNMP master agent.

@@ -309,8 +309,8 @@

Default is [].

- - ]]> + + ]]>

mib_storage_opt() = {module, mib_storage_module()} | {options, mib_storage_options()}

This option specifies how basic mib data is stored. @@ -319,8 +319,8 @@

Default is [{module, snmpa_mib_storage_ets}].

- - + +

Defines the mib storage module of the SNMP agent as defined by the snmpa_mib_storage @@ -334,8 +334,8 @@

Default module is snmpa_mib_storage_ets.

- - ]]> + + ]]>

This is implementattion depended. That is, it depends on the module. For each module a specific set of options are valid. @@ -429,8 +429,8 @@ This is the old format which is "supported", but not documented, in so far as it will be converted to the new format if found. - - ]]> + + ]]>

Specifies how info retrieved from the mibs will be stored.

If mib_storage is {ets, Dir}, the table will also be @@ -456,16 +456,16 @@ in so far as it will be converted to the new format if found. --> - - ]]> + + ]]>

mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()} | {data_module, mib_server_data_module()}

Defines options specific for the SNMP agent mib server.

For defaults see the options in mib_server_opt().

- - ]]> + + ]]>

If this value is false, then when loading a mib each mib- entry is checked prior to installation of the mib. @@ -474,8 +474,8 @@ in so far as it will be converted to the new format if found.

Default is false.

- - ]]> + + ]]>

If this value is false, then when loading a mib each trap is checked prior to installation of the mib. @@ -484,11 +484,13 @@ in so far as it will be converted to the new format if found.

Default is false.

- + - ]]> + + ]]>

Defines the backend data module of the SNMP agent mib-server as defined by the @@ -505,24 +507,24 @@ in so far as it will be converted to the new format if found.

Default module is snmpa_mib_data_tttn.

- - ]]> + + ]]>

Shall the agent utilize the mib server lookup cache or not.

Default is true (in which case the mibs_cache_opts() default values apply).

- - ]]> + + ]]>

mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}

Defines options specific for the SNMP agent mib server cache.

For defaults see the options in mibs_cache_opt().

- - ]]> + + ]]>

Defines if the mib server shall perform cache gc automatically or leave it to the user (see @@ -530,8 +532,8 @@ in so far as it will be converted to the new format if found.

Default is true.

- - 0 ]]> + + 0 ]]>

Defines how old the entries in the cache will be allowed to become before they are GC'ed (assuming GC is performed). @@ -540,8 +542,8 @@ in so far as it will be converted to the new format if found.

Default is 10 timutes.

- - 0 | infinity ]]> + + 0 | infinity ]]>

When performing a GC, this is the max number of cache entries that will be deleted from the cache.

@@ -551,8 +553,8 @@ in so far as it will be converted to the new format if found.

Default is 100.

- - ]]> + + ]]>

Defines an error report module, implementing the snmpa_error_report @@ -561,38 +563,38 @@ in so far as it will be converted to the new format if found.

Default is snmpa_error_logger.

- - symbolic_store() = [symbolic_store_opt()] + + symbolic_store() = [symbolic_store_opt()]

symbolic_store_opt() = {verbosity, verbosity()}

Defines options specific for the SNMP agent symbolic store.

For defaults see the options in symbolic_store_opt().

- - target_cache() = [target_cache_opt()] + + target_cache() = [target_cache_opt()]

target_cache_opt() = {verbosity, verbosity()}

Defines options specific for the SNMP agent target cache.

For defaults see the options in target_cache_opt().

- - ]]> + + ]]>

agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}

Defines specific config related options for the SNMP agent.

For defaults see the options in agent_config_opt().

- - ]]> + + ]]>

Defines where the SNMP agent configuration files are stored.

- - ]]> + + ]]>

If true the configuration files are re-read during start-up, and the contents of the configuration @@ -606,16 +608,16 @@ in so far as it will be converted to the new format if found.

Manager specific config options and types:

- - ]]> + + ]]>

server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}

Specifies the options for the manager server process.

Default is silence.

- - ]]> + + ]]>

Asynchronous request cleanup time. For every requests, some info is stored internally, in order to be able to @@ -635,44 +637,44 @@ in so far as it will be converted to the new format if found.

Default is 30000.

- - ]]> + + ]]>

manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}

Defines specific config related options for the SNMP manager.

For defaults see the options in manager_config_opt().

- - ]]> + + ]]>

Defines where the SNMP manager configuration files are stored.

- - ]]> + + ]]>

Defines where the SNMP manager store persistent data.

- - ]]> + + ]]>

Defines the repair option for the persistent database (if and how the table is repaired when opened).

Default is true.

- - ]]> + + ]]>

The auto save interval. The table is flushed to disk whenever not accessed for this amount of time.

Default is 5000.

- - ]]> + + ]]>

This option defines how the manager will handle the sending of response (acknowledgment) to received inform-requests.

@@ -701,16 +703,16 @@ in so far as it will be converted to the new format if found.

Default is auto.

- - ]]> + + ]]>

Specifies a list of MIBs (including path) and defines which MIBs are initially loaded into the SNMP manager.

Default is [].

- - ]]> + + ]]>

manager_net_if_opt() = {module, manager_net_if_module()} | {verbosity, verbosity()} | @@ -720,8 +722,8 @@ in so far as it will be converted to the new format if found.

For defaults see the options in manager_net_if_opt().

- - ]]> + + ]]>

manager_net_if_option() = {bind_to, bind_to()} | {sndbuf, sndbuf()} | @@ -734,8 +736,8 @@ in so far as it will be converted to the new format if found.

For defaults see the options in manager_net_if_option().

- - ]]> + + ]]>

The module which handles the network interface part for the SNMP manager. It must implement the @@ -743,8 +745,8 @@ in so far as it will be converted to the new format if found.

Default is snmpm_net_if.

- - ]]> + + ]]>

manager_net_if_filter_option() = {module, manager_net_if_filter_module()}

These options are actually specific to the used module. @@ -754,8 +756,8 @@ in so far as it will be converted to the new format if found. manager_net_if_filter_option().

- - ]]> + + ]]>

Module which handles the network interface filter part for the SNMP manager. Must implement the @@ -763,16 +765,16 @@ in so far as it will be converted to the new format if found.

Default is snmpm_net_if_filter.

- - ]]> + + ]]>

The module implementing the default user. See the snmpm_user behaviour.

Default is snmpm_user_default.

- - ]]> + + ]]>

Data for the default user. Passed to the user when calling the callback functions.

@@ -783,8 +785,8 @@ in so far as it will be converted to the new format if found.

Common config types:

- - restart_type() = permanent | transient | temporary + + restart_type() = permanent | transient | temporary

See supervisor documentation for more info.

@@ -792,8 +794,8 @@ in so far as it will be converted to the new format if found. for the manager.

- - db_init_error() = terminate | create | create_db_and_dir + + db_init_error() = terminate | create | create_db_and_dir

Defines what to do if the agent is unable to open an existing database file. terminate means that the @@ -805,31 +807,31 @@ in so far as it will be converted to the new format if found.

Default is terminate.

- - ]]> + + ]]>

Defines the Erlang priority for all SNMP processes.

Default is normal.

- - ]]> + + ]]>

version() = v1 | v2 | v3

Which SNMP versions shall be accepted/used.

Default is [v1,v2,v3].

- - ]]> + + ]]>

Verbosity for a SNMP process. This specifies now much debug info is printed.

Default is silence.

- - ]]> + + ]]>

If true, net_if binds to the IP address. If false, net_if listens on any IP address on the host @@ -837,8 +839,8 @@ in so far as it will be converted to the new format if found.

Default is false.

- - ]]> + + ]]>

If true, net_if does not specify that the IP and port address should be reusable. If false, @@ -846,30 +848,30 @@ in so far as it will be converted to the new format if found.

Default is false.

- - ]]> + + ]]>

Receive buffer size.

Default value is defined by gen_udp.

- - ]]> + + ]]>

Send buffer size.

Default value is defined by gen_udp.

- - ]]> + + ]]>

note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}

Specifies the options for the SNMP note store.

For defaults see the options in note_store_opt().

- - ]]> + + ]]>

Note cleanup time. When storing a note in the note store, each note is given lifetime. Every timeout the note_store @@ -878,8 +880,8 @@ in so far as it will be converted to the new format if found.

Default is 30000.

- - ]]> + + ]]>

audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}

If present, this option specifies the options for the @@ -889,8 +891,8 @@ in so far as it will be converted to the new format if found.

If not present, audit trail logging is not used.

- - ]]> + + ]]>

Specifies what type of an audit trail log should be used. The effect of the type is actually different for the the agent @@ -911,16 +913,16 @@ in so far as it will be converted to the new format if found.

Default is read_write.

- - ]]> + + ]]>

Specifies where the audit trail log should be stored.

If audit_trail_log specifies that logging should take place, this parameter must be defined.

- - ]]> + + ]]>

Specifies the size of the audit trail log. This parameter is sent to disk_log.

@@ -928,8 +930,8 @@ in so far as it will be converted to the new format if found. take place, this parameter must be defined.

- - ]]> + + ]]>

Specifies if and how the audit trail log shall be repaired when opened. Unless this parameter has the value snmp_repair @@ -941,8 +943,8 @@ in so far as it will be converted to the new format if found.

Default is true.

- - ]]> + + ]]>

Specifies if the audit trail log entries will be (sequence) numbered or not. The range of the sequence numbers are according diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml index 8454d03b17..98d4e7fd96 100644 --- a/lib/snmp/doc/src/snmp_manager_netif.xml +++ b/lib/snmp/doc/src/snmp_manager_netif.xml @@ -75,8 +75,7 @@

In this section a Domain field is the transport domain i.e one of transportDomainUdpIpv4 or transportDomainUdpIpv6, and an Addr field is an - {IpAddr, - IpPort} tuple.

+ {IpAddr,IpPort} tuple.

Net if must send the following message when it receives an SNMP PDU from the network that is aimed for the MasterAgent: diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml index f205af6e88..c84eeec524 100644 --- a/lib/snmp/doc/src/snmpa.xml +++ b/lib/snmp/doc/src/snmpa.xml @@ -622,12 +622,12 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}

Converts an Audit Trail Log to a readable format and prints it on stdio. LogName defaults to "snmpa_log". - LogFile defaults to "snmpa.log". + LogFile defaults to "snmpa.log".

The Block option indicates if the log should be blocked during conversion. This could be usefull when converting large logs (when otherwise the log could wrap during conversion). Defaults to true.

- See snmp:log_to_io +

See snmp:log_to_io for more info.

diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml index b14c0e6afd..ab288fd020 100644 --- a/lib/snmp/doc/src/snmpm.xml +++ b/lib/snmp/doc/src/snmpm.xml @@ -1241,12 +1241,12 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1

Converts an Audit Trail Log to a readable text file. OutFile defaults to "./snmpm_log.txt". LogName defaults to "snmpm_log". - LogFile defaults to "snmpm.log". + LogFile defaults to "snmpm.log".

The Block argument indicates if the log should be blocked during conversion. This could be usefull when converting large logs (when otherwise the log could wrap during conversion). Defaults to true.

- See snmp:log_to_txt +

See snmp:log_to_txt for more info.

@@ -1280,12 +1280,12 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1

Converts an Audit Trail Log to a readable format and prints it on stdio. LogName defaults to "snmpm_log". - LogFile defaults to "snmpm.log". + LogFile defaults to "snmpm.log".

The Block argument indicates if the log should be blocked during conversion. This could be usefull when converting large logs (when otherwise the log could wrap during conversion). Defaults to true.

- See snmp:log_to_io +

See snmp:log_to_io for more info.

-- cgit v1.2.3 From f5427a21fdcaebe6144e02c1771609595fa07e7a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:02:17 +0200 Subject: [ssh] Correct documentation Fix mistakes found by 'xmllint'. --- lib/ssh/doc/src/notes.xml | 10 +++++----- lib/ssh/doc/src/using_ssh.xml | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index bb111c8e0e..012d7051eb 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -4,7 +4,7 @@
- 20042014 + 20042015 Ericsson AB. All Rights Reserved. @@ -216,9 +216,9 @@

Thanks to Simon Cornish

- Own Id: OTP-12760 Aux Id: pull req - 715

+ 715

@@ -384,13 +384,13 @@

- Made Codenomicon Defensics test suite pass: + Made Codenomicon Defensics test suite pass:

limit number of algorithms in kexinit message check 'e' and 'f' parameters in kexdh implement 'keyboard-interactive' user authentication on server side return plain text message to bad version exchange message -

+

Own Id: OTP-12784

diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml index 91185a0f6e..2d045fdb60 100644 --- a/lib/ssh/doc/src/using_ssh.xml +++ b/lib/ssh/doc/src/using_ssh.xml @@ -234,7 +234,7 @@ SFTP Client with TAR Compression and Encryption

Example of writing and then reading a tar file follows:

- + {ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]), ok = erl_tar:add(HandleWrite, .... ), ok = erl_tar:add(HandleWrite, .... ), @@ -249,7 +249,7 @@

The previous write and read example can be extended with encryption and decryption as follows:

- + %% First three parameters depending on which crypto type we select: Key = <<"This is a 256 bit key. abcdefghi">>, Ivec0 = crypto:rand_bytes(16), -- cgit v1.2.3 From 6f50633829adc53d20a2c2aee454aef8caece907 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:01:18 +0200 Subject: [compiler] Correct documentation Fix mistakes found by 'xmllint'. --- lib/compiler/doc/src/notes.xml | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index bd85f22462..daf3bd3af9 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -458,22 +458,28 @@

EEP43: New data type - Maps

- With Maps you may for instance: M0 = - #{ a => 1, b => 2}, % create - associations M1 = M0#{ a := 10 }, % - update values M2 = M1#{ "hi" => - "hello"}, % add new associations #{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values

+ With Maps you may for instance:

+ + M0 = #{ a => 1, b => 2}, % create + associations + M1 = M0#{ a := 10 }, % update values + M2 = M1#{ "hi" => + "hello"}, % add new associations + #{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values +

For information on how to use Maps please see Map Expressions in the Reference Manual.

The current implementation is without the following - features: No variable keys - No single value access No map - comprehensions

+ features:

+ + No variable keys + No single value access + No map comprehensions +

Note that Maps is experimental during OTP 17.0.

-- cgit v1.2.3 From ea4114d5d4156bae207788e5be7d0157e32adfe9 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:01:30 +0200 Subject: [crypto] Correct documentation Fix mistakes found by 'xmllint'. --- lib/crypto/doc/src/crypto.xml | 84 +++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'lib') diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 291a5145e4..8d082bf3fe 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -66,29 +66,29 @@

DATA TYPES -

key_value() = integer() | binary()

+ key_value() = integer() | binary()

Always binary() when used as return value

-

rsa_public() = [key_value()] = [E, N]

+ rsa_public() = [key_value()] = [E, N]

Where E is the public exponent and N is public modulus.

-

rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]

+ rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]

Where E is the public exponent, N is public modulus and D is the private exponent.The longer key format contains redundant information that will make the calculation faster. P1,P2 are first and second prime factors. E1,E2 are first and second exponents. C is the CRT coefficient. Terminology is taken from RFC 3447.

-

dss_public() = [key_value()] = [P, Q, G, Y]

+ dss_public() = [key_value()] = [P, Q, G, Y]

Where P, Q and G are the dss parameters and Y is the public key.

-

dss_private() = [key_value()] = [P, Q, G, X]

+ dss_private() = [key_value()] = [P, Q, G, X]

Where P, Q and G are the dss parameters and X is the private key.

-

srp_public() = key_value()

+ srp_public() = key_value()

Where is A or B from SRP design

-

srp_private() = key_value()

+ srp_private() = key_value()

Where is a or b from SRP design

Where Verifier is v, Generator is g and Prime is N, DerivedKey is X, and Scrambler is @@ -96,29 +96,29 @@ Version = '3' | '6' | '6a'

-

dh_public() = key_value()

+ dh_public() = key_value() -

dh_private() = key_value()

+ dh_private() = key_value() -

dh_params() = [key_value()] = [P, G]

+ dh_params() = [key_value()] = [P, G] -

ecdh_public() = key_value()

+ ecdh_public() = key_value() -

ecdh_private() = key_value()

+ ecdh_private() = key_value() -

ecdh_params() = ec_named_curve() | ec_explicit_curve()

+ ecdh_params() = ec_named_curve() | ec_explicit_curve() -

ec_explicit_curve() = - {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(), CoFactor :: none | integer()}

+ ec_explicit_curve() = + {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(), CoFactor :: none | integer()} -

ec_field() = {prime_field, Prime :: integer()} | - {characteristic_two_field, M :: integer(), Basis :: ec_basis()}

+ ec_field() = {prime_field, Prime :: integer()} | + {characteristic_two_field, M :: integer(), Basis :: ec_basis()} -

ec_basis() = {tpbasis, K :: non_neg_integer()} | + ec_basis() = {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | - onbasis

+ onbasis -

ec_named_curve() -> + ec_named_curve() -> sect571r1| sect571k1| sect409r1| sect409k1| secp521r1| secp384r1| secp224r1| secp224k1| secp192k1| secp160r2| secp128r2| secp128r1| sect233r1| sect233k1| sect193r2| sect193r1| sect131r2| sect131r1| sect283r1| sect283k1| sect163r2| secp256k1| secp160k1| secp160r1| @@ -128,42 +128,42 @@ brainpoolP224t1| brainpoolP256r1| brainpoolP256t1| brainpoolP320r1| brainpoolP320t1| brainpoolP384r1| brainpoolP384t1| brainpoolP512r1| brainpoolP512t1 - Note that the sect curves are GF2m (characteristic two) curves and are only supported if the +

Note that the sect curves are GF2m (characteristic two) curves and are only supported if the underlying OpenSSL has support for them. See also crypto:supports/0

-

stream_cipher() = rc4 | aes_ctr

+ stream_cipher() = rc4 | aes_ctr -

block_cipher() = aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc | + block_cipher() = aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc | blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf - | des_ede3 | rc2_cbc

+ | des_ede3 | rc2_cbc -

aead_cipher() = aes_gcm | chacha20_poly1305

+ aead_cipher() = aes_gcm | chacha20_poly1305 -

stream_key() = aes_key() | rc4_key()

+ stream_key() = aes_key() | rc4_key() -

block_key() = aes_key() | blowfish_key() | des_key()| des3_key()

+ block_key() = aes_key() | blowfish_key() | des_key()| des3_key() -

aes_key() = iodata() Key length is 128, 192 or 256 bits

+ aes_key() = iodata()

Key length is 128, 192 or 256 bits

-

rc4_key() = iodata() Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)

+ rc4_key() = iodata()

Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)

-

blowfish_key() = iodata() Variable key length from 32 bits up to 448 bits

+ blowfish_key() = iodata()

Variable key length from 32 bits up to 448 bits

-

des_key() = iodata() Key length is 64 bits (in CBC mode only 8 bits are used)

+ des_key() = iodata()

Key length is 64 bits (in CBC mode only 8 bits are used)

-

des3_key() = [binary(), binary(), binary()] Each key part is 64 bits (in CBC mode only 8 bits are used)

+ des3_key() = [binary(), binary(), binary()]

Each key part is 64 bits (in CBC mode only 8 bits are used)

-

digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512

+ digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512 -

hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 md4 is also supported for hash_init/1 and hash/2. + hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512

md4 is also supported for hash_init/1 and hash/2. Note that both md4 and md5 are recommended only for compatibility with existing applications.

-

cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | - blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128| aes_cbc256 | aes_ige256 | aes_gcm | chacha20_poly1305 | rc2_cbc | aes_ctr| rc4

-

public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m - Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported + cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | + blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128| aes_cbc256 | aes_ige256 | aes_gcm | chacha20_poly1305 | rc2_cbc | aes_ctr| rc4 + public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m +

Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported with ecdsa and ecdh.

@@ -381,8 +381,8 @@

Computes a HMAC of type Type from Data using - Key as the authentication key.

MacLength - will limit the size of the resultant Mac. + Key as the authentication key.

MacLength + will limit the size of the resultant Mac.

@@ -650,7 +650,7 @@

Creates a digital signature.

Algorithm dss can only be used together with digest type sha.

- See also public_key:sign/3 +

See also public_key:sign/3.

@@ -802,7 +802,7 @@

Algorithm dss can only be used together with digest type sha.

- See also public_key:verify/4 +

See also public_key:verify/4.

-- cgit v1.2.3 From 1391715d8bbba315e1509e60e6245159a009bd9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 25 Sep 2015 17:03:02 +0200 Subject: Use copy literal range check in message passing and purging --- lib/kernel/src/code_server.erl | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index e461c95d19..68dd21b1d7 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1428,16 +1428,18 @@ absname_vr([[X, $:]|Name], _, _AbsBase) -> do_purge(Mod0) -> Mod = to_atom(Mod0), case erlang:check_old_code(Mod) of - false -> - false; - true -> - Res = check_proc_code(erlang:processes(), Mod, true), - try - erlang:purge_module(Mod) - catch - _:_ -> ignore - end, - Res + false -> + false; + true -> + true = erlang:copy_literals(Mod, true), + Res = check_proc_code(erlang:processes(), Mod, true), + true = erlang:copy_literals(Mod, false), + try + erlang:purge_module(Mod) + catch + _:_ -> ignore + end, + Res end. %% do_soft_purge(Module) @@ -1451,10 +1453,13 @@ do_soft_purge(Mod0) -> false -> true; true -> + true = erlang:copy_literals(Mod, true), case check_proc_code(erlang:processes(), Mod, false) of false -> + true = erlang:copy_literals(Mod, false), false; true -> + true = erlang:copy_literals(Mod, false), try erlang:purge_module(Mod) catch -- cgit v1.2.3 From 71390889787b571aa3f13e683d9e2349415f5808 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 13 Nov 2015 15:07:26 +0100 Subject: ssl: Client should send the hello message in the lowest version it is willing to support Refactor highest_protocol_version so that code is symmetrical with lowest_protocol_version. For clarity and possible future use cases of highest_protocol_version/2 --- lib/ssl/src/tls_connection.erl | 3 +- lib/ssl/src/tls_record.erl | 62 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 3093508f61..a468c131ce 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -168,9 +168,10 @@ hello(start, #state{host = Host, port = Port, role = client, Cache, CacheCb, Renegotiation, Cert), Version = Hello#client_hello.client_version, + HelloVersion = tls_record:lowest_protocol_version(SslOpts#ssl_options.versions), Handshake0 = ssl_handshake:init_handshake_history(), {BinMsg, ConnectionStates, Handshake} = - encode_handshake(Hello, Version, ConnectionStates0, Handshake0), + encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0), Transport:send(Socket, BinMsg), State1 = State0#state{connection_states = ConnectionStates, negotiated_version = Version, %% Requested version diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl index aa524f0225..1e266ed424 100644 --- a/lib/ssl/src/tls_record.erl +++ b/lib/ssl/src/tls_record.erl @@ -41,8 +41,9 @@ -export([encode_plain_text/4]). %% Protocol version handling --export([protocol_version/1, lowest_protocol_version/2, - highest_protocol_version/1, is_higher/2, supported_protocol_versions/0, +-export([protocol_version/1, lowest_protocol_version/1, lowest_protocol_version/2, + highest_protocol_version/1, highest_protocol_version/2, + is_higher/2, supported_protocol_versions/0, is_acceptable_version/1, is_acceptable_version/2]). -export_type([tls_version/0, tls_atom_version/0]). @@ -257,6 +258,18 @@ lowest_protocol_version(Version = {M,_}, Version; lowest_protocol_version(_,Version) -> Version. + +%%-------------------------------------------------------------------- +-spec lowest_protocol_version([tls_version()]) -> tls_version(). +%% +%% Description: Lowest protocol version present in a list +%%-------------------------------------------------------------------- +lowest_protocol_version([]) -> + lowest_protocol_version(); +lowest_protocol_version(Versions) -> + [Ver | Vers] = Versions, + lowest_list_protocol_version(Ver, Vers). + %%-------------------------------------------------------------------- -spec highest_protocol_version([tls_version()]) -> tls_version(). %% @@ -266,19 +279,29 @@ highest_protocol_version([]) -> highest_protocol_version(); highest_protocol_version(Versions) -> [Ver | Vers] = Versions, - highest_protocol_version(Ver, Vers). + highest_list_protocol_version(Ver, Vers). -highest_protocol_version(Version, []) -> +%%-------------------------------------------------------------------- +-spec highest_protocol_version(tls_version(), tls_version()) -> tls_version(). +%% +%% Description: Highest protocol version of two given versions +%%-------------------------------------------------------------------- +highest_protocol_version(Version = {M, N}, {M, O}) when N > O -> + Version; +highest_protocol_version({M, _}, + Version = {M, _}) -> Version; -highest_protocol_version(Version = {N, M}, [{N, O} | Rest]) when M > O -> - highest_protocol_version(Version, Rest); -highest_protocol_version({M, _}, [Version = {M, _} | Rest]) -> - highest_protocol_version(Version, Rest); -highest_protocol_version(Version = {M,_}, [{N,_} | Rest]) when M > N -> - highest_protocol_version(Version, Rest); -highest_protocol_version(_, [Version | Rest]) -> - highest_protocol_version(Version, Rest). +highest_protocol_version(Version = {M,_}, + {N, _}) when M > N -> + Version; +highest_protocol_version(_,Version) -> + Version. +%%-------------------------------------------------------------------- +-spec is_higher(V1 :: tls_version(), V2::tls_version()) -> tls_version(). +%% +%% Description: Is V1 > V2 +%%-------------------------------------------------------------------- is_higher({M, N}, {M, O}) when N > O -> true; is_higher({M, _}, {N, _}) when M > N -> @@ -352,6 +375,17 @@ is_acceptable_version(_,_) -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- + +lowest_list_protocol_version(Ver, []) -> + Ver; +lowest_list_protocol_version(Ver1, [Ver2 | Rest]) -> + lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest). + +highest_list_protocol_version(Ver, []) -> + Ver; +highest_list_protocol_version(Ver1, [Ver2 | Rest]) -> + highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest). + encode_tls_cipher_text(Type, {MajVer, MinVer}, Fragment) -> Length = erlang:iolist_size(Fragment), [<>, Fragment]. @@ -370,6 +404,10 @@ mac_hash({3, N} = Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment) highest_protocol_version() -> highest_protocol_version(supported_protocol_versions()). +lowest_protocol_version() -> + lowest_protocol_version(supported_protocol_versions()). + + sufficient_tlsv1_2_crypto_support() -> CryptoSupport = crypto:supports(), proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)). -- cgit v1.2.3 From cd2f57bda32374dba98cbb0e72039a2e266f1633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 18 Nov 2015 10:07:08 +0100 Subject: epp: Only flatten the original filename There is no need to flatten filenames using file_name/1 every time the current filename changes. Any filename obtained from a source file will be already flattened. Only the original source filename may need flattening. --- lib/stdlib/src/epp.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 0d3f725afe..45f616bb02 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -543,7 +543,8 @@ init_server(Pid, Name, Options, St0) -> default_encoding=DefEncoding}, From = wait_request(St), Anno = erl_anno:new(AtLocation), - enter_file_reply(From, Name, Anno, AtLocation, code), + enter_file_reply(From, file_name(Name), Anno, + AtLocation, code), wait_req_scan(St); {error,E} -> epp_reply(Pid, {error,E}) @@ -678,7 +679,7 @@ enter_file_reply(From, Name, LocationAnno, AtLocation, Where) -> generated -> erl_anno:set_generated(true, Anno0) end, Rep = {ok, [{'-',Anno},{atom,Anno,file},{'(',Anno}, - {string,Anno,file_name(Name)},{',',Anno}, + {string,Anno,Name},{',',Anno}, {integer,Anno,get_line(LocationAnno)},{')',LocationAnno}, {dot,Anno}]}, epp_reply(From, Rep). -- cgit v1.2.3 From 98ebbee6fa562d6812c1f132205e122b4ff4db3d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 18 Nov 2015 17:35:59 +0100 Subject: ssh: Make it possible for more than one daemon started with option fd --- lib/ssh/src/ssh.erl | 37 +++++++++++++++++++++++++++++++++++-- lib/ssh/src/ssh_acceptor.erl | 7 ++++++- 2 files changed, 41 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 5bde184070..bb50e436a3 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -235,10 +235,27 @@ start_daemon(Host, Port, Options, Inet) -> {error, _Reason} = Error -> Error; {SocketOptions, SshOptions}-> - do_start_daemon(Host, Port,[{role, server} |SshOptions] , [Inet | SocketOptions]) + try + do_start_daemon(Host, Port,[{role, server} |SshOptions] , [Inet | SocketOptions]) + catch + throw:bad_fd -> {error,bad_fd}; + _C:_E -> {error,{cannot_start_daemon,_C,_E}} + end end. -do_start_daemon(Host, Port, Options, SocketOptions) -> +do_start_daemon(Host0, Port0, Options, SocketOptions) -> + {Host,Port} = try + case proplists:get_value(fd, SocketOptions) of + undefined -> + {Host0,Port0}; + Fd when Port0==0 -> + find_hostport(Fd); + _ -> + {Host0,Port0} + end + catch + _:_ -> throw(bad_fd) + end, Profile = proplists:get_value(profile, Options, ?DEFAULT_PROFILE), case ssh_system_sup:system_supervisor(Host, Port, Profile) of undefined -> @@ -272,6 +289,22 @@ do_start_daemon(Host, Port, Options, SocketOptions) -> end end. +find_hostport(Fd) -> + %% Using internal functions inet:open/8 and inet:close/0. + %% Don't try this at home unless you know what you are doing! + {ok,S} = inet:open(Fd, {0,0,0,0}, 0, [], tcp, inet, stream, inet_tcp), + {ok, HostPort} = inet:sockname(S), + ok = inet:close(S), + HostPort. + +%% find_port(Fd) -> +%% %% Hack.... +%% {ok,TmpSock} = gen_tcp:listen(0,[{fd,Fd}]), +%% {ok, {_,ThePort}} = inet:sockname(TmpSock), +%% gen_tcp:close(TmpSock), +%% ThePort. + + handle_options(Opts) -> try handle_option(algs_compatibility(proplists:unfold(Opts)), [], []) of {Inet, Ssh} -> diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl index c5ad1d7b6c..d94dedf1bf 100644 --- a/lib/ssh/src/ssh_acceptor.erl +++ b/lib/ssh/src/ssh_acceptor.erl @@ -56,7 +56,12 @@ acceptor_init(Parent, Port, Address, SockOpts, Opts, AcceptTimeout) -> error end. -do_socket_listen(Callback, Port, Opts) -> +do_socket_listen(Callback, Port0, Opts) -> + Port = + case proplists:get_value(fd, Opts) of + undefined -> Port0; + _ -> 0 + end, case Callback:listen(Port, Opts) of {error, nxdomain} -> Callback:listen(Port, lists:delete(inet6, Opts)); -- cgit v1.2.3 From d3feb5bc94a02008738f4b1b15ea37309e7507ed Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 19 Nov 2015 12:25:40 +0100 Subject: Fix inet:setopts/2 to take multiple raw options --- lib/kernel/src/inet.erl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index ec2c350931..9211134c75 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -690,6 +690,7 @@ connect_options(Opts, Family) -> case con_opt(Opts, BaseOpts, connect_options()) of {ok, R} -> {ok, R#connect_opts { + opts = lists:reverse(R#connect_opts.opts), ifaddr = translate_ip(R#connect_opts.ifaddr, Family) }}; Error -> Error @@ -758,6 +759,7 @@ listen_options(Opts, Family) -> case list_opt(Opts, BaseOpts, listen_options()) of {ok, R} -> {ok, R#listen_opts { + opts = lists:reverse(R#listen_opts.opts), ifaddr = translate_ip(R#listen_opts.ifaddr, Family) }}; Error -> Error @@ -816,6 +818,7 @@ udp_options(Opts, Family) -> case udp_opt(Opts, #udp_opts { }, udp_options()) of {ok, R} -> {ok, R#udp_opts { + opts = lists:reverse(R#udp_opts.opts), ifaddr = translate_ip(R#udp_opts.ifaddr, Family) }}; Error -> Error @@ -889,9 +892,12 @@ sctp_options() -> sctp_options(Opts, Mod) -> case sctp_opt(Opts, Mod, #sctp_opts{}, sctp_options()) of {ok,#sctp_opts{ifaddr=undefined}=SO} -> - {ok,SO#sctp_opts{ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}}; - {ok,_}=OK -> - OK; + {ok, + SO#sctp_opts{ + opts=lists:reverse(SO#sctp_opts.opts), + ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}}; + {ok,SO} -> + {ok,SO#sctp_opts{opts=lists:reverse(SO#sctp_opts.opts)}}; Error -> Error end. @@ -963,6 +969,8 @@ add_opt(Name, Val, Opts, As) -> case lists:member(Name, As) of true -> case prim_inet:is_sockopt_val(Name, Val) of + true when Name =:= raw -> + {ok, [{Name,Val} | Opts]}; true -> Opts1 = lists:keydelete(Name, 1, Opts), {ok, [{Name,Val} | Opts1]}; -- cgit v1.2.3 From 9c336118f80135b31d99da8acb5528f6063e6670 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 19 Nov 2015 12:26:28 +0100 Subject: Testcase for inet:setopts/2 multiple raw options --- lib/kernel/test/inet_sockopt_SUITE.erl | 82 +++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl index 9d236a8a0a..2b1abeb88f 100644 --- a/lib/kernel/test/inet_sockopt_SUITE.erl +++ b/lib/kernel/test/inet_sockopt_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -51,6 +51,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, simple/1, loop_all/1, simple_raw/1, simple_raw_getbin/1, + multiple_raw/1, multiple_raw_getbin/1, doc_examples_raw/1,doc_examples_raw_getbin/1, large_raw/1,large_raw_getbin/1,combined/1,combined_getbin/1, ipv6_v6only_udp/1, ipv6_v6only_tcp/1, ipv6_v6only_sctp/1, @@ -64,6 +65,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [simple, loop_all, simple_raw, simple_raw_getbin, + multiple_raw, multiple_raw_getbin, doc_examples_raw, doc_examples_raw_getbin, large_raw, large_raw_getbin, combined, combined_getbin, ipv6_v6only_udp, ipv6_v6only_tcp, ipv6_v6only_sctp, @@ -184,6 +186,84 @@ nintbin2int(<>) -> Int; nintbin2int(<>) -> Int; nintbin2int(<<>>) -> 0. + + +multiple_raw(suite) -> []; +multiple_raw(doc) -> "Test setopt/getopt of multiple raw options."; +multiple_raw(Config) when is_list(Config) -> + do_multiple_raw(Config,false). +multiple_raw_getbin(suite) -> []; +multiple_raw_getbin(doc) -> "Test setopt/getopt of multiple raw options, " + "with binaries in getopt."; +multiple_raw_getbin(Config) when is_list(Config) -> + do_multiple_raw(Config,true). + +do_multiple_raw(Config, Binary) -> + Port = start_helper(Config), + SolSocket = ask_helper(Port, ?C_GET_SOL_SOCKET), + SoKeepalive = ask_helper(Port, ?C_GET_SO_KEEPALIVE), + SoKeepaliveTrue = {raw,SolSocket,SoKeepalive,<<1:32/native>>}, + SoKeepaliveFalse = {raw,SolSocket,SoKeepalive,<<0:32/native>>}, + SoReuseaddr = ask_helper(Port, ?C_GET_SO_REUSEADDR), + SoReuseaddrTrue = {raw,SolSocket,SoReuseaddr,<<1:32/native>>}, + SoReuseaddrFalse = {raw,SolSocket,SoReuseaddr,<<0:32/native>>}, + {S1,S2} = + create_socketpair( + [SoReuseaddrFalse,SoKeepaliveTrue], + [SoKeepaliveFalse,SoReuseaddrTrue]), + {ok,[{reuseaddr,false},{keepalive,true}]} = + inet:getopts(S1, [reuseaddr,keepalive]), + {ok, + [{raw,SolSocket,SoReuseaddr,S1R1}, + {raw,SolSocket,SoKeepalive,S1K1}]} = + inet:getopts( + S1, + [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)}, + {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]), + true = nintbin2int(S1R1) =:= 0, + true = nintbin2int(S1K1) =/= 0, + {ok,[{keepalive,false},{reuseaddr,true}]} = + inet:getopts(S2, [keepalive,reuseaddr]), + {ok, + [{raw,SolSocket,SoKeepalive,S2K1}, + {raw,SolSocket,SoReuseaddr,S2R1}]} = + inet:getopts( + S2, + [{raw,SolSocket,SoKeepalive,binarify(4, Binary)}, + {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]), + true = nintbin2int(S2K1) =:= 0, + true = nintbin2int(S2R1) =/= 0, + %% + ok = inet:setopts( + S1, [SoReuseaddrTrue,SoKeepaliveFalse]), + ok = inet:setopts( + S2, [SoKeepaliveTrue,SoReuseaddrFalse]), + {ok, + [{raw,SolSocket,SoReuseaddr,S1R2}, + {raw,SolSocket,SoKeepalive,S1K2}]} = + inet:getopts( + S1, + [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)}, + {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]), + true = nintbin2int(S1R2) =/= 0, + true = nintbin2int(S1K2) =:= 0, + {ok, + [{raw,SolSocket,SoKeepalive,S2K2}, + {raw,SolSocket,SoReuseaddr,S2R2}]} = + inet:getopts( + S2, + [{raw,SolSocket,SoKeepalive,binarify(4, Binary)}, + {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]), + true = nintbin2int(S2K2) =/= 0, + true = nintbin2int(S2R2) =:= 0, + %% + gen_tcp:close(S1), + gen_tcp:close(S2), + stop_helper(Port), + ok. + + + doc_examples_raw(suite) -> []; doc_examples_raw(doc) -> "Test that the example code from the documentation " "works"; -- cgit v1.2.3 From e6d99a21e905f234d579bd2e64a275fc4fdd5ed9 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 19 Nov 2015 11:54:51 +0100 Subject: ssh: testcases for starting daemon with given fd --- lib/ssh/test/ssh_basic_SUITE.erl | 66 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 400edb4d2c..0a5964c560 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -36,6 +36,8 @@ cli/1, close/1, daemon_already_started/1, + daemon_opt_fd/1, + multi_daemon_opt_fd/1, double_close/1, exec/1, exec_compressed/1, @@ -85,6 +87,8 @@ all() -> {group, internal_error}, daemon_already_started, double_close, + daemon_opt_fd, + multi_daemon_opt_fd, packet_size_zero, ssh_info_print ]. @@ -704,6 +708,68 @@ double_close(Config) when is_list(Config) -> exit(CM, {shutdown, normal}), ok = ssh:close(CM). +%%-------------------------------------------------------------------- +daemon_opt_fd(Config) -> + SystemDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + + {ok,S1} = gen_tcp:listen(0,[]), + {ok,Fd1} = prim_inet:getfd(S1), + + {ok,Pid1} = ssh:daemon(0, [{system_dir, SystemDir}, + {fd,Fd1}, + {user_dir, UserDir}, + {user_passwords, [{"vego", "morot"}]}, + {failfun, fun ssh_test_lib:failfun/2}]), + + {ok,{_Host1,Port1}} = inet:sockname(S1), + {ok, C1} = ssh:connect("localhost", Port1, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user, "vego"}, + {password, "morot"}, + {user_interaction, false}]), + exit(C1, {shutdown, normal}), + ssh:stop_daemon(Pid1), + gen_tcp:close(S1). + + +%%-------------------------------------------------------------------- +multi_daemon_opt_fd(Config) -> + SystemDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + + Test = + fun() -> + {ok,S} = gen_tcp:listen(0,[]), + {ok,Fd} = prim_inet:getfd(S), + + {ok,Pid} = ssh:daemon(0, [{system_dir, SystemDir}, + {fd,Fd}, + {user_dir, UserDir}, + {user_passwords, [{"vego", "morot"}]}, + {failfun, fun ssh_test_lib:failfun/2}]), + + {ok,{_Host,Port}} = inet:sockname(S), + {ok, C} = ssh:connect("localhost", Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user, "vego"}, + {password, "morot"}, + {user_interaction, false}]), + {S,Pid,C} + end, + + Tests = [Test(),Test(),Test(),Test(),Test(),Test()], + + [begin + gen_tcp:close(S), + ssh:stop_daemon(Pid), + exit(C, {shutdown, normal}) + end || {S,Pid,C} <- Tests]. + %%-------------------------------------------------------------------- packet_size_zero(Config) -> SystemDir = ?config(data_dir, Config), -- cgit v1.2.3 From d4bb044cb5359c6d4bffe3efcb8256cf7199bdf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 19 Nov 2015 12:13:21 +0100 Subject: Fix missing filename and line number in warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the 'bin_opt_info' is given, warnings without filenames and line numbers could sometimes be produced: no_file: Warning: INFO: matching non-variables after a previous clause matching a variable will prevent delayed sub binary optimization The reason for the missing information is that #c_alias{} records lack location information. There are several ways to fix the problem. The easiest seems to be to get the location information from the code). Noticed-by: José Valim --- lib/compiler/src/sys_core_fold.erl | 6 +++--- lib/compiler/test/bs_match_SUITE.erl | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 27d023d067..65699ccda9 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -3091,12 +3091,12 @@ bsm_ensure_no_partition_2([#c_var{name=V}|Ps], N, G, Vstate, S) -> bsm_ensure_no_partition_2([_|Ps], N, G, _, S) -> bsm_ensure_no_partition_2(Ps, N-1, G, bin_argument_order, S). -bsm_ensure_no_partition_after([#c_clause{pats=Ps}|Cs], Pos) -> +bsm_ensure_no_partition_after([#c_clause{pats=Ps}=C|Cs], Pos) -> case nth(Pos, Ps) of #c_var{} -> bsm_ensure_no_partition_after(Cs, Pos); - P -> - bsm_problem(P, bin_partition) + _ -> + bsm_problem(C, bin_partition) end; bsm_ensure_no_partition_after([], _) -> ok. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 6e138b0a43..b4601b0798 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -36,7 +36,7 @@ match_string/1,zero_width/1,bad_size/1,haystack/1, cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1, no_partition/1,calling_a_binary/1,binary_in_map/1, - match_string_opt/1]). + match_string_opt/1,map_and_binary/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -62,7 +62,7 @@ groups() -> otp_7498,match_string,zero_width,bad_size,haystack, cover_beam_bool,matched_out_size,follow_fail_branch, no_partition,calling_a_binary,binary_in_map, - match_string_opt]}]. + match_string_opt,map_and_binary]}]. init_per_suite(Config) -> @@ -1225,6 +1225,24 @@ match_string_opt(Config) when is_list(Config) -> do_match_string_opt({<<1>>,{v,V}}=T) -> {x,V,T}. +%% If 'bin_opt_info' was given the warning would lack filename +%% and line number. + +map_and_binary(_Config) -> + {<<"10">>,<<"37">>,<<"am">>} = do_map_and_binary(<<"10:37am">>), + Map1 = #{time => "noon"}, + {ok,Map1} = do_map_and_binary(Map1), + Map2 = #{hour => 8, min => 42}, + {8,42,Map2} = do_map_and_binary(Map2), + ok. + +do_map_and_binary(<>) -> + {Hour, Min, Rest}; +do_map_and_binary(#{time := _} = T) -> + {ok, T}; +do_map_and_binary(#{hour := Hour, min := Min} = T) -> + {Hour, Min, T}. + check(F, R) -> R = F(). -- cgit v1.2.3 From 226e77ef7162b0fc043d99a5f68f5dcc891fb093 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 19 Nov 2015 17:16:05 +0100 Subject: ssh: refactor packet reception There was an assymetric relationship between receiving a ssh-packet (decrypting-mac-decompress) and sending one. When sending, most of the work was defined in the ssh_transport module, while at reception the ssh_connection_handler was the one knowing what to do. This commit moves the reception down to the ssh_transport module where it belongs. --- lib/ssh/src/ssh_connection_handler.erl | 129 ++++++++------------------------- lib/ssh/src/ssh_transport.erl | 94 ++++++++++++++++-------- 2 files changed, 94 insertions(+), 129 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 8448218d91..505c6eb181 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -970,57 +970,39 @@ handle_info({Protocol, Socket, Info}, hello, transport_protocol = Protocol} = State) -> event({info_line, Info}, hello, State); -handle_info({Protocol, Socket, Data}, Statename, +handle_info({Protocol, Socket, Data}, StateName, #state{socket = Socket, transport_protocol = Protocol, - ssh_params = #ssh{decrypt_block_size = BlockSize, - recv_mac_size = MacSize} = Ssh0, - decoded_data_buffer = <<>>, - encoded_data_buffer = EncData0} = State0) -> - - %% Implementations SHOULD decrypt the length after receiving the - %% first 8 (or cipher block size, whichever is larger) bytes of a - %% packet. (RFC 4253: Section 6 - Binary Packet Protocol) - case size(EncData0) + size(Data) >= erlang:max(8, BlockSize) of - true -> - {Ssh, SshPacketLen, DecData, EncData} = - - ssh_transport:decrypt_first_block(<>, Ssh0), - case SshPacketLen > ?SSH_MAX_PACKET_SIZE of - true -> - DisconnectMsg = - #ssh_msg_disconnect{code = - ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "Bad packet length " - ++ integer_to_list(SshPacketLen), - language = "en"}, - handle_disconnect(DisconnectMsg, State0); - false -> - RemainingSshPacketLen = - (SshPacketLen + ?SSH_LENGHT_INDICATOR_SIZE) - - BlockSize + MacSize, - State = State0#state{ssh_params = Ssh}, - handle_ssh_packet_data(RemainingSshPacketLen, - DecData, EncData, Statename, - State) - end; - false -> - {next_state, Statename, - next_packet(State0#state{encoded_data_buffer = - <>})} + ssh_params = Ssh0, + decoded_data_buffer = DecData0, + encoded_data_buffer = EncData0, + undecoded_packet_length = RemainingSshPacketLen0} = State0) -> + Encoded = <>, + case ssh_transport:handle_packet_part(DecData0, Encoded, RemainingSshPacketLen0, Ssh0) of + {get_more, DecBytes, EncDataRest, RemainingSshPacketLen, Ssh1} -> + {next_state, StateName, + next_packet(State0#state{encoded_data_buffer = EncDataRest, + decoded_data_buffer = DecBytes, + undecoded_packet_length = RemainingSshPacketLen, + ssh_params = Ssh1})}; + {decoded, MsgBytes, EncDataRest, Ssh1} -> + generate_event(MsgBytes, StateName, + State0#state{ssh_params = Ssh1, + %% Important to be set for + %% next_packet +%%% FIXME: the following three seem to always be set in generate_event! + decoded_data_buffer = <<>>, + undecoded_packet_length = undefined, + encoded_data_buffer = EncDataRest}, + EncDataRest); + {bad_mac, Ssh1} -> + DisconnectMsg = + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad mac", + language = ""}, + handle_disconnect(DisconnectMsg, State0#state{ssh_params=Ssh1}) end; - -handle_info({Protocol, Socket, Data}, Statename, - #state{socket = Socket, - transport_protocol = Protocol, - decoded_data_buffer = DecData, - encoded_data_buffer = EncData, - undecoded_packet_length = Len} = - State) when is_integer(Len) -> - handle_ssh_packet_data(Len, DecData, <>, - Statename, State); - + handle_info({CloseTag, _Socket}, _StateName, #state{transport_close_tag = CloseTag, ssh_params = #ssh{role = _Role, opts = _Opts}} = State) -> @@ -1631,57 +1613,6 @@ after_new_keys_events({connection_reply, _Data} = Reply, {StateName, State}) -> NewState = send_replies([Reply], State), {next_state, StateName, NewState}. -handle_ssh_packet_data(RemainingSshPacketLen, DecData, EncData, StateName, - State) -> - EncSize = size(EncData), - case RemainingSshPacketLen > EncSize of - true -> - {next_state, StateName, - next_packet(State#state{decoded_data_buffer = DecData, - encoded_data_buffer = EncData, - undecoded_packet_length = - RemainingSshPacketLen})}; - false -> - handle_ssh_packet(RemainingSshPacketLen, StateName, - State#state{decoded_data_buffer = DecData, - encoded_data_buffer = EncData}) - - end. - -handle_ssh_packet(Length, StateName, #state{decoded_data_buffer = DecData0, - encoded_data_buffer = EncData0, - ssh_params = Ssh0, - transport_protocol = _Protocol, - socket = _Socket} = State0) -> - try - {Ssh1, DecData, EncData, Mac} = - ssh_transport:unpack(EncData0, Length, Ssh0), - SshPacket = <>, - case ssh_transport:is_valid_mac(Mac, SshPacket, Ssh1) of - true -> - PacketData = ssh_transport:msg_data(SshPacket), - {Ssh1, Msg} = ssh_transport:decompress(Ssh1, PacketData), - generate_event(Msg, StateName, - State0#state{ssh_params = Ssh1, - %% Important to be set for - %% next_packet - decoded_data_buffer = <<>>}, - EncData); - false -> - DisconnectMsg = - #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "Bad mac", - language = "en"}, - handle_disconnect(DisconnectMsg, State0) - end - catch _:_ -> - Disconnect = - #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "Bad input", - language = "en"}, - handle_disconnect(Disconnect, State0) - end. - handle_disconnect(DisconnectMsg, State) -> handle_disconnect(own, DisconnectMsg, State). diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 0c999b96cc..f18e4b4d01 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -31,10 +31,10 @@ -include("ssh.hrl"). -export([versions/2, hello_version_msg/1]). --export([next_seqnum/1, decrypt_first_block/2, decrypt_blocks/3, +-export([next_seqnum/1, supported_algorithms/0, supported_algorithms/1, default_algorithms/0, default_algorithms/1, - is_valid_mac/3, + handle_packet_part/4, handle_hello_version/1, key_exchange_init_msg/1, key_init/3, new_keys_message/1, @@ -45,9 +45,13 @@ handle_kex_ecdh_init/2, handle_kex_ecdh_reply/2, extract_public_key/1, - unpack/3, decompress/2, ssh_packet/2, pack/2, pack/3, msg_data/1, + ssh_packet/2, pack/2, sign/3, verify/4]). +%%% For test suites +-export([pack/3]). +-export([decompress/2, decrypt_blocks/3, is_valid_mac/3 ]). % FIXME: remove + %%%---------------------------------------------------------------------------- %%% %%% There is a difference between supported and default algorithms. The @@ -196,12 +200,6 @@ hello_version_msg(Data) -> next_seqnum(SeqNum) -> (SeqNum + 1) band 16#ffffffff. -decrypt_first_block(Bin, #ssh{decrypt_block_size = BlockSize} = Ssh0) -> - <> = Bin, - {Ssh, <> = DecData} = - decrypt(Ssh0, EncBlock), - {Ssh, PacketLen, DecData, EncData}. - decrypt_blocks(Bin, Length, Ssh0) -> <> = Bin, {Ssh, DecData} = decrypt(Ssh0, EncBlocks), @@ -938,27 +936,61 @@ pack(Data0, #ssh{encrypt_block_size = BlockSize, Ssh = Ssh2#ssh{send_sequence = (SeqNum+1) band 16#ffffffff}, {Packet, Ssh}. -unpack(EncodedSoFar, ReminingLenght, #ssh{recv_mac_size = MacSize} = Ssh0) -> - SshLength = ReminingLenght - MacSize, - {NoMac, Mac, Rest} = case MacSize of - 0 -> - <> = EncodedSoFar, - {NoMac0, <<>>, Rest0}; - _ -> - <> = EncodedSoFar, - {NoMac0, Mac0, Rest0} - end, - {Ssh1, DecData, <<>>} = - case SshLength of - 0 -> - {Ssh0, <<>>, <<>>}; - _ -> - decrypt_blocks(NoMac, SshLength, Ssh0) - end, - {Ssh1, DecData, Rest, Mac}. + +handle_packet_part(<<>>, Encoded0, undefined, Ssh0) -> + %% New ssh packet + case get_length(Encoded0, Ssh0) of + get_more -> + %% too short to get the length + {get_more, <<>>, Encoded0, undefined, Ssh0}; + + {ok, PacketLen, _DecData, _Encoded1, _Ssh1} when PacketLen > ?SSH_MAX_PACKET_SIZE -> + %% far too long message than expected + throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad packet length " + ++ integer_to_list(PacketLen), + language = ""}); + + {ok, PacketLen, DecData, Encoded1, + #ssh{decrypt_block_size = BlockSize, + recv_mac_size = MacSize} = Ssh1} -> + %% enough bytes so we got the length and can calculate how many + %% more bytes to expect for a full packet + Remaining = (PacketLen + ?SSH_LENGHT_INDICATOR_SIZE) - BlockSize + MacSize, + handle_packet_part(DecData, Encoded1, Remaining, Ssh1) + end; +handle_packet_part(Decoded0, Encoded0, Remaining, Ssh0) + when size(Encoded0) < Remaining -> + %% need more bytes to finalize the packet + {get_more, Decoded0, Encoded0, Remaining, Ssh0}; +handle_packet_part(Decoded0, Encoded0, Remaining, + #ssh{recv_mac_size = MacSize} = Ssh0) -> + %% enough bytes to decode the packet. + SshLengthNotDecoded = Remaining - MacSize, + <> = Encoded0, + {Ssh1, DecData} = decrypt(Ssh0, PktT), + MsgBytes = <>, + case is_valid_mac(Mac, MsgBytes, Ssh1) of + false -> + {bad_mac, Ssh1}; + true -> + {Ssh, DecompressedMsgBytes} = decompress(Ssh1, msg_data(MsgBytes)), + {decoded, DecompressedMsgBytes, EncRest0, Ssh} + end. + + +get_length(Encoded0, #ssh{decrypt_block_size = BlockSize} = Ssh0) -> + case size(Encoded0) >= erlang:max(8, BlockSize) of + true -> + <> = Encoded0, + {Ssh, Decoded} = decrypt(Ssh0, EncBlock), + <> = Decoded, + {ok, PacketLen, Decoded, EncodedRest, Ssh}; + false -> + get_more + end. + + msg_data(PacketData) -> <> = PacketData, @@ -1181,6 +1213,8 @@ decrypt_final(Ssh) -> decrypt_ctx = undefined, decrypt_block_size = 8}}. +decrypt(Ssh, <<>>) -> + {Ssh, <<>>}; decrypt(#ssh{decrypt = none} = Ssh, Data) -> {Ssh, Data}; decrypt(#ssh{decrypt = '3des-cbc', decrypt_keys = Keys, -- cgit v1.2.3 From a895fc7303497f1795cf49360980abeb68be2223 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 18 Nov 2015 20:26:12 +0100 Subject: ssh: AEAD_AES_(128|256)_GCM and aes(128|256)-gcm@openssh.com crypto Note that the rfc5647 is ambigous so this implementation of AEAD_AES_(128|256)_GCM may or may not be compatible with others. They are note enabled by default but may be enabled by the user. See the Reference Manual, Application SSH for details of how we interpret the rfc. To be safe, use aes128-gcm@openssh.com or aes256-gcm@openssh.com instead. --- lib/ssh/src/ssh.hrl | 1 - lib/ssh/src/ssh_transport.erl | 464 ++++++++++++++++++++++++++++++------------ 2 files changed, 333 insertions(+), 132 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 4ad936f742..8efc743b67 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -29,7 +29,6 @@ -define(SSH_DEFAULT_PORT, 22). -define(SSH_MAX_PACKET_SIZE, (256*1024)). --define(SSH_LENGHT_INDICATOR_SIZE, 4). -define(REKEY_TIMOUT, 3600000). -define(REKEY_DATA_TIMOUT, 60000). -define(DEFAULT_PROFILE, default). diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index f18e4b4d01..e2d19b9cef 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -70,10 +70,15 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()]. algo_classes() -> [kex, public_key, cipher, mac, compression]. -%% default_algorithms(kex) -> % Example of how to disable an algorithm -%% supported_algorithms(kex, ['ecdh-sha2-nistp521']); + +default_algorithms(cipher) -> + supported_algorithms(cipher, same(['AEAD_AES_128_GCM', + 'AEAD_AES_256_GCM'])); +default_algorithms(mac) -> + supported_algorithms(mac, same(['AEAD_AES_128_GCM', + 'AEAD_AES_256_GCM'])); default_algorithms(Alg) -> - supported_algorithms(Alg). + supported_algorithms(Alg, []). supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()]. @@ -101,19 +106,25 @@ supported_algorithms(public_key) -> supported_algorithms(cipher) -> same( select_crypto_supported( - [{'aes256-ctr', [{ciphers,{aes_ctr,256}}]}, - {'aes192-ctr', [{ciphers,{aes_ctr,192}}]}, - {'aes128-ctr', [{ciphers,{aes_ctr,128}}]}, - {'aes128-cbc', [{ciphers,aes_cbc128}]}, - {'3des-cbc', [{ciphers,des3_cbc}]} + [{'aes256-ctr', [{ciphers,{aes_ctr,256}}]}, + {'aes192-ctr', [{ciphers,{aes_ctr,192}}]}, + {'aes128-ctr', [{ciphers,{aes_ctr,128}}]}, + {'aes128-cbc', [{ciphers,aes_cbc128}]}, + {'aes128-gcm@openssh.com', [{ciphers,{aes_gcm,128}}]}, + {'aes256-gcm@openssh.com', [{ciphers,{aes_gcm,256}}]}, + {'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]}, + {'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]}, + {'3des-cbc', [{ciphers,des3_cbc}]} ] )); supported_algorithms(mac) -> same( select_crypto_supported( - [{'hmac-sha2-256', [{hashs,sha256}]}, - {'hmac-sha2-512', [{hashs,sha512}]}, - {'hmac-sha1', [{hashs,sha}]} + [{'hmac-sha2-256', [{hashs,sha256}]}, + {'hmac-sha2-512', [{hashs,sha512}]}, + {'hmac-sha1', [{hashs,sha}]}, + {'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]}, + {'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]} ] )); supported_algorithms(compression) -> @@ -122,46 +133,6 @@ supported_algorithms(compression) -> 'zlib' ]). -%% Dialyzer complains when not called...supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> -%% Dialyzer complains when not called... [{client2server,As1},{server2client,As2}] = supported_algorithms(Key), -%% Dialyzer complains when not called... [{client2server,As1--BL1},{server2client,As2--BL2}]; -%% Dialyzer complains when not called...supported_algorithms(Key, BlackList) -> -%% Dialyzer complains when not called... supported_algorithms(Key) -- BlackList. - -select_crypto_supported(L) -> - Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()], - [Name || {Name,CryptoRequires} <- L, - crypto_supported(CryptoRequires, Sup)]. - -crypto_supported_curves() -> - try crypto:ec_curves() - catch _:_ -> [] - end. - -crypto_supported(Conditions, Supported) -> - lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) -> - crypto_name_supported(Tag,CryptoName,Supported); - ({Tag,{Name=aes_ctr,Len}}) when is_integer(Len) -> - crypto_name_supported(Tag,Name,Supported) andalso - ctr_len_supported(Name,Len) - end, Conditions). - -crypto_name_supported(Tag, CryptoName, Supported) -> - lists:member(CryptoName, proplists:get_value(Tag,Supported,[])). - -ctr_len_supported(Name, Len) -> - try - crypto:stream_encrypt(crypto:stream_init(Name, <<0:Len>>, <<0:128>>), <<"">>) - of - {_,X} -> is_binary(X) - catch - _:_ -> false - end. - - -same(Algs) -> [{client2server,Algs}, {server2client,Algs}]. - - %%%---------------------------------------------------------------------------- versions(client, Options)-> Vsn = proplists:get_value(vsn, Options, ?DEFAULT_CLIENT_VERSION), @@ -755,8 +726,12 @@ known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = Peer} = Ssh, %% The first algorithm in each list MUST be the preferred (guessed) %% algorithm. Each string MUST contain at least one algorithm name. select_algorithm(Role, Client, Server) -> - {Encrypt, Decrypt} = select_encrypt_decrypt(Role, Client, Server), - {SendMac, RecvMac} = select_send_recv_mac(Role, Client, Server), + {Encrypt0, Decrypt0} = select_encrypt_decrypt(Role, Client, Server), + {SendMac0, RecvMac0} = select_send_recv_mac(Role, Client, Server), + + {Encrypt, SendMac} = aead_gcm_simultan(Encrypt0, SendMac0), + {Decrypt, RecvMac} = aead_gcm_simultan(Decrypt0, RecvMac0), + {Compression, Decompression} = select_compression_decompression(Role, Client, Server), @@ -787,6 +762,38 @@ select_algorithm(Role, Client, Server) -> s_lng = S_Lng}, {ok, Alg}. + +%%% It is an agreed problem with RFC 5674 that if the selection is +%%% Cipher = AEAD_AES_x_GCM and +%%% Mac = AEAD_AES_y_GCM (where x =/= y) +%%% then it is undefined what length should be selected. +%%% +%%% If only one of the two lengths (128,256) is available, I claim that +%%% there is no such ambiguity. + +%%% From https://anongit.mindrot.org/openssh.git/plain/PROTOCOL +%%% (read Nov 20, 2015) +%%% 1.6 transport: AES-GCM +%%% +%%% OpenSSH supports the AES-GCM algorithm as specified in RFC 5647. +%%% Because of problems with the specification of the key exchange +%%% the behaviour of OpenSSH differs from the RFC as follows: +%%% +%%% AES-GCM is only negotiated as the cipher algorithms +%%% "aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as +%%% an MAC algorithm. Additionally, if AES-GCM is selected as the cipher +%%% the exchanged MAC algorithms are ignored and there doesn't have to be +%%% a matching MAC. + +aead_gcm_simultan('aes128-gcm@openssh.com', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'}; +aead_gcm_simultan('aes256-gcm@openssh.com', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'}; +aead_gcm_simultan('AEAD_AES_128_GCM', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'}; +aead_gcm_simultan('AEAD_AES_256_GCM', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'}; +aead_gcm_simultan(_, 'AEAD_AES_128_GCM') -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'}; +aead_gcm_simultan(_, 'AEAD_AES_256_GCM') -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'}; +aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}. + + select_encrypt_decrypt(client, Client, Server) -> Encrypt = select(Client#ssh_msg_kexinit.encryption_algorithms_client_to_server, @@ -821,18 +828,18 @@ select_compression_decompression(client, Client, Server) -> Compression = select(Client#ssh_msg_kexinit.compression_algorithms_client_to_server, Server#ssh_msg_kexinit.compression_algorithms_client_to_server), - Decomprssion = + Decompression = select(Client#ssh_msg_kexinit.compression_algorithms_server_to_client, Server#ssh_msg_kexinit.compression_algorithms_server_to_client), - {Compression, Decomprssion}; + {Compression, Decompression}; select_compression_decompression(server, Client, Server) -> - Decomprssion = + Decompression = select(Client#ssh_msg_kexinit.compression_algorithms_client_to_server, Server#ssh_msg_kexinit.compression_algorithms_client_to_server), Compression = select(Client#ssh_msg_kexinit.compression_algorithms_server_to_client, Server#ssh_msg_kexinit.compression_algorithms_server_to_client), - {Compression, Decomprssion}. + {Compression, Decompression}. install_alg(SSH) -> SSH1 = alg_final(SSH), @@ -909,14 +916,39 @@ pack(Data, Ssh=#ssh{}) -> %%% Note: pack/3 is only to be called from tests that wants %%% to deliberetly send packets with wrong PacketLength! %%% Use pack/2 for all other purposes! -pack(Data0, #ssh{encrypt_block_size = BlockSize, - send_sequence = SeqNum, send_mac = MacAlg, - send_mac_key = MacKey, - random_length_padding = RandomLengthPadding} - = Ssh0, - PacketLenDeviationForTests) when is_binary(Data0) -> - {Ssh1, Data} = compress(Ssh0, Data0), - PL = (BlockSize - ((4 + 1 + size(Data)) rem BlockSize)) rem BlockSize, +pack(PlainText, + #ssh{send_sequence = SeqNum, + send_mac = MacAlg, + send_mac_key = MacKey, + encrypt = CryptoAlg} = Ssh0, PacketLenDeviationForTests) when is_binary(PlainText) -> + + {Ssh1, CompressedPlainText} = compress(Ssh0, PlainText), + {EcryptedPacket, MAC, Ssh3} = + case pkt_type(CryptoAlg) of + common -> + PaddingLen = padding_length(4+1+size(CompressedPlainText), Ssh0), + Padding = ssh_bits:random(PaddingLen), + PlainPacketLen = 1 + PaddingLen + size(CompressedPlainText) + PacketLenDeviationForTests, + PlainPacketData = <>, + {Ssh2, EcryptedPacket0} = encrypt(Ssh1, PlainPacketData), + MAC0 = mac(MacAlg, MacKey, SeqNum, PlainPacketData), + {EcryptedPacket0, MAC0, Ssh2}; + aead -> + PaddingLen = padding_length(1+size(CompressedPlainText), Ssh0), + Padding = ssh_bits:random(PaddingLen), + PlainPacketLen = 1 + PaddingLen + size(CompressedPlainText) + PacketLenDeviationForTests, + PlainPacketData = <>, + {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, {<>,PlainPacketData}), + {<>, MAC0, Ssh2} + end, + FinalPacket = [EcryptedPacket, MAC], + Ssh = Ssh3#ssh{send_sequence = (SeqNum+1) band 16#ffffffff}, + {FinalPacket, Ssh}. + + +padding_length(Size, #ssh{encrypt_block_size = BlockSize, + random_length_padding = RandomLengthPadding}) -> + PL = (BlockSize - (Size rem BlockSize)) rem BlockSize, MinPaddingLen = if PL < 4 -> PL + BlockSize; true -> PL end, @@ -925,79 +957,94 @@ pack(Data0, #ssh{encrypt_block_size = BlockSize, ExtraPaddingLen = try crypto:rand_uniform(0,MaxExtraBlocks)*PadBlockSize catch _:_ -> 0 end, - PaddingLen = MinPaddingLen + ExtraPaddingLen, - Padding = ssh_bits:random(PaddingLen), - PacketLen = 1 + PaddingLen + size(Data) + PacketLenDeviationForTests, - PacketData = <>, - {Ssh2, EncPacket} = encrypt(Ssh1, PacketData), - MAC = mac(MacAlg, MacKey, SeqNum, PacketData), - Packet = [EncPacket, MAC], - Ssh = Ssh2#ssh{send_sequence = (SeqNum+1) band 16#ffffffff}, - {Packet, Ssh}. - - -handle_packet_part(<<>>, Encoded0, undefined, Ssh0) -> + MinPaddingLen + ExtraPaddingLen. + + + +handle_packet_part(<<>>, Encrypted0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) -> %% New ssh packet - case get_length(Encoded0, Ssh0) of + case get_length(pkt_type(CryptoAlg), Encrypted0, Ssh0) of get_more -> %% too short to get the length - {get_more, <<>>, Encoded0, undefined, Ssh0}; + {get_more, <<>>, Encrypted0, undefined, Ssh0}; - {ok, PacketLen, _DecData, _Encoded1, _Ssh1} when PacketLen > ?SSH_MAX_PACKET_SIZE -> + {ok, PacketLen, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE -> %% far too long message than expected throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, description = "Bad packet length " ++ integer_to_list(PacketLen), language = ""}); - {ok, PacketLen, DecData, Encoded1, - #ssh{decrypt_block_size = BlockSize, - recv_mac_size = MacSize} = Ssh1} -> + {ok, PacketLen, Decrypted, Encrypted1, + #ssh{recv_mac_size = MacSize} = Ssh1} -> %% enough bytes so we got the length and can calculate how many %% more bytes to expect for a full packet - Remaining = (PacketLen + ?SSH_LENGHT_INDICATOR_SIZE) - BlockSize + MacSize, - handle_packet_part(DecData, Encoded1, Remaining, Ssh1) + TotalNeeded = (4 + PacketLen + MacSize), + handle_packet_part(Decrypted, Encrypted1, TotalNeeded, Ssh1) end; -handle_packet_part(Decoded0, Encoded0, Remaining, Ssh0) - when size(Encoded0) < Remaining -> + +handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0) + when (size(DecryptedPfx)+size(EncryptedBuffer)) < TotalNeeded -> %% need more bytes to finalize the packet - {get_more, Decoded0, Encoded0, Remaining, Ssh0}; -handle_packet_part(Decoded0, Encoded0, Remaining, - #ssh{recv_mac_size = MacSize} = Ssh0) -> + {get_more, DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0}; + +handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded, + #ssh{recv_mac_size = MacSize, + decrypt = CryptoAlg} = Ssh0) -> %% enough bytes to decode the packet. - SshLengthNotDecoded = Remaining - MacSize, - <> = Encoded0, - {Ssh1, DecData} = decrypt(Ssh0, PktT), - MsgBytes = <>, - case is_valid_mac(Mac, MsgBytes, Ssh1) of - false -> - {bad_mac, Ssh1}; - true -> - {Ssh, DecompressedMsgBytes} = decompress(Ssh1, msg_data(MsgBytes)), - {decoded, DecompressedMsgBytes, EncRest0, Ssh} + DecryptLen = TotalNeeded - size(DecryptedPfx) - MacSize, + <> = EncryptedBuffer, + case pkt_type(CryptoAlg) of + common -> + {Ssh1, DecryptedSfx} = decrypt(Ssh0, EncryptedSfx), + DecryptedPacket = <>, + case is_valid_mac(Mac, DecryptedPacket, Ssh1) of + false -> + {bad_mac, Ssh1}; + true -> + {Ssh, DecompressedPayload} = decompress(Ssh1, payload(DecryptedPacket)), + {decoded, DecompressedPayload, NextPacketBytes, Ssh} + end; + aead -> + PacketLenBin = DecryptedPfx, + case decrypt(Ssh0, {PacketLenBin,EncryptedSfx,Mac}) of + {Ssh1, error} -> + {bad_mac, Ssh1}; + {Ssh1, DecryptedSfx} -> + DecryptedPacket = <>, + {Ssh, DecompressedPayload} = decompress(Ssh1, payload(DecryptedPacket)), + {decoded, DecompressedPayload, NextPacketBytes, Ssh} + end end. -get_length(Encoded0, #ssh{decrypt_block_size = BlockSize} = Ssh0) -> - case size(Encoded0) >= erlang:max(8, BlockSize) of +get_length(common, EncryptedBuffer, #ssh{decrypt_block_size = BlockSize} = Ssh0) -> + case size(EncryptedBuffer) >= erlang:max(8, BlockSize) of true -> - <> = Encoded0, - {Ssh, Decoded} = decrypt(Ssh0, EncBlock), - <> = Decoded, - {ok, PacketLen, Decoded, EncodedRest, Ssh}; + <> = EncryptedBuffer, + {Ssh, + <> = Decrypted} = decrypt(Ssh0, EncBlock), + {ok, PacketLen, Decrypted, EncryptedRest, Ssh}; + false -> + get_more + end; +get_length(aead, EncryptedBuffer, Ssh) -> + case size(EncryptedBuffer) >= 4 of + true -> + <> = EncryptedBuffer, + {ok, PacketLen, <>, EncryptedRest, Ssh}; false -> get_more end. +pkt_type('AEAD_AES_128_GCM') -> aead; +pkt_type('AEAD_AES_256_GCM') -> aead; +pkt_type(_) -> common. - -msg_data(PacketData) -> - <> = PacketData, - DataLen = Len - PaddingLen - 1, - <<_:32, _:8, Data:DataLen/binary, - _:PaddingLen/binary>> = PacketData, - Data. +payload(<>) -> + PayloadLen = PacketLen - PaddingLen - 1, + <> = PayloadAndPadding, + Payload. sign(SigData, Hash, #'DSAPrivateKey'{} = Key) -> DerSignature = public_key:sign(SigData, Hash, Key), @@ -1023,6 +1070,7 @@ verify(PlainText, Hash, Sig, {#'ECPoint'{},_} = Key) -> verify(PlainText, Hash, Sig, Key) -> public_key:verify(PlainText, Hash, Sig, Key). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Encryption @@ -1031,6 +1079,30 @@ verify(PlainText, Hash, Sig, Key) -> encrypt_init(#ssh{encrypt = none} = Ssh) -> {ok, Ssh}; +encrypt_init(#ssh{encrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) -> + IV = hash(Ssh, "A", 12*8), + <> = hash(Ssh, "C", 128), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = IV}}; +encrypt_init(#ssh{encrypt = 'AEAD_AES_128_GCM', role = server} = Ssh) -> + IV = hash(Ssh, "B", 12*8), + <> = hash(Ssh, "D", 128), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = IV}}; +encrypt_init(#ssh{encrypt = 'AEAD_AES_256_GCM', role = client} = Ssh) -> + IV = hash(Ssh, "A", 12*8), + <> = hash(Ssh, "C", 256), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = IV}}; +encrypt_init(#ssh{encrypt = 'AEAD_AES_256_GCM', role = server} = Ssh) -> + IV = hash(Ssh, "B", 12*8), + <> = hash(Ssh, "D", 256), + {ok, Ssh#ssh{encrypt_keys = K, + encrypt_block_size = 16, + encrypt_ctx = IV}}; encrypt_init(#ssh{encrypt = '3des-cbc', role = client} = Ssh) -> IV = hash(Ssh, "A", 64), <> = hash(Ssh, "C", 192), @@ -1107,6 +1179,18 @@ encrypt_final(Ssh) -> encrypt(#ssh{encrypt = none} = Ssh, Data) -> {Ssh, Data}; +encrypt(#ssh{encrypt = 'AEAD_AES_128_GCM', + encrypt_keys = K, + encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) -> + Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data), + IV = next_gcm_iv(IV0), + {Ssh#ssh{encrypt_ctx = IV}, Enc}; +encrypt(#ssh{encrypt = 'AEAD_AES_256_GCM', + encrypt_keys = K, + encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) -> + Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data), + IV = next_gcm_iv(IV0), + {Ssh#ssh{encrypt_ctx = IV}, Enc}; encrypt(#ssh{encrypt = '3des-cbc', encrypt_keys = {K1,K2,K3}, encrypt_ctx = IV0} = Ssh, Data) -> @@ -1139,6 +1223,30 @@ encrypt(#ssh{encrypt = 'aes256-ctr', decrypt_init(#ssh{decrypt = none} = Ssh) -> {ok, Ssh}; +decrypt_init(#ssh{decrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) -> + IV = hash(Ssh, "B", 12*8), + <> = hash(Ssh, "D", 128), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = IV}}; +decrypt_init(#ssh{decrypt = 'AEAD_AES_128_GCM', role = server} = Ssh) -> + IV = hash(Ssh, "A", 12*8), + <> = hash(Ssh, "C", 128), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = IV}}; +decrypt_init(#ssh{decrypt = 'AEAD_AES_256_GCM', role = client} = Ssh) -> + IV = hash(Ssh, "B", 12*8), + <> = hash(Ssh, "D", 256), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = IV}}; +decrypt_init(#ssh{decrypt = 'AEAD_AES_256_GCM', role = server} = Ssh) -> + IV = hash(Ssh, "A", 12*8), + <> = hash(Ssh, "C", 256), + {ok, Ssh#ssh{decrypt_keys = K, + decrypt_block_size = 16, + decrypt_ctx = IV}}; decrypt_init(#ssh{decrypt = '3des-cbc', role = client} = Ssh) -> {IV, KD} = {hash(Ssh, "B", 64), hash(Ssh, "D", 192)}, @@ -1217,6 +1325,18 @@ decrypt(Ssh, <<>>) -> {Ssh, <<>>}; decrypt(#ssh{decrypt = none} = Ssh, Data) -> {Ssh, Data}; +decrypt(#ssh{decrypt = 'AEAD_AES_128_GCM', + decrypt_keys = K, + decrypt_ctx = IV0} = Ssh, Data = {_AAD,_Ctext,_Ctag}) -> + Dec = crypto:block_decrypt(aes_gcm, K, IV0, Data), % Dec = PlainText | error + IV = next_gcm_iv(IV0), + {Ssh#ssh{decrypt_ctx = IV}, Dec}; +decrypt(#ssh{decrypt = 'AEAD_AES_256_GCM', + decrypt_keys = K, + decrypt_ctx = IV0} = Ssh, Data = {_AAD,_Ctext,_Ctag}) -> + Dec = crypto:block_decrypt(aes_gcm, K, IV0, Data), % Dec = PlainText | error + IV = next_gcm_iv(IV0), + {Ssh#ssh{decrypt_ctx = IV}, Dec}; decrypt(#ssh{decrypt = '3des-cbc', decrypt_keys = Keys, decrypt_ctx = IV0} = Ssh, Data) -> {K1, K2, K3} = Keys, @@ -1241,6 +1361,10 @@ decrypt(#ssh{decrypt = 'aes256-ctr', {State, Enc} = crypto:stream_decrypt(State0,Data), {Ssh#ssh{decrypt_ctx = State}, Enc}. + +next_gcm_iv(<>) -> <>. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Compression %% @@ -1329,28 +1453,42 @@ decompress(#ssh{decompress = 'zlib@openssh.com', decompress_ctx = Context, authe %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% send_mac_init(SSH) -> - case SSH#ssh.role of - client -> - KeySize =mac_key_size(SSH#ssh.send_mac), - Key = hash(SSH, "E", KeySize), - {ok, SSH#ssh { send_mac_key = Key }}; - server -> - KeySize = mac_key_size(SSH#ssh.send_mac), - Key = hash(SSH, "F", KeySize), - {ok, SSH#ssh { send_mac_key = Key }} + case pkt_type(SSH#ssh.send_mac) of + common -> + case SSH#ssh.role of + client -> + KeySize = mac_key_size(SSH#ssh.send_mac), + Key = hash(SSH, "E", KeySize), + {ok, SSH#ssh { send_mac_key = Key }}; + server -> + KeySize = mac_key_size(SSH#ssh.send_mac), + Key = hash(SSH, "F", KeySize), + {ok, SSH#ssh { send_mac_key = Key }} + end; + aead -> + %% Not applicable + {ok, SSH} end. send_mac_final(SSH) -> - {ok, SSH#ssh { send_mac = none, send_mac_key = undefined }}. + {ok, SSH#ssh {send_mac = none, + send_mac_key = undefined }}. + recv_mac_init(SSH) -> - case SSH#ssh.role of - client -> - Key = hash(SSH, "F", mac_key_size(SSH#ssh.recv_mac)), - {ok, SSH#ssh { recv_mac_key = Key }}; - server -> - Key = hash(SSH, "E", mac_key_size(SSH#ssh.recv_mac)), - {ok, SSH#ssh { recv_mac_key = Key }} + case pkt_type(SSH#ssh.recv_mac) of + common -> + case SSH#ssh.role of + client -> + Key = hash(SSH, "F", mac_key_size(SSH#ssh.recv_mac)), + {ok, SSH#ssh { recv_mac_key = Key }}; + server -> + Key = hash(SSH, "E", mac_key_size(SSH#ssh.recv_mac)), + {ok, SSH#ssh { recv_mac_key = Key }} + end; + aead -> + %% Not applicable + {ok, SSH} end. recv_mac_final(SSH) -> @@ -1481,6 +1619,8 @@ mac_digest_size('hmac-md5') -> 20; mac_digest_size('hmac-md5-96') -> 12; mac_digest_size('hmac-sha2-256') -> 32; mac_digest_size('hmac-sha2-512') -> 64; +mac_digest_size('AEAD_AES_128_GCM') -> 16; +mac_digest_size('AEAD_AES_256_GCM') -> 16; mac_digest_size(none) -> 0. peer_name({Host, _}) -> @@ -1510,6 +1650,68 @@ ecdh_curve('ecdh-sha2-nistp256') -> secp256r1; ecdh_curve('ecdh-sha2-nistp384') -> secp384r1; ecdh_curve('ecdh-sha2-nistp521') -> secp521r1. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Utils for default_algorithms/1 and supported_algorithms/1 +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) -> + [{client2server,As1},{server2client,As2}] = supported_algorithms(Key), + [{client2server,As1--BL1},{server2client,As2--BL2}]; +supported_algorithms(Key, BlackList) -> + supported_algorithms(Key) -- BlackList. + + +select_crypto_supported(L) -> + Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()], + [Name || {Name,CryptoRequires} <- L, + crypto_supported(CryptoRequires, Sup)]. + +crypto_supported_curves() -> + try crypto:ec_curves() + catch _:_ -> [] + end. + +crypto_supported(Conditions, Supported) -> + lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) -> + crypto_name_supported(Tag,CryptoName,Supported); + ({Tag,{Name,Len}}) when is_integer(Len) -> + crypto_name_supported(Tag,Name,Supported) andalso + len_supported(Name,Len) + end, Conditions). + +crypto_name_supported(Tag, CryptoName, Supported) -> + lists:member(CryptoName, proplists:get_value(Tag,Supported,[])). + +len_supported(Name, Len) -> + try + case Name of + aes_ctr -> + {_, <<_/binary>>} = + %% Test encryption + crypto:stream_encrypt(crypto:stream_init(Name, <<0:Len>>, <<0:128>>), <<"">>); + aes_gcm -> + {<<_/binary>>, <<_/binary>>} = + crypto:block_encrypt(Name, + _Key = <<0:Len>>, + _IV = <<0:12/unsigned-unit:8>>, + {"AAD","PT"}) + end + of + _ -> true + catch + _:_ -> false + end. + + +same(Algs) -> [{client2server,Algs}, {server2client,Algs}]. + + +%% default_algorithms(kex) -> % Example of how to disable an algorithm +%% supported_algorithms(kex, ['ecdh-sha2-nistp521']); + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Other utils -- cgit v1.2.3 From 3dd45583508269dc0189277002e140dd0a1369ba Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 20 Nov 2015 21:03:37 +0100 Subject: ssh: documentation updates --- lib/ssh/doc/src/ssh_app.xml | 70 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index 29cbbd79a2..79dd1e210e 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -137,6 +137,19 @@

Supported algorithms are:

+ Key exchange algorithms + + + ecdh-sha2-nistp256 + ecdh-sha2-nistp384 + ecdh-sha2-nistp521 + diffie-hellman-group-exchange-sha1 + diffie-hellman-group-exchange-sha256 + diffie-hellman-group14-sha1 + diffie-hellman-group1-sha1 + + + Public key algorithms @@ -157,30 +170,26 @@ - Encryption algorithms + Encryption algorithms (ciphers) + aes128-gcm@openssh.com (AEAD_AES_128_GCM) + aes256-gcm@openssh.com (AEAD_AES_256_GCM) aes128-ctr aes192-ctr aes256-ctr aes128-cbc 3des-cbc +

Following the internet de-facto standard, the cipher and mac algorithm AEAD_AES_128_GCM is selected when the + cipher aes128-gcm@openssh.com is negotiated. The cipher and mac algorithm AEAD_AES_256_GCM is selected when the + cipher aes256-gcm@openssh.com is negotiated. +

+

See the text at the description of the rfc 5647 further down + for more information. +

- - Key exchange algorithms - - - ecdh-sha2-nistp256 - ecdh-sha2-nistp384 - ecdh-sha2-nistp521 - diffie-hellman-group-exchange-sha1 - diffie-hellman-group-exchange-sha256 - diffie-hellman-group14-sha1 - diffie-hellman-group1-sha1 - - - + Compression algorithms @@ -255,6 +264,30 @@

+ RFC 5647, AES Galois Counter Mode for + the Secure Shell Transport Layer Protocol. +

There is an ambiguity in the synchronized selection of cipher and mac algorithm. + This is resolved by OpenSSH in the ciphers aes128-gcm@openssh.com and aes256-gcm@openssh.com which are implemented. + If the explicit ciphers and macs AEAD_AES_128_GCM or AEAD_AES_256_GCM are needed, + they could be enabled with the option preferred_algorithms. + + If the client or the server is not Erlang/OTP, it is the users responsibility to check that + other implementation has the same interpretation of AEAD_AES_*_GCM as the Erlang/OTP SSH before + enabling them. The aes*-gcm@openssh.com variants are always safe to use since they lack the + ambiguity. + +

+

The second paragraph in section 5.1 is resolved as: + + If the negotiated cipher is AEAD_AES_128_GCM, the mac algorithm is set to AEAD_AES_128_GCM. + If the negotiated cipher is AEAD_AES_256_GCM, the mac algorithm is set to AEAD_AES_256_GCM. + If the mac algorithm is AEAD_AES_128_GCM, the cipher is set to AEAD_AES_128_GCM. + If the mac algorithm is AEAD_AES_256_GCM, the cipher is set to AEAD_AES_256_GCM. + + The first rule that matches when read in order from the top is applied +

+
+ RFC 5656, Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer.

Except @@ -266,6 +299,13 @@

+ + RFC 6668, SHA-2 Data Integrity Verification for + the Secure Shell (SSH) Transport Layer Protocol +

Comment: Defines hmac-sha2-256 and hmac-sha2-512 +

+
+
-- cgit v1.2.3 From b5df882f98c13ac52535f70e50473b9d6c1fb929 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 23 Nov 2015 10:49:16 +0100 Subject: ssh: renegotiate test group for AES_GCM --- lib/ssh/test/ssh_renegotiate_SUITE.erl | 22 ++++++++++++++++++++-- lib/ssh/test/ssh_test_lib.erl | 10 +++++----- 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl index ef631d54bd..227dfcddcd 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE.erl +++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl @@ -32,9 +32,15 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> [rekey, rekey_limit, renegotiate1, renegotiate2]. +all() -> [{group,default_algs}, + {group,aes_gcm} + ]. -groups() -> []. +groups() -> [{default_algs, [], tests()}, + {aes_gcm, [], tests()} + ]. + +tests() -> [rekey, rekey_limit, renegotiate1, renegotiate2]. %%-------------------------------------------------------------------- init_per_suite(Config) -> @@ -49,6 +55,18 @@ end_per_suite(_Config) -> ssh:stop(), crypto:stop(). +%%-------------------------------------------------------------------- +init_per_group(aes_gcm, Config) -> + [{preferred_algorithms, [{cipher,[{client2server,['aes128-gcm@openssh.com']}, + {server2client,['aes128-gcm@openssh.com']}]}]} + | Config]; +init_per_group(_, Config) -> + [{preferred_algorithms, ssh:default_algorithms()} | Config]. + + +end_per_group(_, Config) -> + Config. + %%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config) -> ssh:start(), diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 5816b708f2..424afc76fe 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -296,7 +296,7 @@ setup_dsa(DataDir, UserDir) -> file:make_dir(System), file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")), file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")), -ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), +ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), setup_dsa_known_host(DataDir, UserDir), setup_dsa_auth_keys(DataDir, UserDir). @@ -306,7 +306,7 @@ setup_rsa(DataDir, UserDir) -> file:make_dir(System), file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")), file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")), -ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), +ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), setup_rsa_known_host(DataDir, UserDir), setup_rsa_auth_keys(DataDir, UserDir). @@ -316,7 +316,7 @@ setup_ecdsa(Size, DataDir, UserDir) -> file:make_dir(System), file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size), filename:join(System, "ssh_host_ecdsa_key")), file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")), -ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), +ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]), setup_ecdsa_known_host(Size, System, UserDir), setup_ecdsa_auth_keys(Size, UserDir, UserDir). @@ -502,7 +502,7 @@ default_algorithms(sshd, Host, Port) -> {user_interaction, false}]}])) catch _C:_E -> - ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), + ct:log("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), [] end. @@ -522,7 +522,7 @@ default_algorithms(sshc, DaemonOptions) -> InitialState)) catch _C:_E -> - ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), + ct:log("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]), [] end} end), -- cgit v1.2.3 From e732293edc5a970885d9eb362dcaddf3548f84a4 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 20 Oct 2015 10:19:16 +0200 Subject: wx: Use only one ring buffer for command queue Avoid copying between command queues, cleaner, faster and safer implementation. --- lib/wx/c_src/wxe_helpers.cpp | 58 +++++++++++++++++++++---- lib/wx/c_src/wxe_helpers.h | 4 ++ lib/wx/c_src/wxe_impl.cpp | 101 ++++++++++++++----------------------------- lib/wx/c_src/wxe_impl.h | 4 +- 4 files changed, 87 insertions(+), 80 deletions(-) (limited to 'lib') diff --git a/lib/wx/c_src/wxe_helpers.cpp b/lib/wx/c_src/wxe_helpers.cpp index cc57374d5b..1696b8bd50 100644 --- a/lib/wx/c_src/wxe_helpers.cpp +++ b/lib/wx/c_src/wxe_helpers.cpp @@ -61,6 +61,7 @@ wxeFifo::wxeFifo(unsigned int sz) m_max = sz; m_n = 0; m_first = 0; + cb_start = 0; m_old = NULL; for(unsigned int i = 0; i < sz; i++) { m_q[i].buffer = NULL; @@ -76,15 +77,30 @@ wxeFifo::~wxeFifo() { wxeCommand * wxeFifo::Get() { unsigned int pos; - if(m_n > 0) { + do { + if(m_n <= 0) + return NULL; + pos = m_first++; m_n--; m_first %= m_max; - return &m_q[pos]; - } - return NULL; + } while(m_q[pos].op == -1); + return &m_q[pos]; +} + +wxeCommand * wxeFifo::Peek(unsigned int *i) +{ + unsigned int pos; + do { + if(*i >= m_n || m_n <= 0) + return NULL; + pos = (m_first+*i) % m_max; + (*i)++; + } while(m_q[pos].op == -1); + return &m_q[pos]; } + void wxeFifo::Add(int fc, char * cbuf,int buflen, wxe_data *sd) { unsigned int pos; @@ -140,10 +156,12 @@ void wxeFifo::Append(wxeCommand *orig) pos = (m_first + m_n) % m_max; m_n++; + curr = &m_q[pos]; + curr->op = orig->op; + if(curr->op == -1) return; curr->caller = orig->caller; curr->port = orig->port; - curr->op = orig->op; curr->len = orig->len; curr->bin[0] = orig->bin[0]; curr->bin[1] = orig->bin[1]; @@ -171,17 +189,19 @@ void wxeFifo::Realloc() wxeCommand * old = m_q; wxeCommand * queue = (wxeCommand *)driver_alloc(new_sz*sizeof(wxeCommand)); + // fprintf(stderr, "\r\nrealloc qsz %d\r\n", new_sz);fflush(stderr); + m_max=new_sz; m_first = 0; m_n=0; m_q = queue; for(i=0; i < n; i++) { - unsigned int pos = i+first; - if(old[pos%max].op >= 0) { - Append(&old[pos%max]); - } + unsigned int pos = (i+first)%max; + if(old[pos].op >= 0) + Append(&old[pos]); } + for(i = m_n; i < new_sz; i++) { // Reset the rest m_q[i].buffer = NULL; m_q[i].op = -1; @@ -190,6 +210,26 @@ void wxeFifo::Realloc() m_old = old; } +// Strip end of queue if ops are already taken care of, avoids reallocs +void wxeFifo::Strip() +{ + while((m_n > 0) && (m_q[(m_first + m_n - 1)%m_max].op == -1)) { + m_n--; + } +} + +unsigned int wxeFifo::Cleanup(unsigned int def) +{ + if(m_old) { + driver_free(m_old); + m_old = NULL; + // Realloced we need to start from the beginning + return 0; + } else { + return def; + } +} + /* **************************************************************************** * TreeItemData * ****************************************************************************/ diff --git a/lib/wx/c_src/wxe_helpers.h b/lib/wx/c_src/wxe_helpers.h index 4f9d9ca9c3..ff949e332b 100644 --- a/lib/wx/c_src/wxe_helpers.h +++ b/lib/wx/c_src/wxe_helpers.h @@ -67,9 +67,13 @@ class wxeFifo { void Append(wxeCommand *Other); wxeCommand * Get(); + wxeCommand * Peek(unsigned int *item); void Realloc(); + void Strip(); + unsigned int Cleanup(unsigned int peek=0); + unsigned int cb_start; unsigned int m_max; unsigned int m_first; unsigned int m_n; diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index 5b34f08704..f81d0bbbd9 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -57,10 +57,8 @@ extern ErlDrvTermData init_caller; extern int wxe_status; wxeFifo * wxe_queue = NULL; -wxeFifo * wxe_queue_cb_saved = NULL; unsigned int wxe_needs_signal = 0; // inside batch if larger than 0 -unsigned int wxe_cb_invoked = 0; /* ************************************************************ * Commands from erlang @@ -123,11 +121,10 @@ bool WxeApp::OnInit() { global_me = new wxeMemEnv(); - wxe_queue = new wxeFifo(1000); - wxe_queue_cb_saved = new wxeFifo(200); + wxe_queue = new wxeFifo(2000); cb_buff = NULL; recurse_level = 0; - delayed_delete = new wxeFifo(10); + delayed_delete = new wxeFifo(100); delayed_cleanup = new wxList; wxe_ps_init2(); @@ -173,7 +170,6 @@ void WxeApp::shutdown(wxeMetaCommand& Ecmd) { wxe_status = WXE_EXITING; ExitMainLoop(); delete wxe_queue; - delete wxe_queue_cb_saved; } void WxeApp::dummy_close(wxEvent& Ev) { @@ -230,11 +226,10 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process) // Should we be able to handle commands when recursing? probably // fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr); app->recurse_level++; - app->dispatch_cb(wxe_queue, wxe_queue_cb_saved, process); + app->dispatch_cb(wxe_queue, process); app->recurse_level--; // fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr); driver_demonitor_process(port, &monitor); - wxe_cb_invoked = 1; } } @@ -242,16 +237,11 @@ void WxeApp::dispatch_cmds() { if(wxe_status != WXE_INITIATED) return; - do { - wxe_cb_invoked = 0; - recurse_level++; - // fprintf(stderr, "\r\ndispatch_saved 0 \r\n");fflush(stderr); - int level = dispatch(wxe_queue_cb_saved, 0, WXE_STORED); - // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr); - dispatch(wxe_queue, level, WXE_NORMAL); - // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr); - recurse_level--; - } while(wxe_cb_invoked); + recurse_level++; + // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr); + dispatch(wxe_queue); + // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr); + recurse_level--; // Cleanup old memenv's and deleted objects if(recurse_level == 0) { @@ -260,6 +250,7 @@ void WxeApp::dispatch_cmds() wxe_dispatch(*curr); curr->Delete(); } + delayed_delete->Cleanup(); if(delayed_cleanup->size() > 0) for( wxList::compatibility_iterator node = delayed_cleanup->GetFirst(); node; @@ -269,28 +260,19 @@ void WxeApp::dispatch_cmds() destroyMemEnv(*event); delete event; } - if(wxe_queue_cb_saved->m_old) { - driver_free(wxe_queue_cb_saved->m_old); - wxe_queue_cb_saved->m_old = NULL; - } - if(delayed_delete->m_old) { - driver_free(delayed_delete->m_old); - delayed_delete->m_old = NULL; - } } } -int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type) +int WxeApp::dispatch(wxeFifo * batch) { int ping = 0; + int blevel = 0; wxeCommand *event; - if(list_type == WXE_NORMAL) erl_drv_mutex_lock(wxe_batch_locker_m); + erl_drv_mutex_lock(wxe_batch_locker_m); while(true) { while((event = batch->Get()) != NULL) { - if(list_type == WXE_NORMAL) erl_drv_mutex_unlock(wxe_batch_locker_m); + erl_drv_mutex_unlock(wxe_batch_locker_m); switch(event->op) { - case -1: - break; case WXE_BATCH_END: {--blevel; } break; @@ -321,20 +303,10 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type) break; } event->Delete(); - if(list_type == WXE_NORMAL) { - if(wxe_cb_invoked) - return blevel; - else - erl_drv_mutex_lock(wxe_batch_locker_m); - } + erl_drv_mutex_lock(wxe_batch_locker_m); + batch->Cleanup(); } - if(list_type == WXE_STORED) - return blevel; - if(blevel <= 0) { // list_type == WXE_NORMAL - if(wxe_queue->m_old) { - driver_free(wxe_queue->m_old); - wxe_queue->m_old = NULL; - } + if(blevel <= 0) { erl_drv_mutex_unlock(wxe_batch_locker_m); return blevel; } @@ -348,12 +320,13 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type) } } -void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process) { +void WxeApp::dispatch_cb(wxeFifo * batch, ErlDrvTermData process) { wxeCommand *event; + unsigned int peek; erl_drv_mutex_lock(wxe_batch_locker_m); + peek = batch->Cleanup(batch->cb_start); while(true) { - while((event = batch->Get()) != NULL) { - erl_drv_mutex_unlock(wxe_batch_locker_m); + while((event = batch->Peek(&peek)) != NULL) { wxeMemEnv *memenv = getMemEnv(event->port); // fprintf(stderr, " Ev %d %lu\r\n", event->op, event->caller); if(event->caller == process || // Callbacks from CB process only @@ -361,8 +334,8 @@ void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process event->op == WXE_CB_DIED || // Event callback process died // Allow connect_cb during CB i.e. msg from wxe_server. (memenv && event->caller == memenv->owner)) { + erl_drv_mutex_unlock(wxe_batch_locker_m); switch(event->op) { - case -1: case WXE_BATCH_END: case WXE_BATCH_BEGIN: case WXE_DEBUG_PING: @@ -373,52 +346,42 @@ void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process memcpy(cb_buff, event->buffer, event->len); } // continue case WXE_CB_DIED: + batch->cb_start = 0; event->Delete(); + erl_drv_mutex_lock(wxe_batch_locker_m); + batch->Strip(); + erl_drv_mutex_unlock(wxe_batch_locker_m); return; case WXE_CB_START: // CB start from now accept message from CB process only process = event->caller; break; default: - size_t start=temp->m_n; + batch->cb_start = peek; // In case of recursive callbacks if(event->op < OPENGL_START) { - // fprintf(stderr, " cb %d \r\n", event->op); wxe_dispatch(*event); } else { gl_dispatch(event->op,event->buffer,event->caller,event->bin); } - if(temp->m_n > start) { - erl_drv_mutex_lock(wxe_batch_locker_m); - // We have recursed dispatch_cb and messages for this - // callback may be saved on temp list move them - // to orig list - for(unsigned int i=start; i < temp->m_n; i++) { - wxeCommand *ev = &temp->m_q[(temp->m_first+i) % temp->m_max]; - if(ev->caller == process) { - batch->Append(ev); - } - } - erl_drv_mutex_unlock(wxe_batch_locker_m); - } break; } event->Delete(); - } else { - // fprintf(stderr, " save %d %lu\r\n", event->op, event->caller); - temp->Append(event); + erl_drv_mutex_lock(wxe_batch_locker_m); + peek = batch->Cleanup(peek); } - erl_drv_mutex_lock(wxe_batch_locker_m); } // sleep until something happens // fprintf(stderr, "%s:%d sleep %d %d\r\n", __FILE__, __LINE__, - // batch->m_n, temp->m_n);fflush(stderr); + // peek, batch->m_n);fflush(stderr); wxe_needs_signal = 1; - while(batch->m_n == 0) { + while(peek >= batch->m_n) { erl_drv_cond_wait(wxe_batch_locker_c, wxe_batch_locker_m); + peek = batch->Cleanup(peek); } wxe_needs_signal = 0; } } + /* Memory handling */ void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) { diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h index d6d3095a0f..fd25296c73 100644 --- a/lib/wx/c_src/wxe_impl.h +++ b/lib/wx/c_src/wxe_impl.h @@ -67,8 +67,8 @@ public: void shutdown(wxeMetaCommand& event); - int dispatch(wxeFifo *, int, int); - void dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process); + int dispatch(wxeFifo *); + void dispatch_cb(wxeFifo * batch, ErlDrvTermData process); void wxe_dispatch(wxeCommand& event); -- cgit v1.2.3 From 3c68f93ff05bad90550407dc1eb316547227bfa7 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 23 Nov 2015 14:56:32 +0100 Subject: ssh: fix dialyzer reported error --- lib/ssh/src/ssh_transport.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index e2d19b9cef..041e86bae1 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1697,7 +1697,7 @@ len_supported(Name, Len) -> crypto:block_encrypt(Name, _Key = <<0:Len>>, _IV = <<0:12/unsigned-unit:8>>, - {"AAD","PT"}) + {<<"AAD">>,"PT"}) end of _ -> true -- cgit v1.2.3 From 49f56f9dc37499b6ebb365d2304eee940d57801d Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Mon, 23 Nov 2015 16:56:47 +0100 Subject: Make abort_if_missing_suites option work in all io modes --- lib/common_test/src/ct_run.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index ae91601f67..97994d8d6f 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -2071,9 +2071,11 @@ final_skip([Skip|Skips], Final) -> final_skip([], Final) -> lists:reverse(Final). +continue(_MakeErrors, true) -> + false; continue([], _) -> true; -continue(_MakeErrors, AbortIfMissingSuites) -> +continue(_MakeErrors, _AbortIfMissingSuites) -> io:nl(), OldGl = group_leader(), case set_group_leader_same_as_shell() of @@ -2101,7 +2103,7 @@ continue(_MakeErrors, AbortIfMissingSuites) -> true end; false -> % no shell process to use - not AbortIfMissingSuites + true end. set_group_leader_same_as_shell() -> -- cgit v1.2.3 From 6b5ea6ecb4eed204496cf196d98e7453df02c6dd Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 24 Nov 2015 11:57:22 +0100 Subject: Clean up code for file:position/2 --- lib/kernel/src/file_io_server.erl | 64 ++++++++++++++++++++++----------------- lib/kernel/test/file_SUITE.erl | 13 ++++++-- 2 files changed, 46 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl index d0ad43afbf..5b2cae6b02 100644 --- a/lib/kernel/src/file_io_server.erl +++ b/lib/kernel/src/file_io_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2015. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -217,23 +217,23 @@ file_request({allocate, Offset, Length}, file_request({pread,At,Sz}, #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) -> case position(Handle, At, Buf) of - {ok,_Offs} -> + {error,_} = Reply -> + {error,Reply,State}; + _ -> case ?PRIM_FILE:read(Handle, Sz) of {ok,Bin} when ReadMode =:= list -> std_reply({ok,binary_to_list(Bin)}, State); Reply -> std_reply(Reply, State) - end; - Reply -> - std_reply(Reply, State) + end end; file_request({pwrite,At,Data}, #state{handle=Handle,buf=Buf}=State) -> case position(Handle, At, Buf) of - {ok,_Offs} -> - std_reply(?PRIM_FILE:write(Handle, Data), State); - Reply -> - std_reply(Reply, State) + {error,_} = Reply -> + {error,Reply,State}; + _ -> + std_reply(?PRIM_FILE:write(Handle, Data), State) end; file_request(datasync, #state{handle=Handle}=State) -> @@ -257,10 +257,10 @@ file_request(close, file_request({position,At}, #state{handle=Handle,buf=Buf}=State) -> case position(Handle, At, Buf) of - {error, _Reason}=Reply -> - {error,Reply,State}; - Reply -> - {reply,Reply,State#state{buf= <<>>}} + {error,_} = Reply -> + {error,Reply,State}; + Reply -> + std_reply(Reply, State) end; file_request(truncate, #state{handle=Handle}=State) -> @@ -268,13 +268,14 @@ file_request(truncate, {error,_Reason}=Reply -> {stop,normal,Reply,State#state{buf= <<>>}}; Reply -> - {reply,Reply,State} + std_reply(Reply, State) end; file_request(Unknown, #state{}=State) -> Reason = {request, Unknown}, {error,{error,Reason},State}. +%% Standard reply and clear buffer std_reply({error,_}=Reply, State) -> {error,Reply,State#state{buf= <<>>}}; std_reply(Reply, State) -> @@ -291,7 +292,7 @@ io_request({put_chars, Enc, Chars}, #state{handle=Handle,buf=Buf}=State) -> case position(Handle, cur, Buf) of {error,_}=Reply -> - {stop,normal,Reply,State#state{buf= <<>>}}; + {stop,normal,Reply,State}; _ -> put_chars(Chars, Enc, State#state{buf= <<>>}) end; @@ -372,23 +373,27 @@ io_request_loop([Request|Tail], %% I/O request put_chars %% put_chars(Chars, latin1, #state{handle=Handle, unic=latin1}=State) -> + NewState = State#state{buf = <<>>}, case ?PRIM_FILE:write(Handle, Chars) of {error,_}=Reply -> - {stop,normal,Reply,State}; + {stop,normal,Reply,NewState}; Reply -> - {reply,Reply,State} + {reply,Reply,NewState} end; put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) -> + NewState = State#state{buf = <<>>}, case unicode:characters_to_binary(Chars,InEncoding,OutEncoding) of Bin when is_binary(Bin) -> case ?PRIM_FILE:write(Handle, Bin) of {error,_}=Reply -> - {stop,normal,Reply,State}; + {stop,normal,Reply,NewState}; Reply -> - {reply,Reply,State} + {reply,Reply,NewState} end; {error,_,_} -> - {stop,normal,{error,{no_translation, InEncoding, OutEncoding}},State} + {stop,normal, + {error,{no_translation, InEncoding, OutEncoding}}, + NewState} end. %% @@ -902,11 +907,14 @@ cbv({utf32,little},_) -> %% Compensates ?PRIM_FILE:position/2 for the number of bytes %% we have buffered - -position(Handle, cur, Buf) -> - position(Handle, {cur, 0}, Buf); -position(Handle, {cur, Offs}, Buf) when is_binary(Buf) -> - ?PRIM_FILE:position(Handle, {cur, Offs-byte_size(Buf)}); -position(Handle, At, _Buf) -> - ?PRIM_FILE:position(Handle, At). - +position(Handle, At, Buf) -> + ?PRIM_FILE:position( + Handle, + case At of + cur -> + {cur, -byte_size(Buf)}; + {cur, Offs} -> + {cur, Offs-byte_size(Buf)}; + _ -> + At + end). diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 2911635db7..e9300bf019 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2015. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -130,7 +130,7 @@ groups() -> [open1, old_modes, new_modes, path_open, close, access, read_write, pread_write, append, open_errors, exclusive]}, - {pos, [], [pos1, pos2]}, + {pos, [], [pos1, pos2, pos3]}, {file_info, [], [file_info_basic_file, file_info_basic_directory, file_info_bad, file_info_times, file_write_file_info]}, @@ -1220,7 +1220,7 @@ pos2(Config) when is_list(Config) -> ok. pos3(suite) -> []; -pos3(doc) -> ["When it does not use raw mode, file:postiion had a bug."]; +pos3(doc) -> ["When it does not use raw mode, file:position had a bug."]; pos3(Config) when is_list(Config) -> ?line Dog = test_server:timetrap(test_server:seconds(5)), ?line RootDir = ?config(data_dir, Config), @@ -1229,8 +1229,15 @@ pos3(Config) when is_list(Config) -> ?line {ok, Fd} = ?FILE_MODULE:open(Name, [read, binary]), ?line {ok, _} = ?FILE_MODULE:read(Fd, 5), ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof, -1}), + %% Here ok had returned =( ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur, -10}), + %% That test is actually questionable since file:position/2 + %% is documented to leave the file position undefined after + %% it has returned an error. But on Posix systems the position + %% is guaranteed to be unchanged after an error return. On e.g + %% Windows there is nothing stated about this in the documentation. + ?line test_server:timetrap_cancel(Dog), ok. -- cgit v1.2.3 From c998b45d3ecf560b40fa92a49658dd476e40e2ae Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 24 Nov 2015 14:33:31 +0100 Subject: wx: Add wxOverlay --- lib/wx/api_gen/wx_gen_cpp.erl | 1 + lib/wx/api_gen/wxapi.conf | 6 ++++ lib/wx/c_src/gen/wxe_derived_dest.h | 8 ++++- lib/wx/c_src/gen/wxe_funcs.cpp | 52 +++++++++++++++++++++++++++ lib/wx/c_src/gen/wxe_macros.h | 8 +++++ lib/wx/examples/demo/ex_canvas.erl | 47 ++++++++++++++++++++++--- lib/wx/src/gen/wxDCOverlay.erl | 70 +++++++++++++++++++++++++++++++++++++ lib/wx/src/gen/wxOverlay.erl | 57 ++++++++++++++++++++++++++++++ lib/wx/src/gen/wxe_debug.hrl | 7 ++++ lib/wx/src/gen/wxe_funcs.hrl | 7 ++++ 10 files changed, 257 insertions(+), 6 deletions(-) create mode 100644 lib/wx/src/gen/wxDCOverlay.erl create mode 100644 lib/wx/src/gen/wxOverlay.erl (limited to 'lib') diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index 5649336b5d..f26aa64b2b 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -1141,6 +1141,7 @@ gen_macros() -> w("#include ~n"), w("#include ~n"), w("#include ~n"), + w("#include ~n"), w("~n~n", []), w("#ifndef wxICON_DEFAULT_BITMAP_TYPE~n",[]), diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index f076323bea..462a4551a9 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -1975,3 +1975,9 @@ {class, wxMouseCaptureLostEvent, wxEvent, [{event,[wxEVT_MOUSE_CAPTURE_LOST]}],[]}. + +{class, wxOverlay, root, [], + ['wxOverlay', '~wxOverlay', 'Reset']}. + +{class, wxDCOverlay, root, [], + ['wxDCOverlay', '~wxDCOverlay', 'Clear']}. diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h index 03d1502c2a..d26273fb50 100644 --- a/lib/wx/c_src/gen/wxe_derived_dest.h +++ b/lib/wx/c_src/gen/wxe_derived_dest.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2008-2014. All Rights Reserved. + * Copyright Ericsson AB 2008-2015. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -787,3 +787,9 @@ class EwxPopupTransientWindow : public wxPopupTransientWindow { }; #endif // wxUSE_POPUPWIN +class EwxDCOverlay : public wxDCOverlay { + public: ~EwxDCOverlay() {((WxeApp *)wxTheApp)->clearPtr(this);}; + EwxDCOverlay(wxOverlay& overlay,wxWindowDC * dc,int x,int y,int width,int height) : wxDCOverlay(overlay,dc,x,y,width,height) {}; + EwxDCOverlay(wxOverlay& overlay,wxWindowDC * dc) : wxDCOverlay(overlay,dc) {}; +}; + diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index 3211664499..9c05ad2cf8 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -31959,6 +31959,56 @@ case wxPopupTransientWindow_Dismiss: { // wxPopupTransientWindow::Dismiss break; } #endif // wxUSE_POPUPWIN +case wxOverlay_new: { // wxOverlay::wxOverlay + wxOverlay * Result = new wxOverlay(); + newPtr((void *) Result, 236, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxOverlay"); + break; +} +case wxOverlay_destruct: { // wxOverlay::~wxOverlay + wxOverlay *This = (wxOverlay *) getPtr(bp,memenv); bp += 4; + if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This); + delete This;} + break; +} +case wxOverlay_Reset: { // wxOverlay::Reset + wxOverlay *This = (wxOverlay *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->Reset(); + break; +} +case wxDCOverlay_new_6: { // wxDCOverlay::wxDCOverlay + wxOverlay *overlay = (wxOverlay *) getPtr(bp,memenv); bp += 4; + wxWindowDC *dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4; + int * x = (int *) bp; bp += 4; + int * y = (int *) bp; bp += 4; + int * width = (int *) bp; bp += 4; + int * height = (int *) bp; bp += 4; + wxDCOverlay * Result = new EwxDCOverlay(*overlay,dc,*x,*y,*width,*height); + newPtr((void *) Result, 237, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxDCOverlay"); + break; +} +case wxDCOverlay_new_2: { // wxDCOverlay::wxDCOverlay + wxOverlay *overlay = (wxOverlay *) getPtr(bp,memenv); bp += 4; + wxWindowDC *dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4; + wxDCOverlay * Result = new EwxDCOverlay(*overlay,dc); + newPtr((void *) Result, 237, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxDCOverlay"); + break; +} +case wxDCOverlay_destruct: { // wxDCOverlay::~wxDCOverlay + wxDCOverlay *This = (wxDCOverlay *) getPtr(bp,memenv); bp += 4; + if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This); + delete This;} + break; +} +case wxDCOverlay_Clear: { // wxDCOverlay::Clear + wxDCOverlay *This = (wxDCOverlay *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->Clear(); + break; +} default: { wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false); error.addAtom("_wxe_error_"); error.addInt((int) Ecmd.op); @@ -32005,6 +32055,8 @@ bool WxeApp::delete_object(void *ptr, wxeRefData *refd) { case 215: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break; case 227: delete (wxLogNull *) ptr; break; case 231: delete (EwxLocale *) ptr; return false; + case 236: delete (wxOverlay *) ptr; break; + case 237: delete (EwxDCOverlay *) ptr; return false; default: delete (wxObject *) ptr; return false; } return true; diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h index 59f9c7054e..5f51ac5f91 100644 --- a/lib/wx/c_src/gen/wxe_macros.h +++ b/lib/wx/c_src/gen/wxe_macros.h @@ -64,6 +64,7 @@ #include #include #include +#include #ifndef wxICON_DEFAULT_BITMAP_TYPE @@ -3411,5 +3412,12 @@ #define wxPopupTransientWindow_destruct 3583 #define wxPopupTransientWindow_Popup 3584 #define wxPopupTransientWindow_Dismiss 3585 +#define wxOverlay_new 3586 +#define wxOverlay_destruct 3587 +#define wxOverlay_Reset 3588 +#define wxDCOverlay_new_6 3589 +#define wxDCOverlay_new_2 3590 +#define wxDCOverlay_destruct 3591 +#define wxDCOverlay_Clear 3592 diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl index 1cbb96de1f..cdc783055c 100644 --- a/lib/wx/examples/demo/ex_canvas.erl +++ b/lib/wx/examples/demo/ex_canvas.erl @@ -35,7 +35,9 @@ parent, config, canvas, - bitmap + bitmap, + overlay, + pos }). start(Config) -> @@ -60,6 +62,10 @@ do_init(Config) -> wxPanel:connect(Canvas, paint, [callback]), wxPanel:connect(Canvas, size), + wxPanel:connect(Canvas, left_down), + wxPanel:connect(Canvas, left_up), + wxPanel:connect(Canvas, motion), + wxPanel:connect(Button, command_button_clicked), %% Add to sizers @@ -78,7 +84,9 @@ do_init(Config) -> Bitmap = wxBitmap:new(erlang:max(W,30),erlang:max(30,H)), {Panel, #state{parent=Panel, config=Config, - canvas = Canvas, bitmap = Bitmap}}. + canvas = Canvas, bitmap = Bitmap, + overlay = wxOverlay:new() + }}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Sync event from callback events, paint event must be handled in callbacks @@ -127,11 +135,39 @@ handle_event(#wx{event = #wxCommand{type = command_button_clicked}}, wxBitmap:destroy(Bmp), {noreply, State}; handle_event(#wx{event = #wxSize{size={W,H}}}, - State = #state{bitmap=Prev}) -> + State = #state{bitmap=Prev, canvas=Canvas}) -> Bitmap = wxBitmap:new(W,H), - draw(State#state.canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end), + draw(Canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end), wxBitmap:destroy(Prev), {noreply, State#state{bitmap = Bitmap}}; + +handle_event(#wx{event = #wxMouse{type=left_down, x=X, y=Y}}, State) -> + {noreply, State#state{pos={X,Y}}}; +handle_event(#wx{event = #wxMouse{type=motion, x=X1, y=Y1}}, + #state{pos=Start, overlay=Overlay, canvas=Canvas} = State) -> + case Start of + undefined -> ignore; + {X0,Y0} -> + DC = wxClientDC:new(Canvas), + DCO = wxDCOverlay:new(Overlay, DC), + wxDCOverlay:clear(DCO), + wxDC:setPen(DC, ?wxLIGHT_GREY_PEN), + wxDC:setBrush(DC, ?wxTRANSPARENT_BRUSH), + wxDC:drawRectangle(DC, {X0,Y0, X1-X0, Y1-Y0}), + wxDCOverlay:destroy(DCO), + wxClientDC:destroy(DC) + end, + {noreply, State}; +handle_event(#wx{event = #wxMouse{type=left_up}}, + #state{overlay=Overlay, canvas=Canvas} = State) -> + DC = wxClientDC:new(Canvas), + DCO = wxDCOverlay:new(Overlay, DC), + wxDCOverlay:clear(DCO), + wxDCOverlay:destroy(DCO), + wxClientDC:destroy(DC), + wxOverlay:reset(Overlay), + {noreply, State#state{pos=undefined}}; + handle_event(Ev = #wx{}, State = #state{}) -> demo:format(State#state.config, "Got Event ~p\n", [Ev]), {noreply, State}. @@ -155,7 +191,8 @@ handle_cast(Msg, State) -> code_change(_, _, State) -> {stop, ignore, State}. -terminate(_Reason, _) -> +terminate(_Reason, #state{overlay=Overlay}) -> + wxOverlay:destroy(Overlay), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/wx/src/gen/wxDCOverlay.erl b/lib/wx/src/gen/wxDCOverlay.erl new file mode 100644 index 0000000000..f98e310ba6 --- /dev/null +++ b/lib/wx/src/gen/wxDCOverlay.erl @@ -0,0 +1,70 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: wxDCOverlay. +%% @type wxDCOverlay(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxDCOverlay). +-include("wxe.hrl"). +-export([clear/1,destroy/1,new/2,new/6]). + +%% inherited exports +-export([parent_class/1]). + +-export_type([wxDCOverlay/0]). +%% @hidden +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxDCOverlay() :: wx:wx_object(). +%% @doc See external documentation. +-spec new(Overlay, Dc) -> wxDCOverlay() when + Overlay::wxOverlay:wxOverlay(), Dc::wxWindowDC:wxWindowDC(). +new(#wx_ref{type=OverlayT,ref=OverlayRef},#wx_ref{type=DcT,ref=DcRef}) -> + ?CLASS(OverlayT,wxOverlay), + ?CLASS(DcT,wxWindowDC), + wxe_util:construct(?wxDCOverlay_new_2, + <>). + +%% @doc See external documentation. +-spec new(Overlay, Dc, X, Y, Width, Height) -> wxDCOverlay() when + Overlay::wxOverlay:wxOverlay(), Dc::wxWindowDC:wxWindowDC(), X::integer(), Y::integer(), Width::integer(), Height::integer(). +new(#wx_ref{type=OverlayT,ref=OverlayRef},#wx_ref{type=DcT,ref=DcRef},X,Y,Width,Height) + when is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height) -> + ?CLASS(OverlayT,wxOverlay), + ?CLASS(DcT,wxWindowDC), + wxe_util:construct(?wxDCOverlay_new_6, + <>). + +%% @doc See external documentation. +-spec clear(This) -> ok when + This::wxDCOverlay(). +clear(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxDCOverlay), + wxe_util:cast(?wxDCOverlay_Clear, + <>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxDCOverlay()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxDCOverlay), + wxe_util:destroy(?wxDCOverlay_destruct,Obj), + ok. diff --git a/lib/wx/src/gen/wxOverlay.erl b/lib/wx/src/gen/wxOverlay.erl new file mode 100644 index 0000000000..7da3ece657 --- /dev/null +++ b/lib/wx/src/gen/wxOverlay.erl @@ -0,0 +1,57 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: wxOverlay. +%% @type wxOverlay(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxOverlay). +-include("wxe.hrl"). +-export([destroy/1,new/0,reset/1]). + +%% inherited exports +-export([parent_class/1]). + +-export_type([wxOverlay/0]). +%% @hidden +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxOverlay() :: wx:wx_object(). +%% @doc See external documentation. +-spec new() -> wxOverlay(). +new() -> + wxe_util:construct(?wxOverlay_new, + <<>>). + +%% @doc See external documentation. +-spec reset(This) -> ok when + This::wxOverlay(). +reset(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxOverlay), + wxe_util:cast(?wxOverlay_Reset, + <>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxOverlay()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxOverlay), + wxe_util:destroy(?wxOverlay_destruct,Obj), + ok. diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl index 2cb73c0fed..6c7602acd3 100644 --- a/lib/wx/src/gen/wxe_debug.hrl +++ b/lib/wx/src/gen/wxe_debug.hrl @@ -3363,6 +3363,13 @@ wxdebug_table() -> {3583, {wxPopupTransientWindow, destruct, 0}}, {3584, {wxPopupTransientWindow, popup, 1}}, {3585, {wxPopupTransientWindow, dismiss, 0}}, + {3586, {wxOverlay, new, 0}}, + {3587, {wxOverlay, destruct, 0}}, + {3588, {wxOverlay, reset, 0}}, + {3589, {wxDCOverlay, new_6, 6}}, + {3590, {wxDCOverlay, new_2, 2}}, + {3591, {wxDCOverlay, destruct, 0}}, + {3592, {wxDCOverlay, clear, 0}}, {-1, {mod, func, -1}} ]. diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl index d8c2ba9171..3a34cd494d 100644 --- a/lib/wx/src/gen/wxe_funcs.hrl +++ b/lib/wx/src/gen/wxe_funcs.hrl @@ -3360,3 +3360,10 @@ -define(wxPopupTransientWindow_destruct, 3583). -define(wxPopupTransientWindow_Popup, 3584). -define(wxPopupTransientWindow_Dismiss, 3585). +-define(wxOverlay_new, 3586). +-define(wxOverlay_destruct, 3587). +-define(wxOverlay_Reset, 3588). +-define(wxDCOverlay_new_6, 3589). +-define(wxDCOverlay_new_2, 3590). +-define(wxDCOverlay_destruct, 3591). +-define(wxDCOverlay_Clear, 3592). -- cgit v1.2.3 From da4a2d7ca19f967da4561f66659346540d6441c9 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Fri, 20 Nov 2015 15:49:30 +0100 Subject: wx: Make wxPostScriptDC optional By default wxUSE_POSTSCRIPT is not enabled on Windows, make it optional, postscript generation doesn't work that good and is probably never used on windows anyway. --- lib/wx/api_gen/wxapi.conf | 2 +- lib/wx/c_src/gen/wxe_derived_dest.h | 2 ++ lib/wx/c_src/gen/wxe_funcs.cpp | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index 462a4551a9..eabbec3297 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -367,7 +367,7 @@ {class,wxMirrorDC, wxDC, [], ['wxMirrorDC', '~wxMirrorDC']}. {class,wxScreenDC, wxDC, [], ['wxScreenDC', '~wxScreenDC']}. -{class,wxPostScriptDC,wxDC,[], +{class,wxPostScriptDC,wxDC,[{ifdef, wxUSE_POSTSCRIPT}], ['wxPostScriptDC','~wxPostScriptDC', {'SetResolution', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]}, {'GetResolution', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]}]}. diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h index d26273fb50..1dcf029244 100644 --- a/lib/wx/c_src/gen/wxe_derived_dest.h +++ b/lib/wx/c_src/gen/wxe_derived_dest.h @@ -86,11 +86,13 @@ class EwxScreenDC : public wxScreenDC { EwxScreenDC() : wxScreenDC() {}; }; +#if wxUSE_POSTSCRIPT class EwxPostScriptDC : public wxPostScriptDC { public: ~EwxPostScriptDC() {((WxeApp *)wxTheApp)->clearPtr(this);}; EwxPostScriptDC(const wxPrintData& printData) : wxPostScriptDC(printData) {}; EwxPostScriptDC() : wxPostScriptDC() {}; }; +#endif // wxUSE_POSTSCRIPT class EwxWindowDC : public wxWindowDC { public: ~EwxWindowDC() {((WxeApp *)wxTheApp)->clearPtr(this);}; diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index 9c05ad2cf8..fd1cedd714 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -5856,6 +5856,7 @@ case wxScreenDC_new: { // wxScreenDC::wxScreenDC rt.addRef(getRef((void *)Result,memenv), "wxScreenDC"); break; } +#if wxUSE_POSTSCRIPT case wxPostScriptDC_new_0: { // wxPostScriptDC::wxPostScriptDC wxPostScriptDC * Result = new EwxPostScriptDC(); newPtr((void *) Result, 4, memenv); @@ -5883,6 +5884,7 @@ case wxPostScriptDC_GetResolution: { // wxPostScriptDC::GetResolution break; } #endif +#endif // wxUSE_POSTSCRIPT #if !wxCHECK_VERSION(2,9,0) case wxWindowDC_new_0: { // wxWindowDC::wxWindowDC wxWindowDC * Result = new EwxWindowDC(); -- cgit v1.2.3 From 617387025b698c7c7b1d102e35234b2c65dda335 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Sun, 22 Nov 2015 19:36:04 +0100 Subject: wx: Add a command queue check after event sent to erlang Some events are callbacks inside wxWidgets so idle processing doesn't take place until operation is completed, for instance move/resize window on Windows. This way we get some response while mouse button is pressed. --- lib/wx/api_gen/wx_extra/wxEvtHandler.c_src | 4 ++++ lib/wx/api_gen/wx_gen_cpp.erl | 5 +++++ lib/wx/c_src/gen/wxe_events.cpp | 5 +++++ lib/wx/c_src/gen/wxe_funcs.cpp | 4 ++++ lib/wx/c_src/wxe_impl.cpp | 4 ++-- 5 files changed, 20 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src index 5e02066309..08fef1c2ff 100644 --- a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src +++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src @@ -42,11 +42,15 @@ case 101: { // wxEvtHandler::Disconnect int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen; if(eventType > 0) { + if(recurse_level > 1) { + delayed_delete->Append(Ecmd.Save()); + } else { bool Result = This->Disconnect((int) *winid,(int) *lastId,eventType, (wxObjectEventFunction)(wxEventFunction) &wxeEvtListener::forward, NULL, Listener); rt.addBool(Result); + } } else { rt.addAtom("badarg"); rt.addAtom("event_type"); diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index f26aa64b2b..ed7b27f3bf 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -1277,6 +1277,11 @@ encode_events(Evs) -> w(" } else {~n"), w(" send_res = rt.send();~n"), w(" if(cb->skip) event->Skip();~n"), + w(" if(app->recurse_level < 1) {~n"), + w(" app->recurse_level++;~n"), + w(" app->dispatch_cmds();~n"), + w(" app->recurse_level--;~n"), + w(" }~n"), w(" };~n"), w(" return send_res;~n"), w(" }~n"). diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp index a532ee985d..4affe2ba53 100644 --- a/lib/wx/c_src/gen/wxe_events.cpp +++ b/lib/wx/c_src/gen/wxe_events.cpp @@ -897,6 +897,11 @@ case 235: {// wxMouseCaptureLostEvent } else { send_res = rt.send(); if(cb->skip) event->Skip(); + if(app->recurse_level < 1) { + app->recurse_level++; + app->dispatch_cmds(); + app->recurse_level--; + } }; return send_res; } diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index fd1cedd714..4025fb1c16 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -113,11 +113,15 @@ case 101: { // wxEvtHandler::Disconnect int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen; if(eventType > 0) { + if(recurse_level > 1) { + delayed_delete->Append(Ecmd.Save()); + } else { bool Result = This->Disconnect((int) *winid,(int) *lastId,eventType, (wxObjectEventFunction)(wxEventFunction) &wxeEvtListener::forward, NULL, Listener); rt.addBool(Result); + } } else { rt.addAtom("badarg"); rt.addAtom("event_type"); diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index f81d0bbbd9..c5bad41573 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -225,9 +225,9 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process) if(driver_monitor_process(port, process, &monitor) == 0) { // Should we be able to handle commands when recursing? probably // fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr); - app->recurse_level++; + app->recurse_level += 2; app->dispatch_cb(wxe_queue, process); - app->recurse_level--; + app->recurse_level -= 2; // fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr); driver_demonitor_process(port, &monitor); } -- cgit v1.2.3 From 5a2bd5648ced26ed5a8ba8009603908f5226538d Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Thu, 26 Mar 2015 13:22:19 +0000 Subject: TLS Dist: Use inet_dist_ options The inet_dist_ options, such as min/max port numbers aren't used with TLS distribution. This commits uses those settings in the same way as they're used in inet_tcp_dist.erl --- lib/ssl/src/ssl_tls_dist_proxy.erl | 62 ++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index 273d3b5521..3a0990e8b6 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -48,6 +48,48 @@ accept(Listen) -> connect(Ip, Port) -> gen_server:call(?MODULE, {connect, Ip, Port}, infinity). + +do_listen(Options) -> + {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of + {ok,N} when is_integer(N) -> + case application:get_env(kernel, + inet_dist_listen_max) of + {ok,M} when is_integer(M) -> + {N,M}; + _ -> + {N,N} + end; + _ -> + {0,0} + end, + do_listen(First, Last, listen_options([{backlog,128}|Options])). + +do_listen(First,Last,_) when First > Last -> + {error,eaddrinuse}; +do_listen(First,Last,Options) -> + case gen_tcp:listen(First, Options) of + {error, eaddrinuse} -> + do_listen(First+1,Last,Options); + Other -> + Other + end. + +listen_options(Opts0) -> + Opts1 = + case application:get_env(kernel, inet_dist_use_interface) of + {ok, Ip} -> + [{ip, Ip} | Opts0]; + _ -> + Opts0 + end, + case application:get_env(kernel, inet_dist_listen_options) of + {ok,ListenOpts} -> + erlang:display({inet_dist_listen_options, ListenOpts}), + ListenOpts ++ Opts1; + _ -> + Opts1 + end. + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -61,16 +103,16 @@ init([]) -> handle_call({listen, Name}, _From, State) -> case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}]) of - {ok, Socket} -> - {ok, World} = gen_tcp:listen(0, [{active, false}, binary, {packet,?PPRE}]), - {ok, TcpAddress} = get_tcp_address(Socket), - {ok, WorldTcpAddress} = get_tcp_address(World), - {_,Port} = WorldTcpAddress#net_address.address, - {ok, Creation} = erl_epmd:register_node(Name, Port), - {reply, {ok, {Socket, TcpAddress, Creation}}, - State#state{listen={Socket, World}}}; - Error -> - {reply, Error, State} + {ok, Socket} -> + {ok, World} = do_listen([{active, false}, binary, {packet,?PPRE}, {reuseaddr, true}]), + {ok, TcpAddress} = get_tcp_address(Socket), + {ok, WorldTcpAddress} = get_tcp_address(World), + {_,Port} = WorldTcpAddress#net_address.address, + {ok, Creation} = erl_epmd:register_node(Name, Port), + {reply, {ok, {Socket, TcpAddress, Creation}}, + State#state{listen={Socket, World}}}; + Error -> + {reply, Error, State} end; handle_call({accept, Listen}, {From, _}, State = #state{listen={_, World}}) -> -- cgit v1.2.3 From 623de2dc934d5fa5ca31ad67d29caf90eb2a1804 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Tue, 17 Nov 2015 12:48:34 +0000 Subject: Test port options for TLS distribution Add test that checks that the options inet_dist_listen_min and inet_dist_listen_max are used when starting a node with TLS distribution. --- lib/ssl/test/ssl_dist_SUITE.erl | 48 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index 72d62b29a7..949740bb90 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -40,7 +40,7 @@ %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- all() -> - [basic, payload, plain_options, plain_verify_options]. + [basic, payload, plain_options, plain_verify_options, listen_port_options]. groups() -> []. @@ -247,6 +247,52 @@ plain_verify_options(Config) when is_list(Config) -> [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end), [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end), + stop_ssl_node(NH1), + stop_ssl_node(NH2), + success(Config). +%%-------------------------------------------------------------------- +listen_port_options() -> + [{doc, "Test specifying listening ports"}]. +listen_port_options(Config) when is_list(Config) -> + %% Start a node, and get the port number it's listening on. + NH1 = start_ssl_node(Config), + Node1 = NH1#node_handle.nodename, + Name1 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node1)), + {ok, NodesPorts} = apply_on_ssl_node(NH1, fun net_adm:names/0), + {Name1, Port1} = lists:keyfind(Name1, 1, NodesPorts), + + %% Now start a second node, configuring it to use the same port + %% number. + PortOpt1 = "-kernel inet_dist_listen_min " ++ integer_to_list(Port1) ++ + " inet_dist_listen_max " ++ integer_to_list(Port1), + + try start_ssl_node([{additional_dist_opts, PortOpt1} | Config]) of + #node_handle{} -> + %% If the node was able to start, it didn't take the port + %% option into account. + exit(unexpected_success) + catch + exit:{accept_failed, timeout} -> + %% The node failed to start, as expected. + ok + end, + + %% Try again, now specifying a high max port. + PortOpt2 = "-kernel inet_dist_listen_min " ++ integer_to_list(Port1) ++ + " inet_dist_listen_max 65535", + NH2 = start_ssl_node([{additional_dist_opts, PortOpt2} | Config]), + Node2 = NH2#node_handle.nodename, + Name2 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node2)), + {ok, NodesPorts2} = apply_on_ssl_node(NH2, fun net_adm:names/0), + {Name2, Port2} = lists:keyfind(Name2, 1, NodesPorts2), + + %% The new port should be higher: + if Port2 > Port1 -> + ok; + true -> + error({port, Port2, not_higher_than, Port1}) + end, + stop_ssl_node(NH1), stop_ssl_node(NH2), success(Config). -- cgit v1.2.3 From 991d3fa399154b6166a4974406fc2bdda02a2668 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Tue, 17 Nov 2015 13:40:54 +0000 Subject: Test socket listen options for TLS distribution Add test that checks that the option inet_dist_listen_options is used when starting a node with TLS distribution. This test was adapted from inet_dist_options_options in erl_distribution_SUITE. --- lib/ssl/src/ssl_tls_dist_proxy.erl | 1 - lib/ssl/test/ssl_dist_SUITE.erl | 64 +++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index 3a0990e8b6..c8f29cee4b 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -84,7 +84,6 @@ listen_options(Opts0) -> end, case application:get_env(kernel, inet_dist_listen_options) of {ok,ListenOpts} -> - erlang:display({inet_dist_listen_options, ListenOpts}), ListenOpts ++ Opts1; _ -> Opts1 diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index 949740bb90..cc644ce6da 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -40,7 +40,8 @@ %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- all() -> - [basic, payload, plain_options, plain_verify_options, listen_port_options]. + [basic, payload, plain_options, plain_verify_options, listen_port_options, + listen_options]. groups() -> []. @@ -293,6 +294,61 @@ listen_port_options(Config) when is_list(Config) -> error({port, Port2, not_higher_than, Port1}) end, + stop_ssl_node(NH1), + stop_ssl_node(NH2), + success(Config). +%%-------------------------------------------------------------------- +listen_options() -> + [{doc, "Test inet_dist_listen_options"}]. +listen_options(Config) when is_list(Config) -> + Prio = 1, + case gen_udp:open(0, [{priority,Prio}]) of + {ok,Socket} -> + case inet:getopts(Socket, [priority]) of + {ok,[{priority,Prio}]} -> + ok = gen_udp:close(Socket), + do_listen_options(Prio, Config); + _ -> + ok = gen_udp:close(Socket), + {skip, + "Can not set priority "++integer_to_list(Prio)++ + " on socket"} + end; + {error,_} -> + {skip, "Can not set priority on socket"} + end. + +do_listen_options(Prio, Config) -> + PriorityString0 = "[{priority,"++integer_to_list(Prio)++"}]", + PriorityString = + case os:cmd("echo [{a,1}]") of + "[{a,1}]"++_ -> + PriorityString0; + _ -> + %% Some shells need quoting of [{}] + "'"++PriorityString0++"'" + end, + + Options = "-kernel inet_dist_listen_options " ++ PriorityString, + + NH1 = start_ssl_node([{additional_dist_opts, Options} | Config]), + NH2 = start_ssl_node([{additional_dist_opts, Options} | Config]), + Node2 = NH2#node_handle.nodename, + + pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end), + + PrioritiesNode1 = + apply_on_ssl_node(NH1, fun get_socket_priorities/0), + PrioritiesNode2 = + apply_on_ssl_node(NH2, fun get_socket_priorities/0), + + Elevated1 = [P || P <- PrioritiesNode1, P =:= Prio], + ?t:format("Elevated1: ~p~n", [Elevated1]), + Elevated2 = [P || P <- PrioritiesNode2, P =:= Prio], + ?t:format("Elevated2: ~p~n", [Elevated2]), + [_|_] = Elevated1, + [_|_] = Elevated2, + stop_ssl_node(NH1), stop_ssl_node(NH2), success(Config). @@ -310,6 +366,12 @@ tstsrvr_format(Fmt, ArgList) -> send_to_tstcntrl(Message) -> send_to_tstsrvr({message, Message}). +get_socket_priorities() -> + [Priority || + {ok,[{priority,Priority}]} <- + [inet:getopts(Port, [priority]) || + Port <- erlang:ports(), + element(2, erlang:port_info(Port, name)) =:= "tcp_inet"]]. %% %% test_server side api -- cgit v1.2.3 From d00d68f96c51cc7f36d2030c7c7c6277adf998f0 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Tue, 17 Nov 2015 14:10:21 +0000 Subject: Test interface listen option for TLS distribution Add test that checks that the option inet_dist_use_interface is used when starting a node with TLS distribution. --- lib/ssl/test/ssl_dist_SUITE.erl | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index cc644ce6da..508a968474 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -41,7 +41,7 @@ %%-------------------------------------------------------------------- all() -> [basic, payload, plain_options, plain_verify_options, listen_port_options, - listen_options]. + listen_options, use_interface]. groups() -> []. @@ -352,6 +352,34 @@ do_listen_options(Prio, Config) -> stop_ssl_node(NH1), stop_ssl_node(NH2), success(Config). +%%-------------------------------------------------------------------- +use_interface() -> + [{doc, "Test inet_dist_use_interface"}]. +use_interface(Config) when is_list(Config) -> + %% Force the node to listen only on the loopback interface. + IpString = "'{127,0,0,1}'", + Options = "-kernel inet_dist_use_interface " ++ IpString, + + %% Start a node, and get the port number it's listening on. + NH1 = start_ssl_node([{additional_dist_opts, Options} | Config]), + Node1 = NH1#node_handle.nodename, + Name = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node1)), + {ok, NodesPorts} = apply_on_ssl_node(NH1, fun net_adm:names/0), + {Name, Port} = lists:keyfind(Name, 1, NodesPorts), + + %% Now find the socket listening on that port, and check its sockname. + Sockets = apply_on_ssl_node( + NH1, + fun() -> + [inet:sockname(P) || + P <- erlang:ports(), + {ok, Port} =:= (catch inet:port(P))] + end), + %% And check that it's actually listening on localhost. + [{ok,{{127,0,0,1},Port}}] = Sockets, + + stop_ssl_node(NH1), + success(Config). %%-------------------------------------------------------------------- %%% Internal functions ----------------------------------------------- -- cgit v1.2.3 From 08585ec49568f6273f51526e40c108abb7480e4d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 25 Nov 2015 15:55:13 +0100 Subject: ssh: added 'pending' in recv_window handling and limit sending --- lib/ssh/src/ssh_connect.hrl | 3 +++ lib/ssh/src/ssh_connection_handler.erl | 27 +++++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl index 6db89c5d80..9f9f3de8fa 100644 --- a/lib/ssh/src/ssh_connect.hrl +++ b/lib/ssh/src/ssh_connect.hrl @@ -248,6 +248,9 @@ local_id, %% local channel id recv_window_size, + recv_window_pending = 0, %% Sum of window size updates that has not + %% yet been sent. This limits the number + %% of sent update msgs. recv_packet_size, recv_close = false, diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 505c6eb181..68062209fc 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -731,13 +731,28 @@ handle_event({adjust_window, ChannelId, Bytes}, StateName, #connection{channel_cache = Cache}} = State0) -> State = case ssh_channel:cache_lookup(Cache, ChannelId) of - #channel{recv_window_size = WinSize, remote_id = Id} = Channel -> - ssh_channel:cache_update(Cache, Channel#channel{recv_window_size = - WinSize + Bytes}), - Msg = ssh_connection:channel_adjust_window_msg(Id, Bytes), + #channel{recv_window_size = WinSize, + recv_window_pending = Pending, + recv_packet_size = PktSize} = Channel + when (WinSize-Bytes) >= 2*PktSize -> + %% The peer can send at least two more *full* packet, no hurry. + ssh_channel:cache_update(Cache, + Channel#channel{recv_window_pending = Pending + Bytes}), + State0; + + #channel{recv_window_size = WinSize, + recv_window_pending = Pending, + remote_id = Id} = Channel -> + %% Now we have to update the window - we can't receive so many more pkts + ssh_channel:cache_update(Cache, + Channel#channel{recv_window_size = + WinSize + Bytes + Pending, + recv_window_pending = 0}), + Msg = ssh_connection:channel_adjust_window_msg(Id, Bytes + Pending), send_replies([{connection_reply, Msg}], State0); - undefined -> - State0 + + undefined -> + State0 end, {next_state, StateName, next_packet(State)}; -- cgit v1.2.3 From 9865cacba44c862af36a5a8d758157bbe5c499e7 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 25 Nov 2015 16:17:24 +0100 Subject: ssh: sftpd callback takes new option 'recv_window_size', defaults to 1000000 --- lib/ssh/src/ssh_sftpd.erl | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl index a6549f1c73..819cba697e 100644 --- a/lib/ssh/src/ssh_sftpd.erl +++ b/lib/ssh/src/ssh_sftpd.erl @@ -30,6 +30,7 @@ -include("ssh.hrl"). -include("ssh_xfer.hrl"). +-include("ssh_connect.hrl"). %% For ?DEFAULT_PACKET_SIZE and ?DEFAULT_WINDOW_SIZE %%-------------------------------------------------------------------- %% External exports @@ -47,6 +48,7 @@ file_handler, % atom() - callback module file_state, % state for the file callback module max_files, % integer >= 0 max no files sent during READDIR + options, % from the subsystem declaration handles % list of open handles %% handle is either {, directory, {Path, unread|eof}} or %% {, file, {Path, IoDevice}} @@ -121,6 +123,7 @@ init(Options) -> MaxLength = proplists:get_value(max_files, Options, 0), Vsn = proplists:get_value(sftpd_vsn, Options, 5), {ok, State#state{cwd = CWD, root = Root, max_files = MaxLength, + options = Options, handles = [], pending = <<>>, xf = #ssh_xfer{vsn = Vsn, ext = []}}}. @@ -164,7 +167,9 @@ handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State) -> %% Description: Handles other messages %%-------------------------------------------------------------------- handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, - #state{xf =Xf} = State) -> + #state{xf = Xf, + options = Options} = State) -> + maybe_increase_recv_window(ConnectionManager, ChannelId, Options), {ok, State#state{xf = Xf#ssh_xfer{cm = ConnectionManager, channel = ChannelId}}}. @@ -934,3 +939,18 @@ rename(Path, Path2, ReqId, State0) -> {Status, FS1} = FileMod:rename(Path, Path2, FS0), State1 = State0#state{file_state = FS1}, send_status(Status, ReqId, State1). + + +maybe_increase_recv_window(ConnectionManager, ChannelId, Options) -> + WantedRecvWindowSize = + proplists:get_value(recv_window_size, Options, 1000000), + NumPkts = WantedRecvWindowSize div ?DEFAULT_PACKET_SIZE, + Increment = NumPkts*?DEFAULT_PACKET_SIZE - ?DEFAULT_WINDOW_SIZE, + + if + Increment > 0 -> + ssh_connection:adjust_window(ConnectionManager, ChannelId, + Increment); + Increment =< 0 -> + do_nothing + end. -- cgit v1.2.3 From 3dd86e73c17631a1e8c12ae4bed8bd320ae66082 Mon Sep 17 00:00:00 2001 From: Roger Lipscombe Date: Wed, 25 Nov 2015 14:26:38 +0000 Subject: Ensure single 'raw' option is handled correctly Add a test to ensure that a single 'raw' option can be passed to ssl:listen correctly. Note: multiple raw options are (incorrectly) handled by inet:listen_options. See http://erlang.org/pipermail/erlang-questions/2014-March/078371.html --- lib/ssl/test/ssl_basic_SUITE.erl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'lib') diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index ecedb89c23..0712764274 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -96,6 +96,7 @@ options_tests() -> [der_input, misc_ssl_options, ssl_options_not_proplist, + raw_ssl_option, socket_options, invalid_inet_get_option, invalid_inet_get_option_not_list, @@ -311,6 +312,14 @@ init_per_testcase(clear_pem_cache, Config) -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), ct:timetrap({seconds, 20}), Config; +init_per_testcase(raw_ssl_option, Config) -> + ct:timetrap({seconds, 5}), + case os:type() of + {unix,linux} -> + Config; + _ -> + {skip, "Raw options are platform-specific"} + end; init_per_testcase(_TestCase, Config) -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), @@ -1135,6 +1144,23 @@ ssl_options_not_proplist(Config) when is_list(Config) -> ssl:connect("twitter.com", 443, [binary, {active, false}, BadOption]). +%%-------------------------------------------------------------------- +raw_ssl_option() -> + [{doc,"Ensure that a single 'raw' option is passed to ssl:listen correctly."}]. + +raw_ssl_option(Config) when is_list(Config) -> + % 'raw' option values are platform-specific; these are the Linux values: + IpProtoTcp = 6, + % Use TCP_KEEPIDLE, because (e.g.) TCP_MAXSEG can't be read back reliably. + TcpKeepIdle = 4, + KeepAliveTimeSecs = 55, + LOptions = [{raw, IpProtoTcp, TcpKeepIdle, <>}], + {ok, LSocket} = ssl:listen(0, LOptions), + % Per http://www.erlang.org/doc/man/inet.html#getopts-2, we have to specify + % exactly which raw option we want, and the size of the buffer. + {ok, [{raw, IpProtoTcp, TcpKeepIdle, <>}]} = ssl:getopts(LSocket, [{raw, IpProtoTcp, TcpKeepIdle, 4}]). + + %%-------------------------------------------------------------------- versions() -> [{doc,"Test API function versions/0"}]. -- cgit v1.2.3 From 5c6ddf14e8264e61225c0bb5cdc79d537f58be3f Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 25 Nov 2015 11:43:20 +0100 Subject: Fix file:pread and :pwrite to use character encoding --- lib/kernel/src/file_io_server.erl | 46 +++++++++++++++++++++++++++++++++------ lib/kernel/test/file_SUITE.erl | 37 ++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl index 5b2cae6b02..9c425d2175 100644 --- a/lib/kernel/src/file_io_server.erl +++ b/lib/kernel/src/file_io_server.erl @@ -214,26 +214,58 @@ file_request({allocate, Offset, Length}, #state{handle = Handle} = State) -> Reply = ?PRIM_FILE:allocate(Handle, Offset, Length), {reply, Reply, State}; +file_request({pread,At,Sz}, State) + when At =:= cur; + At =:= {cur,0} -> + case get_chars(Sz, latin1, State) of + {reply,Reply,NewState} + when is_list(Reply); + is_binary(Reply) -> + {reply,{ok,Reply},NewState}; + {stop,_,Reply,NewState} -> + {error,Reply,NewState}; + Other -> + Other + end; file_request({pread,At,Sz}, - #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) -> + #state{handle=Handle,buf=Buf}=State) -> case position(Handle, At, Buf) of {error,_} = Reply -> {error,Reply,State}; _ -> - case ?PRIM_FILE:read(Handle, Sz) of - {ok,Bin} when ReadMode =:= list -> - std_reply({ok,binary_to_list(Bin)}, State); - Reply -> - std_reply(Reply, State) + case get_chars(Sz, latin1, State#state{buf= <<>>}) of + {reply,Reply,NewState} + when is_list(Reply); + is_binary(Reply) -> + {reply,{ok,Reply},NewState}; + {stop,_,Reply,NewState} -> + {error,Reply,NewState}; + Other -> + Other end end; +file_request({pwrite,At,Data}, + #state{buf= <<>>}=State) + when At =:= cur; + At =:= {cur,0} -> + case put_chars(Data, latin1, State) of + {stop,_,Reply,NewState} -> + {error,Reply,NewState}; + Other -> + Other + end; file_request({pwrite,At,Data}, #state{handle=Handle,buf=Buf}=State) -> case position(Handle, At, Buf) of {error,_} = Reply -> {error,Reply,State}; _ -> - std_reply(?PRIM_FILE:write(Handle, Data), State) + case put_chars(Data, latin1, State) of + {stop,_,Reply,NewState} -> + {error,Reply,NewState}; + Other -> + Other + end end; file_request(datasync, #state{handle=Handle}=State) -> diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index e9300bf019..87d2de4cae 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -79,6 +79,7 @@ -export([interleaved_read_write/1]). +-export([unicode/1]). -export([altname/1]). -export([large_file/1, large_write/1]). @@ -110,7 +111,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [altname, read_write_file, {group, dirs}, + [unicode, altname, read_write_file, {group, dirs}, {group, files}, delete, rename, names, {group, errors}, {group, compression}, {group, links}, copy, delayed_write, read_ahead, segment_read, segment_write, @@ -2631,6 +2632,40 @@ compress_async_crash_loop(N, Path, ExpectedData) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +unicode(Config) when is_list(Config) -> + Dir = ?config(priv_dir, Config), + Name = filename:join(Dir, "data-utf8.txt"), + Txt = lists:seq(128, 255), + D = unicode:characters_to_binary(Txt, latin1, latin1), + {ok,Fd1} = + ?FILE_MODULE:open(Name, [write,read,binary,{encoding,unicode}]), + ok = ?FILE_MODULE:truncate(Fd1), + ok = ?FILE_MODULE:write(Fd1, Txt), + {ok,0} = ?FILE_MODULE:position(Fd1, bof), + {ok,D} = ?FILE_MODULE:read(Fd1, 129), + {ok,0} = ?FILE_MODULE:position(Fd1, bof), + {ok,D1} = ?FILE_MODULE:read(Fd1, 64), + {ok,Pos} = ?FILE_MODULE:position(Fd1, cur), + {ok,D2} = ?FILE_MODULE:pread(Fd1, {cur,0}, 65), + D = <>, + {ok,D1} = ?FILE_MODULE:pread(Fd1, bof, 64), + {ok,Pos} = ?FILE_MODULE:position(Fd1, Pos), + {ok,D2} = ?FILE_MODULE:read(Fd1, 64), + ok = ?FILE_MODULE:close(Fd1), + %% + RawD = unicode:characters_to_binary(Txt, latin1, unicode), + {ok,RawD} = ?FILE_MODULE:read_file(Name), + %% + {ok,Fd2} = ?FILE_MODULE:open(Name, [read,{encoding,unicode}]), + {ok,Txt} = ?FILE_MODULE:read(Fd2, 129), + {Txt1,Txt2} = lists:split(64, Txt), + {ok,Txt2} = ?FILE_MODULE:pread(Fd2, Pos, 65), + {ok,0} = ?FILE_MODULE:position(Fd2, bof), + {ok,Txt1} = ?FILE_MODULE:read(Fd2, 64), + ok = ?FILE_MODULE:close(Fd2). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + altname(doc) -> "Test the file:altname/1 function"; altname(suite) -> -- cgit v1.2.3 From 2be6707c8e900d6d9eb55aa93872e18fa72a1309 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 26 Nov 2015 11:19:38 +0100 Subject: Unify internal error handling --- lib/kernel/src/file_io_server.erl | 55 ++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl index 9c425d2175..9a7975b6c0 100644 --- a/lib/kernel/src/file_io_server.erl +++ b/lib/kernel/src/file_io_server.erl @@ -205,8 +205,8 @@ io_reply(From, ReplyAs, Reply) -> file_request({advise,Offset,Length,Advise}, #state{handle=Handle}=State) -> case ?PRIM_FILE:advise(Handle, Offset, Length, Advise) of - {error,_}=Reply -> - {stop,normal,Reply,State}; + {error,Reason}=Reply -> + {stop,Reason,Reply,State}; Reply -> {reply,Reply,State} end; @@ -222,8 +222,6 @@ file_request({pread,At,Sz}, State) when is_list(Reply); is_binary(Reply) -> {reply,{ok,Reply},NewState}; - {stop,_,Reply,NewState} -> - {error,Reply,NewState}; Other -> Other end; @@ -238,8 +236,6 @@ file_request({pread,At,Sz}, when is_list(Reply); is_binary(Reply) -> {reply,{ok,Reply},NewState}; - {stop,_,Reply,NewState} -> - {error,Reply,NewState}; Other -> Other end @@ -248,44 +244,39 @@ file_request({pwrite,At,Data}, #state{buf= <<>>}=State) when At =:= cur; At =:= {cur,0} -> - case put_chars(Data, latin1, State) of - {stop,_,Reply,NewState} -> - {error,Reply,NewState}; - Other -> - Other - end; + put_chars(Data, latin1, State); file_request({pwrite,At,Data}, #state{handle=Handle,buf=Buf}=State) -> case position(Handle, At, Buf) of {error,_} = Reply -> {error,Reply,State}; _ -> - case put_chars(Data, latin1, State) of - {stop,_,Reply,NewState} -> - {error,Reply,NewState}; - Other -> - Other - end + put_chars(Data, latin1, State) end; file_request(datasync, #state{handle=Handle}=State) -> case ?PRIM_FILE:datasync(Handle) of - {error,_}=Reply -> - {stop,normal,Reply,State}; + {error,Reason}=Reply -> + {stop,Reason,Reply,State}; Reply -> {reply,Reply,State} end; file_request(sync, #state{handle=Handle}=State) -> case ?PRIM_FILE:sync(Handle) of - {error,_}=Reply -> - {stop,normal,Reply,State}; + {error,Reason}=Reply -> + {stop,Reason,Reply,State}; Reply -> {reply,Reply,State} end; file_request(close, #state{handle=Handle}=State) -> - {stop,normal,?PRIM_FILE:close(Handle),State#state{buf= <<>>}}; + case ?PRIM_FILE:close(Handle) of + {error,Reason}=Reply -> + {stop,Reason,Reply,State#state{buf= <<>>}}; + Reply -> + {stop,normal,Reply,State#state{buf= <<>>}} + end; file_request({position,At}, #state{handle=Handle,buf=Buf}=State) -> case position(Handle, At, Buf) of @@ -297,8 +288,8 @@ file_request({position,At}, file_request(truncate, #state{handle=Handle}=State) -> case ?PRIM_FILE:truncate(Handle) of - {error,_Reason}=Reply -> - {stop,normal,Reply,State#state{buf= <<>>}}; + {error,Reason}=Reply -> + {stop,Reason,Reply,State#state{buf= <<>>}}; Reply -> std_reply(Reply, State) end; @@ -323,8 +314,8 @@ io_request({put_chars, Enc, Chars}, io_request({put_chars, Enc, Chars}, #state{handle=Handle,buf=Buf}=State) -> case position(Handle, cur, Buf) of - {error,_}=Reply -> - {stop,normal,Reply,State}; + {error,Reason}=Reply -> + {stop,Reason,Reply,State}; _ -> put_chars(Chars, Enc, State#state{buf= <<>>}) end; @@ -407,8 +398,8 @@ io_request_loop([Request|Tail], put_chars(Chars, latin1, #state{handle=Handle, unic=latin1}=State) -> NewState = State#state{buf = <<>>}, case ?PRIM_FILE:write(Handle, Chars) of - {error,_}=Reply -> - {stop,normal,Reply,NewState}; + {error,Reason}=Reply -> + {stop,Reason,Reply,NewState}; Reply -> {reply,Reply,NewState} end; @@ -417,13 +408,13 @@ put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) -> case unicode:characters_to_binary(Chars,InEncoding,OutEncoding) of Bin when is_binary(Bin) -> case ?PRIM_FILE:write(Handle, Bin) of - {error,_}=Reply -> - {stop,normal,Reply,NewState}; + {error,Reason}=Reply -> + {stop,Reason,Reply,NewState}; Reply -> {reply,Reply,NewState} end; {error,_,_} -> - {stop,normal, + {stop,no_translation, {error,{no_translation, InEncoding, OutEncoding}}, NewState} end. -- cgit v1.2.3 From 9b9d1cfa157134d8b14aaa2de5b36db28cb8b17a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 25 Nov 2015 20:02:36 +0100 Subject: ssh: implemented server side SSH_MSG_KEX_DH_GEX_REQUEST_OLD for putty client --- lib/ssh/src/ssh_connection_handler.erl | 6 ++++++ lib/ssh/src/ssh_transport.erl | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index fcd66b80c0..5b4f6081c1 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -425,6 +425,12 @@ key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg, send_msg(GexGroup, State), {next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})}; +key_exchange(#ssh_msg_kex_dh_gex_request_old{} = Msg, + #state{ssh_params = #ssh{role = server} = Ssh0} = State) -> + {ok, GexGroup, Ssh} = ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0), + send_msg(GexGroup, State), + {next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})}; + key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg, #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> {ok, KexGexInit, Ssh} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0), diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 2b6f0a3cdc..1fbe50e758 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -427,6 +427,32 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min, Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, keyex_info = {Min, Max, NBits} }}; + +handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request_old{n = NBits}, + Ssh0=#ssh{opts=Opts}) -> + %% server + %% + %% This message was in the draft-00 of rfc4419 + %% (https://tools.ietf.org/html/draft-ietf-secsh-dh-group-exchange-00) + %% In later drafts and the rfc is "is used for backward compatibility". + %% Unfortunatly the rfc does not specify how to treat the parameter n + %% if there is no group of that modulus length :( + %% The draft-00 however specifies that n is the "... number of bits + %% the subgroup should have at least". + %% Further, it says that "Servers and clients SHOULD support groups + %% with a modulus length of k bits, where 1024 <= k <= 8192." + %% + Min = NBits, + Max = 8192, + {G, P} = dh_gex_group(Min, NBits, Max, proplists:get_value(dh_gex_groups,Opts)), + {Public, Private} = generate_key(dh, [P,G]), + {SshPacket, Ssh} = + ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0), + {ok, SshPacket, + Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}, + keyex_info = {-1, -1, NBits} % flag for kex_h hash calc + }}; + handle_kex_dh_gex_request(_, _) -> throw({{error,bad_ssh_msg_kex_dh_gex_request}, #ssh_msg_disconnect{ @@ -1286,6 +1312,9 @@ kex_h(SSH, Curve, Key, Q_c, Q_s, K) -> kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> L = if Min==-1; Max==-1 -> + %% flag from 'ssh_msg_kex_dh_gex_request_old' + %% It was like this before that message was supported, + %% why? Ts = [string,string,binary,binary,binary, uint32, mpint,mpint,mpint,mpint,mpint], -- cgit v1.2.3 From ecf301d7dbd173cc18f86026ecf88597b15a7c69 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 26 Nov 2015 10:45:13 +0100 Subject: ssh: Improve group selection Now it chooses the first found if no exact match. --- lib/ssh/src/ssh_transport.erl | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 1fbe50e758..e3ee399b8e 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1378,35 +1378,23 @@ dh_gex_default_groups() -> ?dh_default_groups. dh_gex_group(Min, N, Max, undefined) -> dh_gex_group(Min, N, Max, dh_gex_default_groups()); dh_gex_group(Min, N, Max, Groups) -> - %% First try to find an exact match. If not an exact match, select the largest possible. - {_,Group} = - lists:foldl( - fun(_, {I,G}) when I==N -> - %% If we have an exact match already: use that one - {I,G}; - ({I,G}, _) when I==N -> - %% If we now found an exact match: use that very one - {I,G}; - ({I,G}, {Imax,_Gmax}) when Min=Imax -> % b) {I,G} is larger than current max - %% A group within the limits and better than the one we have - {I,G}; - (_, IGmax) -> - %% Keep the one we have - IGmax - end, {-1,undefined}, Groups), - - case Group of - undefined -> - throw(#ssh_msg_disconnect{ - code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "No possible diffie-hellman-group-exchange group found", - language = ""}); - _ -> - Group + %% Try to find an exact match. If not an exact match, select the first found. + case lists:keyfind(N, 1, Groups) of + {N,Grp} -> + Grp; + false -> + case lists:dropwhile(fun({I,_}) -> I < Min-1 orelse I > Max+1 end, + Groups) of + [{_,Grp}|_] -> + Grp; + [] -> + throw(#ssh_msg_disconnect{ + code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "No possible diffie-hellman-group-exchange group found", + language = ""}) + end end. - generate_key(Algorithm, Args) -> {Public,Private} = crypto:generate_key(Algorithm, Args), {crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}. -- cgit v1.2.3 From 7596e5d97b4154f645eac6152f98c8c28f7ff6f6 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 26 Nov 2015 10:52:48 +0100 Subject: ssh: update existing testcases --- lib/ssh/test/ssh_protocol_SUITE.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index d8e99799e2..2415ceba47 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -333,13 +333,13 @@ no_common_alg_client_disconnects(Config) -> gex_client_init_default_noexact(Config) -> do_gex_client_init(Config, {2000, 3000, 4000}, %% Warning, app knowledege: - ?dh_group15). + ?dh_group14). gex_client_init_default_exact(Config) -> - do_gex_client_init(Config, {2000, 2048, 4000}, + do_gex_client_init(Config, {2000, 3072, 4000}, %% Warning, app knowledege: - ?dh_group14). + ?dh_group15). gex_client_init_option_groups(Config) -> -- cgit v1.2.3 From 9ec50b9817f7cd852cf3380f665ade9f86323283 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 26 Nov 2015 11:46:10 +0100 Subject: ssh: New test cases for SSH_MSG_KEX_DH_GEX_REQUEST_OLD --- lib/ssh/test/ssh_protocol_SUITE.erl | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 2415ceba47..dd0adda2dc 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -60,7 +60,9 @@ groups() -> gex_client_init_default_noexact, gex_client_init_default_exact, gex_client_init_option_groups, - gex_client_init_option_groups_file + gex_client_init_option_groups_file, + gex_client_old_request_exact, + gex_client_old_request_noexact ]} ]. @@ -79,7 +81,9 @@ init_per_testcase(no_common_alg_server_disconnects, Config) -> init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; TC == gex_client_init_default_exact ; TC == gex_client_init_option_groups ; - TC == gex_client_init_option_groups_file -> + TC == gex_client_init_option_groups_file ; + TC == gex_client_old_request_exact ; + TC == gex_client_old_request_noexact -> Opts = case TC of gex_client_init_option_groups -> [{dh_gex_groups, [{2345, 3, 41}]}]; @@ -101,7 +105,9 @@ end_per_testcase(no_common_alg_server_disconnects, Config) -> end_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ; TC == gex_client_init_default_exact ; TC == gex_client_init_option_groups ; - TC == gex_client_init_option_groups_file -> + TC == gex_client_init_option_groups_file ; + TC == gex_client_old_request_exact ; + TC == gex_client_old_request_noexact -> stop_std_daemon(Config); end_per_testcase(_TestCase, Config) -> check_std_daemon_works(Config, ?LINE). @@ -373,6 +379,31 @@ do_gex_client_init(Config, {Min,N,Max}, {_,{G,P}}) -> ] ). +%%%-------------------------------------------------------------------- +gex_client_old_request_exact(Config) -> do_gex_client_init_old(Config, 2048, ?dh_group14). +gex_client_old_request_noexact(Config) -> do_gex_client_init_old(Config, 1000, ?dh_group1). + +do_gex_client_init_old(Config, N, {_,{G,P}}) -> + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {connect, + server_host(Config),server_port(Config), + [{silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}, + {preferred_algorithms,[{kex,['diffie-hellman-group-exchange-sha1']}]} + ]}, + receive_hello, + {send, hello}, + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, #ssh_msg_kex_dh_gex_request_old{n = N}}, + {match, #ssh_msg_kex_dh_gex_group{p=P, g=G, _='_'}, receive_msg} + ] + ). + + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ -- cgit v1.2.3 From ad47d0d5617da6e0d1490d3cd91b3e247e4cdf1a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 26 Nov 2015 11:51:35 +0100 Subject: ssh: vsn.mk updated --- lib/ssh/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 5bb18a656a..762bd9b208 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.1.2 +SSH_VSN = 4.1.3 APP_VSN = "ssh-$(SSH_VSN)" -- cgit v1.2.3 From 23ee0606f06e07755128a583541e63c7bb165182 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Thu, 26 Nov 2015 15:10:36 +0100 Subject: Update release notes --- lib/ssh/doc/src/notes.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'lib') diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index bb111c8e0e..b7e7634637 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,22 @@ notes.xml
+
Ssh 4.1.3 + +
Known Bugs and Problems + + +

+ SSH_MSG_KEX_DH_GEX_REQUEST_OLD implemented to make PuTTY + work with erl server.

+

+ Own Id: OTP-13140

+
+
+
+ +
+
Ssh 4.1.2
Fixed Bugs and Malfunctions -- cgit v1.2.3 From 49014e56350dc942fb950da98075cc781ea3b63a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 26 Nov 2015 15:58:30 +0100 Subject: stdlib: Fix the shell command rp and pretty-printing The shell command 'rp' prints strings as lists of integers when pretty printing of lists is 'false'. --- lib/stdlib/src/shell.erl | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index f215a66812..ce1d9eb0ff 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -999,12 +999,7 @@ local_func(rl, [A], Bs0, _Shell, RT, Lf, Ef) -> {value,list_records(record_defs(RT, listify(Recs))),Bs}; local_func(rp, [A], Bs0, _Shell, RT, Lf, Ef) -> {[V],Bs} = expr_list([A], Bs0, Lf, Ef), - Cs = io_lib_pretty:print(V, ([{column, 1}, - {line_length, columns()}, - {depth, -1}, - {max_chars, ?CHAR_MAX}, - {record_print_fun, record_print_fun(RT)}] - ++ enc())), + Cs = pp(V, _Column=1, _Depth=-1, RT), io:requests([{put_chars, unicode, Cs}, nl]), {value,ok,Bs}; local_func(rr, [A], Bs0, _Shell, RT, Lf, Ef) -> @@ -1397,9 +1392,9 @@ get_history_and_results() -> {History, erlang:min(Results, History)}. pp(V, I, RT) -> - pp(V, I, RT, enc()). + pp(V, I, _Depth=?LINEMAX, RT). -pp(V, I, RT, Enc) -> +pp(V, I, D, RT) -> Strings = case application:get_env(stdlib, shell_strings) of {ok, false} -> @@ -1408,10 +1403,10 @@ pp(V, I, RT, Enc) -> true end, io_lib_pretty:print(V, ([{column, I}, {line_length, columns()}, - {depth, ?LINEMAX}, {max_chars, ?CHAR_MAX}, + {depth, D}, {max_chars, ?CHAR_MAX}, {strings, Strings}, {record_print_fun, record_print_fun(RT)}] - ++ Enc)). + ++ enc())). columns() -> case io:columns() of -- cgit v1.2.3 From 8391c2717200ce001684c53aca30ad64487cd281 Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Wed, 26 Aug 2015 09:57:07 +0300 Subject: inets: SNI to be passed with requests through CONNECT httpc should fill SNI extenstion for HTTPS requests sent through CONNECT tunnel to provide proper access to websites using SNI --- lib/inets/src/http_client/httpc_handler.erl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index e6dcfee818..d1c52dcc78 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1827,11 +1827,13 @@ host_header(_, URI) -> tls_upgrade(#state{status = {ssl_tunnel, #request{settings = - #http_options{ssl = {_, TLSOptions} = SocketType}, - address = Address} = Request}, + #http_options{ssl = {_, TLSOptions0} = SocketType}, + address = {Host, _} = Address} = Request}, session = #session{socket = TCPSocket} = Session0, options = Options} = State) -> + TLSOptions = maybe_add_sni(Host, TLSOptions0), + case ssl:connect(TCPSocket, TLSOptions) of {ok, TLSSocket} -> ClientClose = httpc_request:is_client_closing(Request#request.headers), @@ -1862,6 +1864,15 @@ tls_upgrade(#state{status = {stop, normal, State#state{request = Request}} end. +maybe_add_sni(Host, Options) -> + case http_util:is_hostname(Host) andalso + not lists:keymember(server_name_indication, 1, Options) of + true -> + [{server_name_indication, Host} | Options]; + false -> + Options + end. + %% --------------------------------------------------------------------- %% Session wrappers %% --------------------------------------------------------------------- -- cgit v1.2.3 From c7c27a608e219d7aa2ecd20203632095af94da8a Mon Sep 17 00:00:00 2001 From: Aleksei Magusev Date: Wed, 7 Oct 2015 22:39:35 +0200 Subject: Forbid bytes modifier for unsized part of binary generator This type modifier was missed in 90efeaf21147505b1e8207822e606027f94183cc. --- lib/stdlib/src/erl_lint.erl | 4 ++-- lib/stdlib/test/erl_lint_SUITE.erl | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index a5f0e7dbd3..69eff615b4 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -3189,8 +3189,8 @@ handle_generator(P,E,Vt,Uvt,St0) -> handle_bitstring_gen_pat({bin,_,Segments=[_|_]},St) -> case lists:last(Segments) of {bin_element,Line,{var,_,_},default,Flags} when is_list(Flags) -> - case member(binary, Flags) orelse member(bits, Flags) - orelse member(bitstring, Flags) of + case member(binary, Flags) orelse member(bytes, Flags) + orelse member(bits, Flags) orelse member(bitstring, Flags) of true -> add_error(Line, unsized_binary_in_bin_gen_pattern, St); false -> diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 6c07dc1ec6..c1975b8dae 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -1296,12 +1296,16 @@ unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) -> Ts = [{unsized_binary_in_bin_gen_pattern, <<"t({bc,binary,Bin}) -> << <> || <> <= Bin >>; + t({bc,bytes,Bin}) -> + << <> || <> <= Bin >>; t({bc,bits,Bin}) -> << <> || <> <= Bin >>; t({bc,bitstring,Bin}) -> << <> || <> <= Bin >>; t({lc,binary,Bin}) -> [ {X,Tail} || <> <= Bin ]; + t({lc,bytes,Bin}) -> + [ {X,Tail} || <> <= Bin ]; t({lc,bits,Bin}) -> [ {X,Tail} || <> <= Bin ]; t({lc,bitstring,Bin}) -> @@ -1313,7 +1317,9 @@ unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) -> {6,erl_lint,unsized_binary_in_bin_gen_pattern}, {8,erl_lint,unsized_binary_in_bin_gen_pattern}, {10,erl_lint,unsized_binary_in_bin_gen_pattern}, - {12,erl_lint,unsized_binary_in_bin_gen_pattern}], + {12,erl_lint,unsized_binary_in_bin_gen_pattern}, + {14,erl_lint,unsized_binary_in_bin_gen_pattern}, + {16,erl_lint,unsized_binary_in_bin_gen_pattern}], []}}], [] = run(Config, Ts), ok. -- cgit v1.2.3 From 7096f9228af1cdf98843660560a0d84b48cf766b Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 17 Nov 2015 15:03:14 +0100 Subject: inets: Remove exit that generates an incorrect internal server error --- lib/inets/src/http_server/mod_esi.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl index b9a0797977..6764e2c51e 100644 --- a/lib/inets/src/http_server/mod_esi.erl +++ b/lib/inets/src/http_server/mod_esi.erl @@ -473,13 +473,12 @@ handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) -> {'EXIT', Pid, Reason} when is_pid(Pid) -> ?hdrv("handle_body - exit", [{reason, Reason}]), httpd_response:send_final_chunk(ModData, IsDisableChunkedSend), - exit({mod_esi_linked_process_died, Pid, Reason}) - + done after Timeout -> ?hdrv("handle_body - timeout", []), process_flag(trap_exit,false), httpd_response:send_final_chunk(ModData, IsDisableChunkedSend), - exit({mod_esi_linked_process_timeout, Pid}) + done end. erl_script_timeout(Db) -> -- cgit v1.2.3 From ebbbd714ad2398858b09065bce82830d8affe2a4 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 18 Nov 2015 10:58:22 +0100 Subject: inets: Add warning header in "chunk trailer" when mod_esi callback times out or fails Also remove legacy debug macros and add help function httpd_util:error_log/2 to avoid code duplication. --- lib/inets/src/http_lib/http_chunk.erl | 19 ++++++++-- lib/inets/src/http_lib/http_response.erl | 2 ++ lib/inets/src/http_server/httpd_example.erl | 10 +++++- .../src/http_server/httpd_request_handler.erl | 15 ++------ lib/inets/src/http_server/httpd_response.erl | 27 +++++--------- lib/inets/src/http_server/httpd_util.erl | 16 ++++++++- lib/inets/src/http_server/mod_esi.erl | 42 +++++++++++++++------- lib/inets/test/httpd_1_1.erl | 11 +++++- lib/inets/test/httpd_SUITE.erl | 9 ++++- lib/inets/test/httpd_test_lib.erl | 16 ++++++--- 10 files changed, 112 insertions(+), 55 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl index 9699856bf8..7325f24809 100644 --- a/lib/inets/src/http_lib/http_chunk.erl +++ b/lib/inets/src/http_lib/http_chunk.erl @@ -25,7 +25,7 @@ -include("http_internal.hrl"). %% API --export([decode/3, encode/1, encode_last/0, handle_headers/2]). +-export([decode/3, encode/1, encode_last/0, encode_last/1, handle_headers/2]). %% Callback API - used for example if the chunkedbody is received a %% little at a time on a socket. -export([decode_size/1, ignore_extensions/1, decode_data/1, decode_trailer/1]). @@ -85,6 +85,11 @@ encode(Chunk) when is_list(Chunk)-> encode_last() -> <<$0, ?CR, ?LF, ?CR, ?LF >>. +encode_last([]) -> + encode_last(); +encode_last(Trailers0) -> + Trailers = list_to_binary(encode_trailers(Trailers0)), + <<$0, ?CR, ?LF, Trailers/binary>>. %%------------------------------------------------------------------------- %% handle_headers(HeaderRecord, ChunkedHeaders) -> NewHeaderRecord @@ -276,10 +281,18 @@ decode_trailer(<>, Header, Headers, Body, BodyLength, Rem Body, BodyLength, RemainingSize, TotalMaxHeaderSize); decode_trailer(<>, Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> - decode_trailer(Rest, [Octet | Header], Headers, - Body, BodyLength, RemainingSize - 1, TotalMaxHeaderSize). + decode_trailer(Rest, [Octet | Header], Headers, + Body, BodyLength, remaing_size(RemainingSize, 1), TotalMaxHeaderSize). remaing_size(nolimit, _) -> nolimit; remaing_size(Total, Consumed) -> Total - Consumed. + +encode_trailers(Trailers) -> + encode_trailers(Trailers, ""). + +encode_trailers([], Acc) -> + Acc ++ ?CRLF ++ ?CRLF; +encode_trailers([{Header, Value} | Rest], Acc) -> + encode_trailers(Rest, Header ++ ":" ++ Value ++ ?CRLF ++ Acc). diff --git a/lib/inets/src/http_lib/http_response.erl b/lib/inets/src/http_lib/http_response.erl index d13670700c..42e5dd263d 100644 --- a/lib/inets/src/http_lib/http_response.erl +++ b/lib/inets/src/http_lib/http_response.erl @@ -65,6 +65,8 @@ header_list(Headers) -> %%%======================================================================== fill_headers([], _, Headers) -> Headers; +fill_headers([[]], _, Headers) -> + Headers; fill_headers([[Ch|HeaderFold]|Tail], Folded, Headers) when Ch == $\t; Ch == $\s -> fill_headers(Tail, [HeaderFold|Folded], Headers); diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl index d729affd6d..0222487a4b 100644 --- a/lib/inets/src/http_server/httpd_example.erl +++ b/lib/inets/src/http_server/httpd_example.erl @@ -24,7 +24,7 @@ -export([newformat/3]). %% These are used by the inets test-suite --export([delay/1]). +-export([delay/1, chunk_timeout/3]). print(String) -> @@ -142,3 +142,11 @@ i(F) -> i(F,[]). i(F,A) -> io:format(F ++ "~n",A). sleep(T) -> receive after T -> ok end. + +%% ------------------------------------------------------ + +chunk_timeout(SessionID, _, StrInt) -> + mod_esi:deliver(SessionID, "Tranfer-Encoding:chunked/html\r\n\r\n"), + mod_esi:deliver(SessionID, top("Test chunk encoding timeout")), + timer:sleep(20000), + mod_esi:deliver(SessionID, footer()). diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl index 143d599edb..134576059d 100644 --- a/lib/inets/src/http_server/httpd_request_handler.erl +++ b/lib/inets/src/http_server/httpd_request_handler.erl @@ -630,21 +630,10 @@ decrease(N) when is_integer(N) -> decrease(N) -> N. -error_log(ReasonString, Info) -> +error_log(ReasonString, #mod{config_db = ConfigDB}) -> Error = lists:flatten( io_lib:format("Error reading request: ~s", [ReasonString])), - error_log(mod_log, Info, Error), - error_log(mod_disk_log, Info, Error). - -error_log(Mod, #mod{config_db = ConfigDB} = Info, String) -> - Modules = httpd_util:lookup(ConfigDB, modules, - [mod_get, mod_head, mod_log]), - case lists:member(Mod, Modules) of - true -> - Mod:error_log(Info, String); - _ -> - ok - end. + httpd_util:error_log(ConfigDB, Error). %%-------------------------------------------------------------------- diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl index 71243f525a..c0b5f09faf 100644 --- a/lib/inets/src/http_server/httpd_response.erl +++ b/lib/inets/src/http_server/httpd_response.erl @@ -20,8 +20,8 @@ %% -module(httpd_response). -export([generate_and_send_response/1, send_status/3, send_header/3, - send_body/3, send_chunk/3, send_final_chunk/2, split_header/2, - is_disable_chunked_send/1, cache_headers/2]). + send_body/3, send_chunk/3, send_final_chunk/2, send_final_chunk/3, + split_header/2, is_disable_chunked_send/1, cache_headers/2]). -export([map_status_code/2]). -include_lib("inets/src/inets_app/inets_internal.hrl"). @@ -89,8 +89,7 @@ traverse_modules(ModData,[Module|Rest]) -> "~n Error: ~p" "~n Stack trace: ~p", [Module, T, E, ?STACK()])), - report_error(mod_log, ModData#mod.config_db, String), - report_error(mod_disk_log, ModData#mod.config_db, String), + httpd_util:error_log(ModData#mod.config_db, String), send_status(ModData, 500, none), done end. @@ -245,7 +244,6 @@ send_chunk(_, <<>>, _) -> ok; send_chunk(_, [], _) -> ok; - send_chunk(#mod{http_version = "HTTP/1.1", socket_type = Type, socket = Sock}, Response0, false) -> Response = http_chunk:encode(Response0), @@ -254,10 +252,13 @@ send_chunk(#mod{http_version = "HTTP/1.1", send_chunk(#mod{socket_type = Type, socket = Sock} = _ModData, Response, _) -> httpd_socket:deliver(Type, Sock, Response). +send_final_chunk(Mod, IsDisableChunkedSend) -> + send_final_chunk(Mod, [], IsDisableChunkedSend). + send_final_chunk(#mod{http_version = "HTTP/1.1", - socket_type = Type, socket = Sock}, false) -> - httpd_socket:deliver(Type, Sock, http_chunk:encode_last()); -send_final_chunk(#mod{socket_type = Type, socket = Sock}, _) -> + socket_type = Type, socket = Sock}, Trailers, false) -> + httpd_socket:deliver(Type, Sock, http_chunk:encode_last(Trailers)); +send_final_chunk(#mod{socket_type = Type, socket = Sock}, _, _) -> httpd_socket:close(Type, Sock). is_disable_chunked_send(Db) -> @@ -397,16 +398,6 @@ send_response_old(#mod{socket_type = Type, content_length(Body)-> integer_to_list(httpd_util:flatlength(Body)). -report_error(Mod, ConfigDB, Error) -> - Modules = httpd_util:lookup(ConfigDB, modules, - [mod_get, mod_head, mod_log]), - case lists:member(Mod, Modules) of - true -> - Mod:report_error(ConfigDB, Error); - _ -> - ok - end. - handle_headers([], NewHeaders) -> {ok, NewHeaders}; diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl index 0387d71911..ab43f0b378 100644 --- a/lib/inets/src/http_server/httpd_util.erl +++ b/lib/inets/src/http_server/httpd_util.erl @@ -31,7 +31,7 @@ convert_netscapecookie_date/1, enable_debug/1, valid_options/3, modules_validate/1, module_validate/1, dir_validate/2, file_validate/2, mime_type_validate/1, - mime_types_validate/1, custom_date/0]). + mime_types_validate/1, custom_date/0, error_log/2]). -export([encode_hex/1, decode_hex/1]). -include_lib("kernel/include/file.hrl"). @@ -776,3 +776,17 @@ do_enable_debug([{Level,Modules}|Rest]) ok end, do_enable_debug(Rest). + +error_log(ConfigDb, Error) -> + error_log(mod_log, ConfigDb, Error), + error_log(mod_disk_log, ConfigDb, Error). + +error_log(Mod, ConfigDB, Error) -> + Modules = httpd_util:lookup(ConfigDB, modules, + [mod_get, mod_head, mod_log]), + case lists:member(Mod, Modules) of + true -> + Mod:report_error(ConfigDB, Error); + _ -> + ok + end. diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl index 6764e2c51e..1923411449 100644 --- a/lib/inets/src/http_server/mod_esi.erl +++ b/lib/inets/src/http_server/mod_esi.erl @@ -376,7 +376,6 @@ erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) -> end), Response = deliver_webpage_chunk(ModData, Pid), - process_flag(trap_exit,false), Response. @@ -418,7 +417,6 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) -> ?hdrv("deliver_webpage_chunk - timeout", []), send_headers(ModData, 504, [{"connection", "close"}]), httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket), - process_flag(trap_exit,false), {proceed,[{response, {already_sent, 200, 0}} | ModData#mod.data]} end. @@ -446,7 +444,6 @@ send_headers(ModData, StatusCode, HTTPHeaders) -> ExtraHeaders ++ HTTPHeaders). handle_body(_, #mod{method = "HEAD"} = ModData, _, _, Size, _) -> - process_flag(trap_exit,false), {proceed, [{response, {already_sent, 200, Size}} | ModData#mod.data]}; handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) -> @@ -454,33 +451,54 @@ handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) -> httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend), receive {esi_data, Data} when is_binary(Data) -> - ?hdrt("handle_body - received binary data (esi)", []), handle_body(Pid, ModData, Data, Timeout, Size + byte_size(Data), IsDisableChunkedSend); {esi_data, Data} -> - ?hdrt("handle_body - received data (esi)", []), handle_body(Pid, ModData, Data, Timeout, Size + length(Data), IsDisableChunkedSend); {ok, Data} -> - ?hdrt("handle_body - received data (ok)", []), handle_body(Pid, ModData, Data, Timeout, Size + length(Data), IsDisableChunkedSend); {'EXIT', Pid, normal} when is_pid(Pid) -> - ?hdrt("handle_body - exit:normal", []), httpd_response:send_final_chunk(ModData, IsDisableChunkedSend), {proceed, [{response, {already_sent, 200, Size}} | ModData#mod.data]}; {'EXIT', Pid, Reason} when is_pid(Pid) -> - ?hdrv("handle_body - exit", [{reason, Reason}]), - httpd_response:send_final_chunk(ModData, IsDisableChunkedSend), + Error = lists:flatten(io_lib:format("mod_esi process failed with reason ~p", [Reason])), + httpd_util:error_log(ModData#mod.config_db, Error), + httpd_response:send_final_chunk(ModData, + [{"Warning", "199 inets server - body maybe incomplete, " + "internal server error"}], + IsDisableChunkedSend), done after Timeout -> - ?hdrv("handle_body - timeout", []), - process_flag(trap_exit,false), - httpd_response:send_final_chunk(ModData, IsDisableChunkedSend), + kill_esi_delivery_process(Pid), + httpd_response:send_final_chunk(ModData, [{"Warning", "199 inets server - " + "body maybe incomplete, timed out"}], + IsDisableChunkedSend), done end. +kill_esi_delivery_process(Pid) -> + exit(Pid, kill), + receive + {'EXIT', Pid, killed} -> + %% Clean message queue + receive + {esi_data, _} -> + ok + after 0 -> + ok + end, + receive + {ok, _} -> + ok + after 0 -> + ok + end + end. + + erl_script_timeout(Db) -> httpd_util:lookup(Db, erl_script_timeout, ?DEFAULT_ERL_TIMEOUT). diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl index dd9d21bbfc..db6def9d17 100644 --- a/lib/inets/test/httpd_1_1.erl +++ b/lib/inets/test/httpd_1_1.erl @@ -24,7 +24,7 @@ -include_lib("kernel/include/file.hrl"). -export([host/4, chunked/4, expect/4, range/4, if_test/5, trace/4, - head/4, mod_cgi_chunked_encoding_test/5]). + head/4, mod_cgi_chunked_encoding_test/5, mod_esi_chunk_timeout/4]). %% -define(all_keys_lower_case,true). -ifndef(all_keys_lower_case). @@ -274,6 +274,15 @@ mod_cgi_chunked_encoding_test(Type, Port, Host, Node, [Request| Rest])-> [{statuscode, 200}]), mod_cgi_chunked_encoding_test(Type, Port, Host, Node, Rest). + +mod_esi_chunk_timeout(Type, Port, Host, Node) -> + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example/chunk_timeout?input=20000 HTTP/1.1\r\n" + "Host:"++ Host ++"\r\n" + "\r\n", + [{statuscode, 200}, + {header, "warning"}]). + %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index 9bd6f3636c..1d8a603981 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -117,7 +117,7 @@ groups() -> {htaccess, [], [htaccess_1_1, htaccess_1_0, htaccess_0_9]}, {security, [], [security_1_1, security_1_0]}, %% Skip 0.9 as causes timing issus in test code {http_1_1, [], [host, chunked, expect, cgi, cgi_chunked_encoding_test, - trace, range, if_modified_since] ++ http_head() ++ http_get() ++ load()}, + trace, range, if_modified_since, mod_esi_chunk_timeout] ++ http_head() ++ http_get() ++ load()}, {http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()}, {http_0_9, [], http_head() ++ http_get() ++ load()} ]. @@ -757,6 +757,13 @@ esi(Config) when is_list(Config) -> Config, [{statuscode, 200}, {no_header, "cache-control"}]). %%------------------------------------------------------------------------- +mod_esi_chunk_timeout(Config) when is_list(Config) -> + ok = httpd_1_1:mod_esi_chunk_timeout(?config(type, Config), + ?config(port, Config), + ?config(host, Config), + ?config(node, Config)). + +%%------------------------------------------------------------------------- cgi() -> [{doc, "Test mod_cgi"}]. diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl index a5b836f651..c58966ce10 100644 --- a/lib/inets/test/httpd_test_lib.erl +++ b/lib/inets/test/httpd_test_lib.erl @@ -235,11 +235,17 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _}, _ -> ok end, - do_validate(http_response:header_list(Headers), Options, N, P), - check_body(RequestStr, StatusCode, - Headers#http_response_h.'content-type', - list_to_integer(Headers#http_response_h.'content-length'), - Body). + HList = http_response:header_list(Headers), + do_validate(HList, Options, N, P), + case lists:keysearch("warning", 1, HList) of + {value, _} -> + ok; + _ -> + check_body(RequestStr, StatusCode, + Headers#http_response_h.'content-type', + list_to_integer(Headers#http_response_h.'content-length'), + Body) + end. %-------------------------------------------------------------------- %% Internal functions -- cgit v1.2.3 From cb431af03a56ac195862289da474947c2107cdde Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Mon, 5 Oct 2015 12:35:27 +0200 Subject: [erl_docgen] Update DTD for anno tag --- lib/erl_docgen/priv/dtd/common.dtd | 7 ++++--- lib/erl_docgen/priv/dtd/common.header.dtd | 4 ++-- lib/erl_docgen/priv/dtd/common.refs.dtd | 6 +++--- lib/erl_docgen/vsn.mk | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd index ded16d308f..5297b510ab 100644 --- a/lib/erl_docgen/priv/dtd/common.dtd +++ b/lib/erl_docgen/priv/dtd/common.dtd @@ -25,7 +25,7 @@ + url|marker|anno" > @@ -37,8 +37,9 @@ - + + @@ -64,7 +65,7 @@ - + diff --git a/lib/erl_docgen/priv/dtd/common.header.dtd b/lib/erl_docgen/priv/dtd/common.header.dtd index 71a8662572..eb27dc8f97 100644 --- a/lib/erl_docgen/priv/dtd/common.header.dtd +++ b/lib/erl_docgen/priv/dtd/common.header.dtd @@ -18,8 +18,8 @@ $Id$ --> + prepared?,responsible?,docno?,approved?, + checked?,date?,rev?,file?) > diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd index a59462bb3f..a32c34536d 100644 --- a/lib/erl_docgen/priv/dtd/common.refs.dtd +++ b/lib/erl_docgen/priv/dtd/common.refs.dtd @@ -27,11 +27,12 @@ - + -- cgit v1.2.3 From 39f4c81043c00e2e1284855b07f5181b6ac28841 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Fri, 16 Oct 2015 12:57:24 +0200 Subject: [erl_docgen] Correct DTD for tags anno, fsummary and add an tag i (italic). --- lib/erl_docgen/priv/dtd/cites.dtd | 2 +- lib/erl_docgen/priv/dtd/common.dtd | 15 ++++++++------- lib/erl_docgen/priv/dtd/common.refs.dtd | 11 ++++++----- lib/erl_docgen/priv/dtd/erlref.dtd | 3 ++- lib/erl_docgen/priv/dtd/terms.dtd | 2 +- lib/erl_docgen/src/docgen_edoc_xml_cb.erl | 24 ++++++++++-------------- 6 files changed, 28 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/dtd/cites.dtd b/lib/erl_docgen/priv/dtd/cites.dtd index 73931af009..4558947db0 100644 --- a/lib/erl_docgen/priv/dtd/cites.dtd +++ b/lib/erl_docgen/priv/dtd/cites.dtd @@ -30,7 +30,7 @@ - + diff --git a/lib/erl_docgen/priv/dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd index cfaf3ead3b..0e7467da36 100644 --- a/lib/erl_docgen/priv/dtd/common.dtd +++ b/lib/erl_docgen/priv/dtd/common.dtd @@ -24,13 +24,13 @@ - - - - + + + @@ -38,7 +38,8 @@ - + + @@ -66,12 +67,12 @@ - + - + diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd index a32c34536d..6889e990de 100644 --- a/lib/erl_docgen/priv/dtd/common.refs.dtd +++ b/lib/erl_docgen/priv/dtd/common.refs.dtd @@ -27,15 +27,15 @@ - + - + - + @@ -44,5 +44,6 @@ warning|note|dont|do)*) > - - + + diff --git a/lib/erl_docgen/priv/dtd/erlref.dtd b/lib/erl_docgen/priv/dtd/erlref.dtd index d62e2a5fcb..835407520a 100644 --- a/lib/erl_docgen/priv/dtd/erlref.dtd +++ b/lib/erl_docgen/priv/dtd/erlref.dtd @@ -32,4 +32,5 @@ + clause_i CDATA #IMPLIED + n_vars CDATA #IMPLIED> diff --git a/lib/erl_docgen/priv/dtd/terms.dtd b/lib/erl_docgen/priv/dtd/terms.dtd index fd160b5c02..c2965eb61c 100644 --- a/lib/erl_docgen/priv/dtd/terms.dtd +++ b/lib/erl_docgen/priv/dtd/terms.dtd @@ -30,7 +30,7 @@ - + diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl index 03fc161c5a..0ac7985a48 100644 --- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl +++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2012. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -352,8 +352,8 @@ otp_xmlify_e(#xmlElement{name=code} = E) -> % 4) end; otp_xmlify_e(#xmlElement{name=Tag} = E) % 5a when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5 -> - Content = text_and_a_name_only(E#xmlElement.content), - [E#xmlElement{name=b, content=Content}]; + {Name, Text} = text_and_a_name_only(E#xmlElement.content), + [Name, E#xmlElement{name=b, content=Text}]; otp_xmlify_e(#xmlElement{name=Tag} = E) % 5b-c) when Tag==center; Tag==font -> @@ -1190,17 +1190,13 @@ get_text(#xmlElement{content=[#xmlText{value=Text}]}) -> get_text(#xmlElement{content=[E]}) -> get_text(E). -%% text_and_name_only(Es) -> Ts -text_and_a_name_only([#xmlElement{ - name = a, - attributes = [#xmlAttribute{name=name}]} = Name|Es]) -> - [Name|text_and_a_name_only(Es)]; -text_and_a_name_only([#xmlElement{content = Content}|Es]) -> - text_and_a_name_only(Content) ++ text_and_a_name_only(Es); -text_and_a_name_only([#xmlText{} = E |Es]) -> - [E | text_and_a_name_only(Es)]; -text_and_a_name_only([]) -> - []. +%% text_and_name_only(Es) -> {N, Ts} +text_and_a_name_only(Es) -> + [Name|_] = [Name || + #xmlElement{ + name = a, + attributes = [#xmlAttribute{name=name}]}=Name <- Es], + {Name#xmlElement{content = []}, text_only(Es)}. %% text_only(Es) -> Ts %% Takes a list of xmlElement and xmlText and return a lists of xmlText. -- cgit v1.2.3 From dd521867851c169fbab15465e9d137eb515a5ed5 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Fri, 16 Oct 2015 13:04:33 +0200 Subject: [erl_docgen] Add conversion of the i tag in the XSL specs --- lib/erl_docgen/priv/xsl/db_html.xsl | 5 ++++- lib/erl_docgen/priv/xsl/db_man.xsl | 6 ++++++ lib/erl_docgen/priv/xsl/db_pdf.xsl | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl index f5ddd364d3..c2325fbee9 100644 --- a/lib/erl_docgen/priv/xsl/db_html.xsl +++ b/lib/erl_docgen/priv/xsl/db_html.xsl @@ -990,12 +990,15 @@

- + + + +
diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl index 120bf9880d..5201465e42 100644 --- a/lib/erl_docgen/priv/xsl/db_man.xsl +++ b/lib/erl_docgen/priv/xsl/db_man.xsl @@ -595,6 +595,12 @@ \fR\& + + \fI + + \fR\& + + diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl index 53e202d52c..37a2d55274 100644 --- a/lib/erl_docgen/priv/xsl/db_pdf.xsl +++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl @@ -1186,6 +1186,12 @@ + + + + + + -- cgit v1.2.3 From 03dfbda168896807c75bd396262a3de060a91b13 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 19 Nov 2015 09:53:33 +0100 Subject: [erl_docgen] Allow br in the tag of tagged lists --- lib/erl_docgen/priv/dtd/common.dtd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd index 0e7467da36..a29fc233fa 100644 --- a/lib/erl_docgen/priv/dtd/common.dtd +++ b/lib/erl_docgen/priv/dtd/common.dtd @@ -67,7 +67,7 @@ - + -- cgit v1.2.3 From b185ad94ac37e20c57d24fb0da4b46d923af53eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 30 Nov 2015 13:54:10 +0100 Subject: BER: Fix encoding of empty named BIT STRING Encoding an empty named BIT STRING would fail for BER. Noticed-by: Svilen Ivanov --- lib/asn1/src/asn1rtt_ber.erl | 4 ++++ lib/asn1/test/testPrimStrings.erl | 9 +++++++++ 2 files changed, 13 insertions(+) (limited to 'lib') diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl index 39fa8aaf99..e50b14941c 100644 --- a/lib/asn1/src/asn1rtt_ber.erl +++ b/lib/asn1/src/asn1rtt_ber.erl @@ -739,6 +739,8 @@ encode_named_bit_string([H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> do_encode_named_bit_string(Bits, NamedBitList, TagIn); encode_named_bit_string([{bit,_}|_]=Bits, NamedBitList, TagIn) -> do_encode_named_bit_string(Bits, NamedBitList, TagIn); +encode_named_bit_string([], _NamedBitList, TagIn) -> + encode_unnamed_bit_string(<<>>, TagIn); encode_named_bit_string(Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> encode_unnamed_bit_string(Bits, TagIn). @@ -746,6 +748,8 @@ encode_named_bit_string(C, [H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> do_encode_named_bit_string(C, Bits, NamedBitList, TagIn); encode_named_bit_string(C, [{bit,_}|_]=Bits, NamedBitList, TagIn) -> do_encode_named_bit_string(C, Bits, NamedBitList, TagIn); +encode_named_bit_string(C, [], _NamedBitList, TagIn) -> + encode_unnamed_bit_string(C, <<>>, TagIn); encode_named_bit_string(C, Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> encode_unnamed_bit_string(C, Bits, TagIn). diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index fa778765b1..46793c6bff 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -123,6 +123,7 @@ bit_string(Rules, Opts) -> %% Bs2 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (7)) %%========================================================== + roundtrip('Bs2', []), roundtrip('Bs2', [mo,tu,fr]), bs_roundtrip('Bs2', <<2#0110010:7>>, [mo,tu,fr]), bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]), @@ -131,6 +132,7 @@ bit_string(Rules, Opts) -> %% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7)) %%========================================================== + roundtrip('Bs3', []), roundtrip('Bs3', [mo,tu,fr]), bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), @@ -138,6 +140,13 @@ bit_string(Rules, Opts) -> bs_roundtrip('Bs3', <<2#011001:6>>, [mo,tu,fr]), bs_roundtrip('Bs3', <<2#11:2>>, [su,mo]), + %%========================================================== + %% Bs4 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } + %%========================================================== + + roundtrip('Bs4', []), + roundtrip('Bs4', [mo,tu,fr,sa]), + %%========================================================== %% Bs7 ::= BIT STRING (SIZE (24)) %%========================================================== -- cgit v1.2.3 From 162d8cdb1ee5efc990abe62a55f8cbff94e48351 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 1 Dec 2015 15:05:49 +0100 Subject: crypto: Avoid bug in OpenSSL-0.9.8 for ECB ciphers that make EVP_CIPHER_iv_length() return non-zero value. Seems to be fixed in 0.9.8m. --- lib/crypto/c_src/crypto.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 18aa8f19ed..bb2771163d 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -99,6 +99,10 @@ # define HAVE_CHACHA20_POLY1305 #endif +#if OPENSSL_VERSION_NUMBER <= 0x009080cfL +# define HAVE_ECB_IVEC_BUG +#endif + #if defined(HAVE_EC) #include #include @@ -358,6 +362,11 @@ static ERL_NIF_TERM atom_onbasis; static ERL_NIF_TERM atom_aes_cfb8; static ERL_NIF_TERM atom_aes_cfb128; +#ifdef HAVE_ECB_IVEC_BUG +static ERL_NIF_TERM atom_aes_ecb; +static ERL_NIF_TERM atom_des_ecb; +static ERL_NIF_TERM atom_blowfish_ecb; +#endif static ErlNifResourceType* hmac_context_rtype; struct hmac_context @@ -613,6 +622,11 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) #endif atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8"); atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128"); +#ifdef HAVE_ECB_IVEC_BUG + atom_aes_ecb = enif_make_atom(env, "aes_ecb"); + atom_des_ecb = enif_make_atom(env, "des_ecb"); + atom_blowfish_ecb = enif_make_atom(env, "blowfish_ecb"); +#endif init_digest_types(env); init_cipher_types(env); @@ -1319,6 +1333,12 @@ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM cipher = cipherp->cipher_func(); ivec_size = EVP_CIPHER_iv_length(cipher); +#ifdef HAVE_ECB_IVEC_BUG + if (argv[0] == atom_aes_ecb || argv[0] == atom_blowfish_ecb || + argv[0] == atom_des_ecb) + ivec_size = 0; /* 0.9.8l returns faulty ivec_size */ +#endif + if (text.size % EVP_CIPHER_block_size(cipher) != 0 || (ivec_size == 0 ? argc != 4 : (argc != 5 || -- cgit v1.2.3 From 54204bb039a780e7b8d9295303bf7a4f41744641 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 1 Dec 2015 15:33:09 +0100 Subject: Update appup --- lib/kernel/src/kernel.appup.src | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index f8f4cc1ec2..652f39c092 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -1,7 +1,7 @@ %% -*- erlang -*- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2014. All Rights Reserved. +%% Copyright Ericsson AB 1999-2015. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -17,9 +17,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 + [{<<"3\\.[0-9]+(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 {<<"2\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R16 %% Down to - max one major revision back - [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 + [{<<"3\\.[0-9]+(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 {<<"2\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R16 }. -- cgit v1.2.3 From f0ab82279fa6fc7c91d9b3c193d1890b7c83e39b Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 1 Dec 2015 16:43:08 +0100 Subject: wx: Remove call to disconnect_impl from server The server might wait for the result of a call to disconnect_impl which can now be delayed, that might cause a callback to never be invoked and thus hang the driver thread. To avoid that dispatch the disconnect_impl call from user process instead of server. --- lib/wx/src/wxe_server.erl | 21 ++------------------- lib/wx/src/wxe_util.erl | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 21 deletions(-) (limited to 'lib') diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl index cc253b1143..ae9440f890 100644 --- a/lib/wx/src/wxe_server.erl +++ b/lib/wx/src/wxe_server.erl @@ -352,25 +352,8 @@ handle_disconnect(Object, Evh = #evh{cb=Fun}, From, State0 = #state{users=Users0, cb=Callbacks}) -> #user{events=Evs0} = gb_trees:get(From, Users0), FunId = gb_trees:lookup(Fun, Callbacks), - case find_handler(Evs0, Object, Evh#evh{cb=FunId}) of - [] -> - {reply, false, State0}; - Handlers -> - case disconnect(Object,Handlers) of - #evh{} -> {reply, true, State0}; - Result -> {reply, Result, State0} - end - end. - -disconnect(Object,[Ev|Evs]) -> - try wxEvtHandler:disconnect_impl(Object,Ev) of - true -> Ev; - false -> disconnect(Object, Evs); - Error -> Error - catch _:_ -> - false - end; -disconnect(_, []) -> false. + Handlers = find_handler(Evs0, Object, Evh#evh{cb=FunId}), + {reply, {try_in_order, Handlers}, State0}. find_handler([{Object,Evh}|Evs], Object, Match) -> case match_handler(Match, Evh) of diff --git a/lib/wx/src/wxe_util.erl b/lib/wx/src/wxe_util.erl index 1983e6783a..398ceddd4f 100644 --- a/lib/wx/src/wxe_util.erl +++ b/lib/wx/src/wxe_util.erl @@ -127,8 +127,21 @@ connect_cb(Object,EvData0 = #evh{cb=Callback}) -> disconnect_cb(Object,EvData) -> Server = (wx:get_env())#wx_env.sv, - gen_server:call(Server, {disconnect_cb,Object,EvData}, infinity). - + {try_in_order, Handlers} = + gen_server:call(Server, {disconnect_cb,Object,EvData}, infinity), + disconnect(Object, Handlers). + +disconnect(Object,[Ev|Evs]) -> + try wxEvtHandler:disconnect_impl(Object,Ev) of + true -> true; + false -> disconnect(Object, Evs); + Error -> Error + catch _:_ -> + false + end; +disconnect(_, []) -> false. + + debug_cast(1, Op, _Args, _Port) -> check_previous(), case ets:lookup(wx_debug_info,Op) of -- cgit v1.2.3 From e14b301be3b5593a13e666885ca795e6bee54b5b Mon Sep 17 00:00:00 2001 From: Vipin Nair Date: Fri, 13 Nov 2015 18:51:03 +0530 Subject: Support SSH key callback module options This patch allows extra callback options to be passed to the module implementing the SSH callback module behaviour. A module implementing the SSH key callback API is used to customize the handling of public key. This patch allows extra callback options to be passed to the module implementing the SSH callback module behaviour. The key_cb option has been changed: {key_cb, atom()} -> {key_cb, key_cb()} Where: key_cb() :: atom() | {atom(), list()} The callback options, if specified, is made available to the callback module via the options passed to it under the key 'key_cb_private'. More details and some backgorund is available here[1]. [1]: http://erlang.org/pipermail/erlang-patches/2015-November/004800.html --- lib/ssh/doc/src/ssh.xml | 29 +++++++++++----- lib/ssh/src/ssh.erl | 14 ++++++-- lib/ssh/test/Makefile | 2 ++ lib/ssh/test/ssh_basic_SUITE.erl | 67 +++++++++++++++++++++++++++++++++++-- lib/ssh/test/ssh_key_cb.erl | 45 +++++++++++++++++++++++++ lib/ssh/test/ssh_key_cb_options.erl | 44 ++++++++++++++++++++++++ 6 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 lib/ssh/test/ssh_key_cb.erl create mode 100644 lib/ssh/test/ssh_key_cb_options.erl (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 1e9acf4a99..18bced2d1d 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -85,6 +85,15 @@

atom() - Name of the Erlang module implementing the subsystem using the ssh_channel behavior, see ssh_channel(3)

+ key_cb() = + +

atom() | {atom(), list()}

+

atom() - Name of the erlang module implementing the behaviours + ssh_client_key_api or + ssh_client_key_api as the + case maybe.

+

list() - List of options that can be passed to the callback module.

+
channel_init_args() =

list()

@@ -272,11 +281,13 @@ kex is implicit but public_key is set explicitly.

password, if the password authentication method is attempted.

- + -

Module implementing the behaviour - ssh_client_key_api. - Can be used to customize the handling of public keys. +

Module implementing the behaviour ssh_client_key_api. Can be used to + customize the handling of public keys. If callback options are provided + along with the module name, they are made available to the callback + module via the options passed to it under the key 'key_cb_private'.

@@ -607,11 +618,13 @@ kex is implicit but public_key is set explicitly.

- + -

Module implementing the behaviour - ssh_server_key_api. - Can be used to customize the handling of public keys. +

Module implementing the behaviour ssh_server_key_api. Can be used to + customize the handling of public keys. If callback options are provided + along with the module name, they are made available to the callback + module via the options passed to it under the key 'key_cb_private'.

diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index bb50e436a3..1d29c95229 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -369,8 +369,12 @@ handle_option([{user_passwords, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{pwdfun, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); -handle_option([{key_cb, _} = Opt | Rest], SocketOptions, SshOptions) -> - handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{key_cb, {Module, Options}} | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option({key_cb, Module}), + handle_ssh_priv_option({key_cb_private, Options}) | + SshOptions]); +handle_option([{key_cb, Module} | Rest], SocketOptions, SshOptions) -> + handle_option([{key_cb, {Module, []}} | Rest], SocketOptions, SshOptions); handle_option([{keyboard_interact_fun, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); %%Backwards compatibility @@ -544,6 +548,9 @@ handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,4) -> Opt; handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) -> Opt; +handle_ssh_option({key_cb, {CallbackMod, CallbackOptions}} = Opt) when is_atom(CallbackMod), + is_list(CallbackOptions) -> + Opt; handle_ssh_option({keyboard_interact_fun, Value} = Opt) when is_function(Value,3) -> Opt; handle_ssh_option({compression, Value} = Opt) when is_atom(Value) -> @@ -610,6 +617,9 @@ handle_ssh_option({profile, Value} = Opt) when is_atom(Value) -> handle_ssh_option(Opt) -> throw({error, {eoptions, Opt}}). +handle_ssh_priv_option({key_cb_private, Value} = Opt) when is_list(Value) -> + Opt. + handle_inet_option({active, _} = Opt) -> throw({error, {{eoptions, Opt}, "SSH has built in flow control, " "and active is handled internally, user is not allowed" diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 96c74c6c8a..781a876723 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -47,6 +47,8 @@ MODULES= \ ssh_to_openssh_SUITE \ ssh_upgrade_SUITE \ ssh_test_lib \ + ssh_key_cb \ + ssh_key_cb_options \ ssh_trpt_test_lib \ ssh_echo_server \ ssh_peername_sockname_server \ diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 0a5964c560..d4cb03f2f2 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -54,8 +54,10 @@ send/1, shell/1, shell_no_unicode/1, - shell_unicode_string/1, - ssh_info_print/1 + shell_unicode_string/1, + ssh_info_print/1, + key_callback/1, + key_callback_options/1 ]). %%% Common test callbacks @@ -84,6 +86,7 @@ all() -> {group, ecdsa_sha2_nistp521_key}, {group, dsa_pass_key}, {group, rsa_pass_key}, + {group, key_cb}, {group, internal_error}, daemon_already_started, double_close, @@ -101,6 +104,7 @@ groups() -> {ecdsa_sha2_nistp521_key, [], basic_tests()}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, + {key_cb, [], [key_callback, key_callback_options]}, {internal_error, [], [internal_error]} ]. @@ -180,6 +184,11 @@ init_per_group(dsa_pass_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:setup_dsa_pass_pharse(DataDir, PrivDir, "Password"), [{pass_phrase, {dsa_pass_phrase, "Password"}}| Config]; +init_per_group(key_cb, Config) -> + DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:setup_dsa(DataDir, PrivDir), + Config; init_per_group(internal_error, Config) -> DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), @@ -247,6 +256,10 @@ end_per_group(rsa_pass_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:clean_rsa(PrivDir), Config; +end_per_group(key_cb, Config) -> + PrivDir = ?config(priv_dir, Config), + ssh_test_lib:clean_dsa(PrivDir), + Config; end_per_group(internal_error, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:clean_dsa(PrivDir), @@ -575,6 +588,56 @@ pass_phrase(Config) when is_list(Config) -> {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), ssh:stop_daemon(Pid). +%%-------------------------------------------------------------------- +%%% Test that we can use key callback +key_callback(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + NoPubKeyDir = filename:join(UserDir, "nopubkey"), + file:make_dir(NoPubKeyDir), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + + ConnectOpts = [{silently_accept_hosts, true}, + {user_dir, NoPubKeyDir}, + {user_interaction, false}, + {key_cb, ssh_key_cb}], + + ConnectionRef = ssh_test_lib:connect(Host, Port, ConnectOpts), + + {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + ssh:stop_daemon(Pid). + + +%%-------------------------------------------------------------------- +%%% Test that we can use key callback with callback options +key_callback_options(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system), + UserDir = ?config(priv_dir, Config), + + NoPubKeyDir = filename:join(UserDir, "nopubkey"), + file:make_dir(NoPubKeyDir), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {failfun, fun ssh_test_lib:failfun/2}]), + + {ok, PrivKey} = file:read_file(filename:join(UserDir, "id_dsa")), + + ConnectOpts = [{silently_accept_hosts, true}, + {user_dir, NoPubKeyDir}, + {user_interaction, false}, + {key_cb, {ssh_key_cb_options, [{priv_key, PrivKey}]}}], + + ConnectionRef = ssh_test_lib:connect(Host, Port, ConnectOpts), + + {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + ssh:stop_daemon(Pid). + %%-------------------------------------------------------------------- %%% Test that client does not hang if disconnects due to internal error diff --git a/lib/ssh/test/ssh_key_cb.erl b/lib/ssh/test/ssh_key_cb.erl new file mode 100644 index 0000000000..388ec2ecc1 --- /dev/null +++ b/lib/ssh/test/ssh_key_cb.erl @@ -0,0 +1,45 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- + +%% Note: This module is used by ssh_basic_SUITE + +-module(ssh_key_cb). +-behaviour(ssh_client_key_api). +-compile(export_all). + +add_host_key(_, _, _) -> + ok. + +is_host_key(_, _, _, _) -> + true. + +user_key('ssh-dss', Opts) -> + UserDir = proplists:get_value(user_dir, Opts), + KeyFile = filename:join(filename:dirname(UserDir), "id_dsa"), + {ok, KeyBin} = file:read_file(KeyFile), + [Entry] = public_key:pem_decode(KeyBin), + Key = public_key:pem_entry_decode(Entry), + {ok, Key}; + +user_key(_Alg, _Opt) -> + {error, "Not Supported"}. diff --git a/lib/ssh/test/ssh_key_cb_options.erl b/lib/ssh/test/ssh_key_cb_options.erl new file mode 100644 index 0000000000..afccb34f0f --- /dev/null +++ b/lib/ssh/test/ssh_key_cb_options.erl @@ -0,0 +1,44 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- + +%% Note: This module is used by ssh_basic_SUITE + +-module(ssh_key_cb_options). +-behaviour(ssh_client_key_api). +-compile(export_all). + +add_host_key(_, _, _) -> + ok. + +is_host_key(_, _, _, _) -> + true. + +user_key('ssh-dss', Opts) -> + KeyCbOpts = proplists:get_value(key_cb_private, Opts), + KeyBin = proplists:get_value(priv_key, KeyCbOpts), + [Entry] = public_key:pem_decode(KeyBin), + Key = public_key:pem_entry_decode(Entry), + {ok, Key}; + +user_key(_Alg, _Opt) -> + {error, "Not Supported"}. -- cgit v1.2.3 From d4bf329e7975eca4eab3522766785b3ae624aa8f Mon Sep 17 00:00:00 2001 From: Zandra Date: Thu, 3 Dec 2015 10:11:58 +0100 Subject: rm assertReceive, due to a leftover of a conflict resolution c574bd33c39d91c487c3fcd819226ecfc46c13c8 --- lib/eunit/include/eunit.hrl | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl index 88e9d6c19b..8f678b0290 100644 --- a/lib/eunit/include/eunit.hrl +++ b/lib/eunit/include/eunit.hrl @@ -135,7 +135,6 @@ -define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)). -define(_assertNotException(Class, Term, Expr), ?_test(?assertNotException(Class, Term, Expr))). --define(_assertReceive(Guard, Expr), ?_test(?assertReceive(Guard, Expr))). %% Macros for running operating system commands. (Note that these %% require EUnit to be present at runtime, or at least eunit_lib.) -- cgit v1.2.3 From 97531f2f4dbd4bf7426434792e7e6af6aa8e12ef Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 3 Dec 2015 10:55:37 +0100 Subject: ssl: Prepare for release --- lib/ssl/src/ssl.appup.src | 8 ++++++-- lib/ssl/vsn.mk | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index d100e41930..4c4163d7fd 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,14 +1,18 @@ %% -*- erlang -*- {"%VSN%", [ - {<<"6.0">>, [{load_module, ssl_handshake, soft_purge, soft_purge, []}]}, + {<<"6.0.1">>, [{load_module, ssl_cipher, soft_purge, soft_purge, []}]}, + {<<"6.0">>, [{load_module, ssl_cipher, soft_purge, soft_purge, []}, + {load_module, ssl_handshake, soft_purge, soft_purge, []}]}, {<<"5\\.3\\.[1-7]($|\\..*)">>, [{restart_application, ssl}]}, {<<"5\\.[0-2]($|\\..*)">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, {<<"3\\..*">>, [{restart_application, ssl}]} ], [ - {<<"6.0">>, [{load_module, ssl_handshake, soft_purge, soft_purge, []}]}, + {<<"6.0.1">>, [{load_module, ssl_cipher, soft_purge, soft_purge, []}]}, + {<<"6.0">>, [{load_module, ssl_cipher, soft_purge, soft_purge, []}, + {load_module, ssl_handshake, soft_purge, soft_purge, []}]}, {<<"5\\.3\\.[1-7]($|\\..*)">>, [{restart_application, ssl}]}, {<<"5\\.[0-2]($|\\..*)">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index d5a9a71736..eedf8cf705 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 6.0.1 +SSL_VSN = 6.0.1.1 -- cgit v1.2.3 From ad50eefb67a69d755d46126bf5e436bf85644c8b Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Thu, 3 Dec 2015 11:11:17 +0100 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 19 +++++++++++++++++++ lib/kernel/vsn.mk | 2 +- lib/ssl/doc/src/notes.xml | 17 ++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 6f7f18a8e7..6cc41403c8 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -30,6 +30,25 @@

This document describes the changes made to the Kernel application.

+
Kernel 3.2.0.1 + +
Fixed Bugs and Malfunctions + + +

+ The 'raw' socket option could not be used multiple times + in one call to any e.g gen_tcp function because only one + of the occurrences were used. This bug has been fixed, + and also a small bug concerning propagating error codes + from within inet:setopts/2.

+

+ Own Id: OTP-11482 Aux Id: seq12872

+
+
+
+ +
+
Kernel 3.2
Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index e1d447a465..2ea32065b9 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 3.2 +KERNEL_VSN = 3.2.0.1 diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index fe0606b1a3..14df10b571 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -25,7 +25,22 @@ notes.xml

This document describes the changes made to the SSL application.

-
SSL 6.0.1 +
SSL 6.0.1.1 + +
Fixed Bugs and Malfunctions + + +

+ Gracefully ignore proprietary hash_sign algorithms

+

+ Own Id: OTP-13151

+
+
+
+ +
+ +
SSL 6.0.1
Fixed Bugs and Malfunctions -- cgit v1.2.3 From 78b3b26ece408ca90e3e78873e9a0212777973fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 3 Dec 2015 12:28:23 +0100 Subject: erl_lint_SUITE: Add smoke test of format_error/1 The test suite depended on the compiler to call erl_lint:format_error/1 to ensure that format_error/1 was covered. Unfortunately, though, if format_error/1 crashed the compiler would catch the exception so that the test suite would not notice it. Add a smoke test of format_error/1 that will crash if there is any problem with erl_lint:format_error/1. --- lib/stdlib/test/erl_lint_SUITE.erl | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 0424e2b967..e6c1f4a87a 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -3920,22 +3920,35 @@ run_test2(Conf, Test, Warnings0) -> %% is no reason to produce an output file since we are only %% interested in the errors and warnings. - %% Print warnings, call erl_lint:format_error/1. + %% Print warnings, call erl_lint:format_error/1. (But note that + %% the compiler will ignore failing calls to erl_lint:format_error/1.) compile:file(File, [binary,report|Opts]), case compile:file(File, [binary|Opts]) of - {ok, _M, Code, Ws} when is_binary(Code) -> warnings(File, Ws); - {error, [{File,Es}], []} -> {errors, Es, []}; - {error, [{File,Es}], [{File,Ws}]} -> {error, Es, Ws}; - {error, [{File,Es1},{File,Es2}], []} -> {errors2, Es1, Es2} + {ok, _M, Code, Ws} when is_binary(Code) -> + warnings(File, Ws); + {error, [{File,Es}], []} -> + {errors, call_format_error(Es), []}; + {error, [{File,Es}], [{File,Ws}]} -> + {error, call_format_error(Es), call_format_error(Ws)}; + {error, [{File,Es1},{File,Es2}], []} -> + {errors2, Es1, Es2} end. warnings(File, Ws) -> case lists:append([W || {F, W} <- Ws, F =:= File]) of - [] -> []; - L -> {warnings, L} + [] -> + []; + L -> + {warnings, call_format_error(L)} end. +call_format_error(L) -> + %% Smoke test of format_error/1 to make sure that no crashes + %% slip through. + _ = [Mod:format_error(Term) || {_,Mod,Term} <- L], + L. + fail() -> io:format("failed~n"), ?t:fail(). -- cgit v1.2.3 From b7514ce549fc8865a2200c44fc686d46ed3d9291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 3 Dec 2015 12:53:56 +0100 Subject: Extend erl_lint:format_error/1 to handle bittype mismatches erl_lint:format_error/1 would crash with a function error if conflicting types were given. That was most easily noticed in the shell: Eshell V7.0.3 (abort with ^G) 1> <<0/integer-binary>>. *** ERROR: Shell process terminated! *** Noticed-by: Aleksei Magusev --- lib/stdlib/src/erl_lint.erl | 3 +++ lib/stdlib/test/erl_lint_SUITE.erl | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index c4cb5fdc80..5678e7eebe 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -293,6 +293,9 @@ format_error({variable_in_record_def,V}) -> %% --- binaries --- format_error({undefined_bittype,Type}) -> io_lib:format("bit type ~w undefined", [Type]); +format_error({bittype_mismatch,Val1,Val2,What}) -> + io_lib:format("conflict in ~s specification for bit field: '~p' and '~p'", + [What,Val1,Val2]); format_error(bittype_unit) -> "a bit unit size must not be specified unless a size is specified too"; format_error(illegal_bitsize) -> diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index e6c1f4a87a..5347ccaf1f 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -3604,7 +3604,10 @@ bin_syntax_errors(Config) -> t(<>) -> X; t(<>) -> X; t(<< <<_:8>> >>) -> ok; - t(<<(x ! y):8/integer>>) -> ok. + t(<<(x ! y):8/integer>>) -> ok; + t(X) -> + {<>,<>, + <>,<>}. ">>, [], {error,[{1,erl_lint,illegal_bitsize}, @@ -3613,7 +3616,12 @@ bin_syntax_errors(Config) -> {4,erl_lint,{undefined_bittype,bad_type}}, {5,erl_lint,bittype_unit}, {7,erl_lint,illegal_pattern}, - {8,erl_lint,illegal_pattern}], + {8,erl_lint,illegal_pattern}, + {10,erl_lint,{bittype_mismatch,integer,binary,"type"}}, + {10,erl_lint,{bittype_mismatch,unsigned,signed,"sign"}}, + {11,erl_lint,{bittype_mismatch,8,4,"unit"}}, + {11,erl_lint,{bittype_mismatch,big,little,"endianness"}} + ], [{6,erl_lint,{bad_bitsize,"float"}}]}} ], [] = run(Config, Ts), -- cgit v1.2.3 From 5e95fdff6589432327e38415fc9c5545231e7961 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 13 Nov 2015 21:56:30 +0100 Subject: ssl: Measure elapsed time with erlang:monotonic_time --- lib/ssl/src/dtls_connection.erl | 2 +- lib/ssl/src/ssl_connection.erl | 2 +- lib/ssl/src/ssl_manager.erl | 8 ++++---- lib/ssl/src/ssl_session.erl | 5 +++-- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index 78662e0ea2..153d3fef48 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -145,7 +145,7 @@ init([Role, Host, Port, Socket, {SSLOpts0, _} = Options, User, CbInfo]) -> process_flag(trap_exit, true), State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo), Handshake = ssl_handshake:init_handshake_history(), - TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}), + TimeStamp = erlang:monotonic_time(), try ssl_config:init(SSLOpts0, Role) of {ok, Ref, CertDbHandle, FileRefHandle, CacheHandle, CRLDbInfo, OwnCert, Key, DHParams} -> Session = State0#state.session, diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 12a56df69f..241871dc38 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -974,7 +974,7 @@ ssl_config(Opts, Role, State) -> {ok, Ref, CertDbHandle, FileRefHandle, CacheHandle, CRLDbInfo, OwnCert, Key, DHParams} = ssl_config:init(Opts, Role), Handshake = ssl_handshake:init_handshake_history(), - TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}), + TimeStamp = erlang:monotonic_time(), Session = State#state.session, State#state{tls_handshake_history = Handshake, session = Session#session{own_certificate = OwnCert, diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index cc15678f23..9e535104f7 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -320,7 +320,7 @@ handle_call({unconditionally_clear_pem_cache, _},_, #state{certificate_db = [_,_ handle_cast({register_session, Host, Port, Session}, #state{session_cache_client = Cache, session_cache_cb = CacheCb} = State) -> - TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}), + TimeStamp = erlang:monotonic_time(), NewSession = Session#session{time_stamp = TimeStamp}, case CacheCb:select_session(Cache, {Host, Port}) of @@ -335,7 +335,7 @@ handle_cast({register_session, Host, Port, Session}, handle_cast({register_session, Port, Session}, #state{session_cache_server = Cache, session_cache_cb = CacheCb} = State) -> - TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}), + TimeStamp = erlang:monotonic_time(), NewSession = Session#session{time_stamp = TimeStamp}, CacheCb:update(Cache, {Port, NewSession#session.session_id}, NewSession), {noreply, State}; @@ -502,7 +502,7 @@ invalidate_session(Cache, CacheCb, Key, Session, #state{last_delay_timer = LastT #session{is_resumable = new} -> CacheCb:delete(Cache, Key), {noreply, State}; - _ -> + _ -> %% When a registered session is invalidated we need to wait a while before deleting %% it as there might be pending connections that rightfully needs to look %% up the session data but new connections should not get to use this session. @@ -530,7 +530,7 @@ new_id(Port, Tries, Cache, CacheCb) -> Id = crypto:rand_bytes(?NUM_OF_SESSION_ID_BYTES), case CacheCb:lookup(Cache, {Port, Id}) of undefined -> - Now = calendar:datetime_to_gregorian_seconds({date(), time()}), + Now = erlang:monotonic_time(), %% New sessions can not be set to resumable %% until handshake is compleate and the %% other session values are set. diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index 1849a05314..0ee8a096e9 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -66,8 +66,9 @@ client_id(ClientInfo, Cache, CacheCb, OwnCert) -> %% Description: Check that the session has not expired %%-------------------------------------------------------------------- valid_session(#session{time_stamp = TimeStamp}, LifeTime) -> - Now = calendar:datetime_to_gregorian_seconds({date(), time()}), - Now - TimeStamp < LifeTime. + Now = erlang:monotonic_time(), + Lived = erlang:convert_time_unit(Now-TimeStamp, native, seconds), + Lived < LifeTime. server_id(Port, <<>>, _SslOpts, _Cert, _, _) -> {ssl_manager:new_session_id(Port), undefined}; -- cgit v1.2.3 From 42b8a29dbae1d626f32bc16dd81a129caf741138 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 16 Nov 2015 21:58:36 +0100 Subject: ssl: Add upper limit for session cache If upper limit is reached invalidate the current cache entries, e.i the session lifetime is the max time a session will be keept, but it may be invalidated earlier if the max limit for the table is reached. This will keep the ssl manager process well behaved, not exhusting memeory. Invalidating the entries will incrementally empty the cache to make room for fresh sessions entries. --- lib/ssl/doc/src/ssl_app.xml | 9 +- lib/ssl/src/ssl_manager.erl | 184 +++++++++++++++++++++---------- lib/ssl/src/ssl_session.erl | 4 +- lib/ssl/src/ssl_session_cache.erl | 8 +- lib/ssl/src/ssl_session_cache_api.erl | 1 + lib/ssl/test/ssl_session_cache_SUITE.erl | 152 ++++++++++++++++++------- 6 files changed, 261 insertions(+), 97 deletions(-) (limited to 'lib') diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index 51ce0cedf1..257175a33f 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -66,7 +66,7 @@ to ssl:connect/[2,3] and ssl:listen/2.

]]> -

Lifetime of the session data in seconds.

+

Maximum lifetime of the session data in seconds.

]]>

Name of the session cache callback module that implements @@ -77,6 +77,13 @@

List of extra user-defined arguments to the init function in the session cache callback module. Defaults to [].

+ + ]]> + ]]> +

Limits the growth of the clients/servers session cache, + if the maximum number of sessions is reached, the current cache entries will + be invalidated regardless of their remaining lifetime. Defaults to 1000. +

]]> diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index 9e535104f7..00e95f5c5b 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -46,15 +46,19 @@ -include_lib("kernel/include/file.hrl"). -record(state, { - session_cache_client, - session_cache_server, - session_cache_cb, - session_lifetime, - certificate_db, - session_validation_timer, + session_cache_client :: db_handle(), + session_cache_server :: db_handle(), + session_cache_cb :: atom(), + session_lifetime :: integer(), + certificate_db :: db_handle(), + session_validation_timer :: reference(), last_delay_timer = {undefined, undefined},%% Keep for testing purposes - last_pem_check, - clear_pem_cache + last_pem_check :: erlang:timestamp(), + clear_pem_cache :: integer(), + session_cache_client_max :: integer(), + session_cache_server_max :: integer(), + session_server_invalidator :: undefined | pid(), + session_client_invalidator :: undefined | pid() }). -define(GEN_UNIQUE_ID_MAX_TRIES, 10). @@ -62,7 +66,7 @@ -define(CLEAR_PEM_CACHE, 120000). -define(CLEAN_SESSION_DB, 60000). -define(CLEAN_CERT_DB, 500). --define(NOT_TO_BIG, 10). +-define(DEFAULT_MAX_SESSION_CACHE, 1000). %%==================================================================== %% API @@ -87,7 +91,8 @@ manager_name(dist) -> %%-------------------------------------------------------------------- start_link(Opts) -> DistMangerName = manager_name(normal), - gen_server:start_link({local, DistMangerName}, ?MODULE, [DistMangerName, Opts], []). + gen_server:start_link({local, DistMangerName}, + ?MODULE, [DistMangerName, Opts], []). %%-------------------------------------------------------------------- -spec start_link_dist(list()) -> {ok, pid()} | ignore | {error, term()}. @@ -97,7 +102,8 @@ start_link(Opts) -> %%-------------------------------------------------------------------- start_link_dist(Opts) -> DistMangerName = manager_name(dist), - gen_server:start_link({local, DistMangerName}, ?MODULE, [DistMangerName, Opts], []). + gen_server:start_link({local, DistMangerName}, + ?MODULE, [DistMangerName, Opts], []). %%-------------------------------------------------------------------- -spec connection_init(binary()| {der, list()}, client | server, @@ -167,7 +173,8 @@ new_session_id(Port) -> %% be called by ssl-connection processes. %%-------------------------------------------------------------------- clean_cert_db(Ref, File) -> - erlang:send_after(?CLEAN_CERT_DB, get(ssl_manager), {clean_cert_db, Ref, File}), + erlang:send_after(?CLEAN_CERT_DB, get(ssl_manager), + {clean_cert_db, Ref, File}), ok. %%-------------------------------------------------------------------- @@ -235,10 +242,12 @@ init([Name, Opts]) -> SessionLifeTime = proplists:get_value(session_lifetime, Opts, ?'24H_in_sec'), CertDb = ssl_pkix_db:create(), - ClientSessionCache = CacheCb:init([{role, client} | - proplists:get_value(session_cb_init_args, Opts, [])]), - ServerSessionCache = CacheCb:init([{role, server} | - proplists:get_value(session_cb_init_args, Opts, [])]), + ClientSessionCache = + CacheCb:init([{role, client} | + proplists:get_value(session_cb_init_args, Opts, [])]), + ServerSessionCache = + CacheCb:init([{role, server} | + proplists:get_value(session_cb_init_args, Opts, [])]), Timer = erlang:send_after(SessionLifeTime * 1000 + 5000, self(), validate_sessions), Interval = pem_check_interval(), @@ -250,7 +259,11 @@ init([Name, Opts]) -> session_lifetime = SessionLifeTime, session_validation_timer = Timer, last_pem_check = os:timestamp(), - clear_pem_cache = Interval + clear_pem_cache = Interval, + session_cache_client_max = + max_session_cache_size(session_cache_client_max), + session_cache_server_max = + max_session_cache_size(session_cache_server_max) }}. %%-------------------------------------------------------------------- @@ -267,7 +280,8 @@ init([Name, Opts]) -> handle_call({{connection_init, <<>>, Role, {CRLCb, UserCRLDb}}, _Pid}, _From, #state{certificate_db = [CertDb, FileRefDb, PemChace | _] = Db} = State) -> Ref = make_ref(), - Result = {ok, Ref, CertDb, FileRefDb, PemChace, session_cache(Role, State), {CRLCb, crl_db_info(Db, UserCRLDb)}}, + Result = {ok, Ref, CertDb, FileRefDb, PemChace, + session_cache(Role, State), {CRLCb, crl_db_info(Db, UserCRLDb)}}, {reply, Result, State#state{certificate_db = Db}}; handle_call({{connection_init, Trustedcerts, Role, {CRLCb, UserCRLDb}}, Pid}, _From, @@ -305,7 +319,8 @@ handle_call({{cache_pem,File}, _Pid}, _, _:Reason -> {reply, {error, Reason}, State} end; -handle_call({unconditionally_clear_pem_cache, _},_, #state{certificate_db = [_,_,PemChace | _]} = State) -> +handle_call({unconditionally_clear_pem_cache, _},_, + #state{certificate_db = [_,_,PemChace | _]} = State) -> ssl_pkix_db:clear(PemChace), {reply, ok, State}. @@ -317,27 +332,12 @@ handle_call({unconditionally_clear_pem_cache, _},_, #state{certificate_db = [_,_ %% %% Description: Handling cast messages %%-------------------------------------------------------------------- -handle_cast({register_session, Host, Port, Session}, - #state{session_cache_client = Cache, - session_cache_cb = CacheCb} = State) -> - TimeStamp = erlang:monotonic_time(), - NewSession = Session#session{time_stamp = TimeStamp}, - - case CacheCb:select_session(Cache, {Host, Port}) of - no_session -> - CacheCb:update(Cache, {{Host, Port}, - NewSession#session.session_id}, NewSession); - Sessions -> - register_unique_session(Sessions, NewSession, CacheCb, Cache, {Host, Port}) - end, +handle_cast({register_session, Host, Port, Session}, State0) -> + State = ssl_client_register_session(Host, Port, Session, State0), {noreply, State}; -handle_cast({register_session, Port, Session}, - #state{session_cache_server = Cache, - session_cache_cb = CacheCb} = State) -> - TimeStamp = erlang:monotonic_time(), - NewSession = Session#session{time_stamp = TimeStamp}, - CacheCb:update(Cache, {Port, NewSession#session.session_id}, NewSession), +handle_cast({register_session, Port, Session}, State0) -> + State = server_register_session(Port, Session, State0), {noreply, State}; handle_cast({invalidate_session, Host, Port, @@ -411,10 +411,10 @@ handle_info({clean_cert_db, Ref, File}, end, {noreply, State}; -handle_info({'EXIT', _, _}, State) -> - %% Session validator died!! Do we need to take any action? - %% maybe error log - {noreply, State}; +handle_info({'EXIT', Pid, _}, #state{session_client_invalidator = Pid} = State) -> + {noreply, State#state{session_client_invalidator = undefined}}; +handle_info({'EXIT', Pid, _}, #state{session_server_invalidator = Pid} = State) -> + {noreply, State#state{session_server_invalidator = undefined}}; handle_info(_Info, State) -> {noreply, State}. @@ -495,23 +495,39 @@ delay_time() -> ?CLEAN_SESSION_DB end. -invalidate_session(Cache, CacheCb, Key, Session, #state{last_delay_timer = LastTimer} = State) -> +max_session_cache_size(CacheType) -> + case application:get_env(ssl, CacheType) of + {ok, Size} when is_integer(Size) -> + Size; + _ -> + ?DEFAULT_MAX_SESSION_CACHE + end. + +invalidate_session(Cache, CacheCb, Key, Session, State) -> case CacheCb:lookup(Cache, Key) of undefined -> %% Session is already invalidated {noreply, State}; #session{is_resumable = new} -> CacheCb:delete(Cache, Key), {noreply, State}; - _ -> - %% When a registered session is invalidated we need to wait a while before deleting - %% it as there might be pending connections that rightfully needs to look - %% up the session data but new connections should not get to use this session. - CacheCb:update(Cache, Key, Session#session{is_resumable = false}), - TRef = - erlang:send_after(delay_time(), self(), {delayed_clean_session, Key, Cache}), - {noreply, State#state{last_delay_timer = last_delay_timer(Key, TRef, LastTimer)}} + _ -> + delayed_invalidate_session(CacheCb, Cache, Key, Session, State) end. +delayed_invalidate_session(CacheCb, Cache, Key, Session, + #state{last_delay_timer = LastTimer} = State) -> + %% When a registered session is invalidated we need to + %% wait a while before deleting it as there might be + %% pending connections that rightfully needs to look up + %% the session data but new connections should not get to + %% use this session. + CacheCb:update(Cache, Key, Session#session{is_resumable = false}), + TRef = + erlang:send_after(delay_time(), self(), + {delayed_clean_session, Key, Cache}), + {noreply, State#state{last_delay_timer = + last_delay_timer(Key, TRef, LastTimer)}}. + last_delay_timer({{_,_},_}, TRef, {LastServer, _}) -> {LastServer, TRef}; last_delay_timer({_,_}, TRef, {_, LastClient}) -> @@ -535,7 +551,7 @@ new_id(Port, Tries, Cache, CacheCb) -> %% until handshake is compleate and the %% other session values are set. CacheCb:update(Cache, {Port, Id}, #session{session_id = Id, - is_resumable = false, + is_resumable = new, time_stamp = Now}), Id; _ -> @@ -557,15 +573,62 @@ clean_cert_db(Ref, CertDb, RefDb, PemCache, File) -> ok end. +ssl_client_register_session(Host, Port, Session, #state{session_cache_client = Cache, + session_cache_cb = CacheCb, + session_cache_client_max = Max, + session_client_invalidator = Pid0} = State) -> + TimeStamp = erlang:monotonic_time(), + NewSession = Session#session{time_stamp = TimeStamp}, + + case CacheCb:select_session(Cache, {Host, Port}) of + no_session -> + Pid = do_register_session({{Host, Port}, + NewSession#session.session_id}, + NewSession, Max, Pid0, Cache, CacheCb), + State#state{session_client_invalidator = Pid}; + Sessions -> + register_unique_session(Sessions, NewSession, {Host, Port}, State) + end. + +server_register_session(Port, Session, #state{session_cache_server_max = Max, + session_cache_server = Cache, + session_cache_cb = CacheCb, + session_server_invalidator = Pid0} = State) -> + TimeStamp = erlang:monotonic_time(), + NewSession = Session#session{time_stamp = TimeStamp}, + Pid = do_register_session({Port, NewSession#session.session_id}, + NewSession, Max, Pid0, Cache, CacheCb), + State#state{session_server_invalidator = Pid}. + +do_register_session(Key, Session, Max, Pid, Cache, CacheCb) -> + try CacheCb:size(Cache) of + N when N > Max -> + invalidate_session_cache(Pid, CacheCb, Cache); + _ -> + CacheCb:update(Cache, Key, Session), + Pid + catch + error:undef -> + CacheCb:update(Cache, Key, Session), + Pid + end. + + %% Do not let dumb clients create a gigantic session table %% for itself creating big delays at connection time. -register_unique_session(Sessions, Session, CacheCb, Cache, PartialKey) -> +register_unique_session(Sessions, Session, PartialKey, + #state{session_cache_client_max = Max, + session_cache_client = Cache, + session_cache_cb = CacheCb, + session_client_invalidator = Pid0} = State) -> case exists_equivalent(Session , Sessions) of true -> - ok; + State; false -> - CacheCb:update(Cache, {PartialKey, - Session#session.session_id}, Session) + Pid = do_register_session({PartialKey, + Session#session.session_id}, + Session, Max, Pid0, Cache, CacheCb), + State#state{session_client_invalidator = Pid} end. exists_equivalent(_, []) -> @@ -620,7 +683,8 @@ pem_check_interval() -> end. is_before_checkpoint(Time, CheckPoint) -> - calendar:datetime_to_gregorian_seconds(calendar:now_to_datetime(CheckPoint)) - + calendar:datetime_to_gregorian_seconds( + calendar:now_to_datetime(CheckPoint)) - calendar:datetime_to_gregorian_seconds(Time) > 0. add_trusted_certs(Pid, Trustedcerts, Db) -> @@ -641,3 +705,9 @@ crl_db_info([_,_,_,Local], {internal, Info}) -> crl_db_info(_, UserCRLDb) -> UserCRLDb. +%% Only start a session invalidator if there is not +%% one already active +invalidate_session_cache(undefined, CacheCb, Cache) -> + start_session_validator(Cache, CacheCb, {invalidate_before, erlang:monotonic_time()}); +invalidate_session_cache(Pid, _CacheCb, _Cache) -> + Pid. diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index 0ee8a096e9..2b24bff5ff 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -61,10 +61,12 @@ client_id(ClientInfo, Cache, CacheCb, OwnCert) -> SessionId end. --spec valid_session(#session{}, seconds()) -> boolean(). +-spec valid_session(#session{}, seconds() | {invalidate_before, integer()}) -> boolean(). %% %% Description: Check that the session has not expired %%-------------------------------------------------------------------- +valid_session(#session{time_stamp = TimeStamp}, {invalidate_before, Before}) -> + TimeStamp > Before; valid_session(#session{time_stamp = TimeStamp}, LifeTime) -> Now = erlang:monotonic_time(), Lived = erlang:convert_time_unit(Now-TimeStamp, native, seconds), diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl index cfc48cd935..9585e613e6 100644 --- a/lib/ssl/src/ssl_session_cache.erl +++ b/lib/ssl/src/ssl_session_cache.erl @@ -27,7 +27,7 @@ -include("ssl_internal.hrl"). -export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3, - select_session/2]). + select_session/2, size/1]). %%-------------------------------------------------------------------- %% Description: Return table reference. Called by ssl_manager process. @@ -85,6 +85,12 @@ select_session(Cache, PartialKey) -> ets:select(Cache, [{{{PartialKey,'_'}, '$1'},[],['$1']}]). +%%-------------------------------------------------------------------- +%% Description: Returns the cache size +%%-------------------------------------------------------------------- +size(Cache) -> + ets:info(Cache, size). + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/ssl_session_cache_api.erl b/lib/ssl/src/ssl_session_cache_api.erl index 536b52c44b..8f62c25be5 100644 --- a/lib/ssl/src/ssl_session_cache_api.erl +++ b/lib/ssl/src/ssl_session_cache_api.erl @@ -33,3 +33,4 @@ -callback delete(db_handle(), key()) -> any(). -callback foldl(fun(), term(), db_handle()) -> term(). -callback select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}]. +-callback size(db_handle()) -> integer(). diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl index 924898f6fa..85345c814f 100644 --- a/lib/ssl/test/ssl_session_cache_SUITE.erl +++ b/lib/ssl/test/ssl_session_cache_SUITE.erl @@ -31,6 +31,7 @@ -define(SLEEP, 500). -define(TIMEOUT, 60000). -define(LONG_TIMEOUT, 600000). +-define(MAX_TABLE_SIZE, 5). -behaviour(ssl_session_cache_api). @@ -46,7 +47,9 @@ all() -> [session_cleanup, session_cache_process_list, session_cache_process_mnesia, - client_unique_session]. + client_unique_session, + max_table_size + ]. groups() -> []. @@ -92,7 +95,17 @@ init_per_testcase(session_cleanup, Config) -> Config; init_per_testcase(client_unique_session, Config) -> - ct:timetrap({seconds, 20}), + ct:timetrap({seconds, 40}), + Config; + +init_per_testcase(max_table_size, Config) -> + ssl:stop(), + application:load(ssl), + application:set_env(ssl, session_cache_server_max, ?MAX_TABLE_SIZE), + application:set_env(ssl, session_cache_client_max, ?MAX_TABLE_SIZE), + application:set_env(ssl, session_delay_cleanup_time, ?DELAY), + ssl:start(), + ct:timetrap({seconds, 40}), Config. init_customized_session_cache(Type, Config) -> @@ -122,6 +135,10 @@ end_per_testcase(session_cleanup, Config) -> application:unset_env(ssl, session_delay_cleanup_time), application:unset_env(ssl, session_lifetime), end_per_testcase(default_action, Config); +end_per_testcase(max_table_size, Config) -> + application:unset_env(ssl, session_cach_server_max), + application:unset_env(ssl, session_cach_client_max), + end_per_testcase(default_action, Config); end_per_testcase(Case, Config) when Case == session_cache_process_list; Case == session_cache_process_mnesia -> ets:delete(ssl_test), @@ -148,7 +165,7 @@ client_unique_session(Config) when is_list(Config) -> {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), LastClient = clients_start(Server, - ClientNode, Hostname, Port, ClientOpts, 20), + ClientNode, Hostname, Port, ClientOpts, client_unique_session, 20), receive {LastClient, {ok, _}} -> ok @@ -157,7 +174,8 @@ client_unique_session(Config) when is_list(Config) -> [_, _,_, _, Prop] = StatusInfo, State = ssl_test_lib:state(Prop), ClientCache = element(2, State), - 1 = ets:info(ClientCache, size), + + 1 = ssl_session_cache:size(ClientCache), ssl_test_lib:close(Server, 500), ssl_test_lib:close(LastClient). @@ -223,35 +241,7 @@ session_cleanup(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). -check_timer(Timer) -> - case erlang:read_timer(Timer) of - false -> - {status, _, _, _} = sys:get_status(whereis(ssl_manager)), - timer:sleep(?SLEEP), - {status, _, _, _} = sys:get_status(whereis(ssl_manager)), - ok; - Int -> - ct:sleep(Int), - check_timer(Timer) - end. -get_delay_timers() -> - {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), - [_, _,_, _, Prop] = StatusInfo, - State = ssl_test_lib:state(Prop), - case element(8, State) of - {undefined, undefined} -> - ct:sleep(?SLEEP), - get_delay_timers(); - {undefined, _} -> - ct:sleep(?SLEEP), - get_delay_timers(); - {_, undefined} -> - ct:sleep(?SLEEP), - get_delay_timers(); - DelayTimers -> - DelayTimers - end. %%-------------------------------------------------------------------- session_cache_process_list() -> [{doc,"Test reuse of sessions (short handshake)"}]. @@ -263,6 +253,42 @@ session_cache_process_mnesia() -> session_cache_process_mnesia(Config) when is_list(Config) -> session_cache_process(mnesia,Config). +%%-------------------------------------------------------------------- + +max_table_size() -> + [{doc,"Test max limit on session table"}]. +max_table_size(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {tcp_options, [{active, false}]}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + LastClient = clients_start(Server, + ClientNode, Hostname, Port, ClientOpts, max_table_size, 20), + receive + {LastClient, {ok, _}} -> + ok + end, + ct:sleep(1000), + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = ssl_test_lib:state(Prop), + ClientCache = element(2, State), + ServerCache = element(3, State), + N = ssl_session_cache:size(ServerCache), + M = ssl_session_cache:size(ClientCache), + ct:pal("~p",[{N, M}]), + ssl_test_lib:close(Server, 500), + ssl_test_lib:close(LastClient), + true = N =< ?MAX_TABLE_SIZE, + true = M =< ?MAX_TABLE_SIZE. + %%-------------------------------------------------------------------- %%% Session cache API callbacks %%-------------------------------------------------------------------- @@ -403,21 +429,73 @@ session_cache_process(_Type,Config) when is_list(Config) -> ssl_basic_SUITE:reuse_session(Config). -clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, 0) -> +clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, Test, 0) -> %% Make sure session is registered ct:sleep(?SLEEP * 2), ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {mfa, {?MODULE, connection_info_result, []}}, - {from, self()}, {options, ClientOpts}]); -clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N) -> + {from, self()}, {options, test_copts(Test, 0, ClientOpts)}]); +clients_start(Server, ClientNode, Hostname, Port, ClientOpts, Test, N) -> spawn_link(ssl_test_lib, start_client, [[{node, ClientNode}, {port, Port}, {host, Hostname}, {mfa, {ssl_test_lib, no_result, []}}, - {from, self()}, {options, ClientOpts}]]), + {from, self()}, {options, test_copts(Test, N, ClientOpts)}]]), Server ! listen, - clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N-1). + wait_for_server(), + clients_start(Server, ClientNode, Hostname, Port, ClientOpts, Test, N-1). connection_info_result(Socket) -> ssl:connection_information(Socket, [protocol, cipher_suite]). + +check_timer(Timer) -> + case erlang:read_timer(Timer) of + false -> + {status, _, _, _} = sys:get_status(whereis(ssl_manager)), + timer:sleep(?SLEEP), + {status, _, _, _} = sys:get_status(whereis(ssl_manager)), + ok; + Int -> + ct:sleep(Int), + check_timer(Timer) + end. + +get_delay_timers() -> + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = ssl_test_lib:state(Prop), + case element(8, State) of + {undefined, undefined} -> + ct:sleep(?SLEEP), + get_delay_timers(); + {undefined, _} -> + ct:sleep(?SLEEP), + get_delay_timers(); + {_, undefined} -> + ct:sleep(?SLEEP), + get_delay_timers(); + DelayTimers -> + DelayTimers + end. + +wait_for_server() -> + ct:sleep(100). + + +test_copts(_, 0, ClientOpts) -> + ClientOpts; +test_copts(max_table_size, N, ClientOpts) -> + Version = tls_record:highest_protocol_version([]), + CipherSuites = %%lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), +[ Y|| Y = {Alg,_, _, _} <- lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), Alg =/= ecdhe_ecdsa, Alg =/= ecdh_ecdsa, Alg =/= ecdh_rsa, Alg =/= ecdhe_rsa, Alg =/= dhe_dss, Alg =/= dss], + case length(CipherSuites) of + M when M >= N -> + Cipher = lists:nth(N, CipherSuites), + ct:pal("~p",[Cipher]), + [{ciphers, [Cipher]} | ClientOpts]; + _ -> + ClientOpts + end; +test_copts(_, _, ClientOpts) -> + ClientOpts. -- cgit v1.2.3 From 80483dcb40c382e38405204370dfac7a8b6513aa Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 3 Dec 2015 14:42:09 +0100 Subject: wx: Fix some function specifications --- lib/wx/api_gen/gl_gen_erl.erl | 12 ++++++-- lib/wx/src/gen/gl.erl | 72 +++++++++++++++++++++++-------------------- lib/wx/src/gen/glu.erl | 8 +++-- 3 files changed, 53 insertions(+), 39 deletions(-) (limited to 'lib') diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl index 20406a8d05..84e9600bc0 100644 --- a/lib/wx/api_gen/gl_gen_erl.erl +++ b/lib/wx/api_gen/gl_gen_erl.erl @@ -226,10 +226,14 @@ gen_types(Where) -> w("-type clamp() :: float(). %% 0.0..1.0~n", []), w("-type offset() :: non_neg_integer(). %% Offset in memory block~n", []) end, - w("-type matrix() :: {float(),float(),float(),float(),~n", []), + w("-type matrix12() :: {float(),float(),float(),float(),~n", []), + w(" float(),float(),float(),float(),~n", []), + w(" float(),float(),float(),float()}.~n", []), + w("-type matrix16() :: {float(),float(),float(),float(),~n", []), w(" float(),float(),float(),float(),~n", []), w(" float(),float(),float(),float(),~n", []), w(" float(),float(),float(),float()}.~n", []), + w("-type matrix() :: matrix12() | matrix16().~n", []), w("-type mem() :: binary() | tuple(). %% Memory block~n", []), ok. @@ -480,10 +484,12 @@ doc_arg_type2(T=#type{single=true}) -> doc_arg_type3(T); doc_arg_type2(T=#type{single=undefined}) -> doc_arg_type3(T); -doc_arg_type2(T=#type{single={tuple,undefined}}) -> - "{" ++ doc_arg_type3(T) ++ "}"; +doc_arg_type2(_T=#type{single={tuple,undefined}}) -> + "tuple()"; doc_arg_type2(#type{base=float, single={tuple,16}}) -> "matrix()"; +doc_arg_type2(#type{base=string, single=list}) -> + "iolist()"; doc_arg_type2(T=#type{single={tuple,Sz}}) -> "{" ++ args(fun doc_arg_type3/1, ",", lists:duplicate(Sz,T)) ++ "}"; doc_arg_type2(T=#type{single=list}) -> diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl index 58cdb59aa2..bedd4e9cca 100644 --- a/lib/wx/src/gen/gl.erl +++ b/lib/wx/src/gen/gl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -53,10 +53,14 @@ -type enum() :: non_neg_integer(). %% See wx/include/gl.hrl -type clamp() :: float(). %% 0.0..1.0 -type offset() :: non_neg_integer(). %% Offset in memory block --type matrix() :: {float(),float(),float(),float(), +-type matrix12() :: {float(),float(),float(),float(), + float(),float(),float(),float(), + float(),float(),float(),float()}. +-type matrix16() :: {float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float()}. +-type matrix() :: matrix12() | matrix16(). -type mem() :: binary() | tuple(). %% Memory block -export([clearIndex/1,clearColor/4,clear/1,indexMask/1,colorMask/4,alphaFunc/2, @@ -4289,14 +4293,14 @@ lighti(Light,Pname,Param) -> %% @doc %% See {@link lightf/3} --spec lightfv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {float()}. +-spec lightfv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: tuple(). lightfv(Light,Pname,Params) -> cast(5207, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link lightf/3} --spec lightiv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {integer()}. +-spec lightiv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: tuple(). lightiv(Light,Pname,Params) -> cast(5208, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -4460,14 +4464,14 @@ lightModeli(Pname,Param) -> %% @doc %% See {@link lightModelf/2} --spec lightModelfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}. +-spec lightModelfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). lightModelfv(Pname,Params) -> cast(5213, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). %% @doc %% See {@link lightModelf/2} --spec lightModeliv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}. +-spec lightModeliv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). lightModeliv(Pname,Params) -> cast(5214, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -4547,14 +4551,14 @@ materiali(Face,Pname,Param) -> %% @doc %% See {@link materialf/3} --spec materialfv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {float()}. +-spec materialfv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: tuple(). materialfv(Face,Pname,Params) -> cast(5217, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link materialf/3} --spec materialiv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {integer()}. +-spec materialiv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: tuple(). materialiv(Face,Pname,Params) -> cast(5218, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -5890,21 +5894,21 @@ texGeni(Coord,Pname,Param) -> %% @doc %% See {@link texGend/3} --spec texGendv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}. +-spec texGendv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple(). texGendv(Coord,Pname,Params) -> cast(5246, <> ||C <- tuple_to_list(Params)>>)/binary>>). %% @doc %% See {@link texGend/3} --spec texGenfv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}. +-spec texGenfv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple(). texGenfv(Coord,Pname,Params) -> cast(5247, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link texGend/3} --spec texGeniv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texGeniv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple(). texGeniv(Coord,Pname,Params) -> cast(5248, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -6123,14 +6127,14 @@ texEnvi(Target,Pname,Param) -> %% replacement. The default value is `?GL_FALSE'. %% %% See external documentation. --spec texEnvfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}. +-spec texEnvfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texEnvfv(Target,Pname,Params) -> cast(5254, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link texEnvfv/3} --spec texEnviv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texEnviv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texEnviv(Target,Pname,Params) -> cast(5255, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -6455,14 +6459,14 @@ texParameteri(Target,Pname,Param) -> %% @doc %% See {@link texParameterf/3} --spec texParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}. +-spec texParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameterfv(Target,Pname,Params) -> cast(5260, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link texParameterf/3} --spec texParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameteriv(Target,Pname,Params) -> cast(5261, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -7609,14 +7613,14 @@ fogi(Pname,Param) -> %% @doc %% See {@link fogf/2} --spec fogfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}. +-spec fogfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). fogfv(Pname,Params) -> cast(5306, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). %% @doc %% See {@link fogf/2} --spec fogiv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}. +-spec fogiv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). fogiv(Pname,Params) -> cast(5307, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -8522,24 +8526,24 @@ convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) -> %% image were replicated. %% %% See external documentation. --spec convolutionParameterf(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}. +-spec convolutionParameterf(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). convolutionParameterf(Target,Pname,Params) -> cast(5339, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @equiv convolutionParameterf(Target,Pname,Params) --spec convolutionParameterfv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {float()}}. +-spec convolutionParameterfv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: tuple()}. convolutionParameterfv(Target,Pname,{Params}) -> convolutionParameterf(Target,Pname,Params). %% @doc %% See {@link convolutionParameterf/3} --spec convolutionParameteri(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec convolutionParameteri(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). convolutionParameteri(Target,Pname,Params) -> cast(5340, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @equiv convolutionParameteri(Target,Pname,Params) --spec convolutionParameteriv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {integer()}}. +-spec convolutionParameteriv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: tuple()}. convolutionParameteriv(Target,Pname,{Params}) -> convolutionParameteri(Target,Pname,Params). %% @doc Copy pixels into a one-dimensional convolution filter @@ -9671,7 +9675,7 @@ pointParameterf(Pname,Param) -> %% @doc %% See {@link pointParameterf/2} --spec pointParameterfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}. +-spec pointParameterfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). pointParameterfv(Pname,Params) -> cast(5397, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -9684,7 +9688,7 @@ pointParameteri(Pname,Param) -> %% @doc %% See {@link pointParameterf/2} --spec pointParameteriv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}. +-spec pointParameteriv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). pointParameteriv(Pname,Params) -> cast(5399, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -11529,7 +11533,7 @@ linkProgram(Program) -> %% scanned or parsed at this time; they are simply copied into the specified shader object. %% %% See external documentation. --spec shaderSource(Shader, String) -> ok when Shader :: integer(),String :: [string()]. +-spec shaderSource(Shader, String) -> ok when Shader :: integer(),String :: iolist(). shaderSource(Shader,String) -> StringTemp = list_to_binary([[Str|[0]] || Str <- String ]), cast(5473, <>). @@ -12278,7 +12282,7 @@ bindBufferBase(Target,Index,Buffer) -> %% and the buffer mode is `?GL_INTERLEAVED_ATTRIBS'. %% %% See external documentation. --spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> ok when Program :: integer(),Varyings :: [string()],BufferMode :: enum(). +-spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> ok when Program :: integer(),Varyings :: iolist(),BufferMode :: enum(). transformFeedbackVaryings(Program,Varyings,BufferMode) -> VaryingsTemp = list_to_binary([[Str|[0]] || Str <- Varyings ]), cast(5536, <>). @@ -12596,7 +12600,7 @@ uniform4uiv(Location,Value) -> %% @doc %% See {@link texParameterf/3} --spec texParameterIiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texParameterIiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameterIiv(Target,Pname,Params) -> cast(5568, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -12604,7 +12608,7 @@ texParameterIiv(Target,Pname,Params) -> %% @doc glTexParameterI %% %% See external documentation. --spec texParameterIuiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texParameterIuiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameterIuiv(Target,Pname,Params) -> cast(5569, <> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -12651,21 +12655,21 @@ getTexParameterIuiv(Target,Pname) -> %% and the buffer being cleared is defined. However, this is not an error. %% %% See external documentation. --spec clearBufferiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}. +-spec clearBufferiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple(). clearBufferiv(Buffer,Drawbuffer,Value) -> cast(5572, <> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>). %% @doc %% See {@link clearBufferiv/3} --spec clearBufferuiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}. +-spec clearBufferuiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple(). clearBufferuiv(Buffer,Drawbuffer,Value) -> cast(5573, <> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>). %% @doc %% See {@link clearBufferiv/3} --spec clearBufferfv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {float()}. +-spec clearBufferfv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple(). clearBufferfv(Buffer,Drawbuffer,Value) -> cast(5574, <> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>). @@ -13219,7 +13223,7 @@ createShaderObjectARB(ShaderType) -> %% @doc glShaderSourceARB %% %% See external documentation. --spec shaderSourceARB(ShaderObj, String) -> ok when ShaderObj :: integer(),String :: [string()]. +-spec shaderSourceARB(ShaderObj, String) -> ok when ShaderObj :: integer(),String :: iolist(). shaderSourceARB(ShaderObj,String) -> StringTemp = list_to_binary([[Str|[0]] || Str <- String ]), cast(5630, <>). @@ -13927,7 +13931,7 @@ isVertexArray(Array) -> %% If an error occurs, nothing is written to `UniformIndices' . %% %% See external documentation. --spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: [string()]. +-spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: iolist(). getUniformIndices(Program,UniformNames) -> UniformNamesTemp = list_to_binary([[Str|[0]] || Str <- UniformNames ]), call(5675, <>). @@ -14458,7 +14462,7 @@ deleteNamedStringARB(Name) -> %% @doc glCompileShaderIncludeARB %% %% See external documentation. --spec compileShaderIncludeARB(Shader, Path) -> ok when Shader :: integer(),Path :: [string()]. +-spec compileShaderIncludeARB(Shader, Path) -> ok when Shader :: integer(),Path :: iolist(). compileShaderIncludeARB(Shader,Path) -> PathTemp = list_to_binary([[Str|[0]] || Str <- Path ]), cast(5703, <>). @@ -15617,7 +15621,7 @@ activeShaderProgram(Pipeline,Program) -> %% @doc glCreateShaderProgramv %% %% See external documentation. --spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: [string()]. +-spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: iolist(). createShaderProgramv(Type,Strings) -> StringsTemp = list_to_binary([[Str|[0]] || Str <- Strings ]), call(5778, <>). diff --git a/lib/wx/src/gen/glu.erl b/lib/wx/src/gen/glu.erl index 6a6e20b3e4..5faba48930 100644 --- a/lib/wx/src/gen/glu.erl +++ b/lib/wx/src/gen/glu.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -51,10 +51,14 @@ -define(GLint64,64/native-signed). -type vertex() :: {float(), float(), float()}. -type enum() :: non_neg_integer(). %% See wx/include/gl.hrl or glu.hrl --type matrix() :: {float(),float(),float(),float(), +-type matrix12() :: {float(),float(),float(),float(), + float(),float(),float(),float(), + float(),float(),float(),float()}. +-type matrix16() :: {float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float()}. +-type matrix() :: matrix12() | matrix16(). -type mem() :: binary() | tuple(). %% Memory block -export([tesselate/2,build1DMipmapLevels/9,build1DMipmaps/6,build2DMipmapLevels/10, -- cgit v1.2.3 From 3864e195ec993f6d03a185b73b183b5c4857c016 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 3 Dec 2015 12:53:33 +0100 Subject: ssh: client pub key documentation --- lib/ssh/doc/src/ssh.xml | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 18bced2d1d..b3f850fc38 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -206,26 +206,25 @@ -

This option is kept for compatibility. It is ignored if the preferred_algorithms - option is used. The equivalence of {public_key_alg,'ssh-dss'} is - {preferred_algorithms, [{public_key,['ssh-dss','ssh-rsa']}]}.

+

This option will be removed in OTP 20, but is kept for compatibility. It is ignored if + the preferred pref_public_key_algs option is used.

Sets the preferred public key algorithm to use for user authentication. If the preferred algorithm fails, - the other algorithm is tried. The default is - to try first.

+ the other algorithm is tried. If {public_key_alg, 'ssh-rsa'} is set, it is translated + to {pref_public_key_algs, ['ssh-rsa','ssh-dss']}. If it is + {public_key_alg, 'ssh-dss'}, it is translated + to {pref_public_key_algs, ['ssh-dss','ssh-rsa']}. +

- -

This option is kept for compatibility. It is ignored if the preferred_algorithms - option is used. The equivalence of {pref_public_key_algs,['ssh-dss']} is - {preferred_algorithms, [{public_key,['ssh-dss']}]}.

-
-

List of public key algorithms to try to use. - 'ssh-rsa' and 'ssh-dss' are available. - Overrides

+

List of user (client) public key algorithms to try to use.

+

The default value is + +

+

If there is no public key of a specified type available, the corresponding entry is ignored.

@@ -233,6 +232,7 @@

List of algorithms to use in the algorithm negotiation. The default algs_list() can be obtained from default_algorithms/0.

+

If an alg_entry() is missing in the algs_list(), the default value is used for that entry.

Here is an example of this option:

{preferred_algorithms, @@ -243,9 +243,9 @@ {compression,[none,zlib]} } -

The example specifies different algorithms in the two directions (client2server and server2client), for cipher but specifies the same -algorithms for mac and compression in both directions. The kex (key exchange) and public key algorithms are set to their default values, -kex is implicit but public_key is set explicitly.

+

The example specifies different algorithms in the two directions (client2server and server2client), + for cipher but specifies the same algorithms for mac and compression in both directions. + The kex (key exchange) is implicit but public_key is set explicitly.

Changing the values can make a connection less secure. Do not change unless you @@ -451,6 +451,7 @@ kex is implicit but public_key is set explicitly.

List of algorithms to use in the algorithm negotiation. The default algs_list() can be obtained from default_algorithms/0.

+

If an alg_entry() is missing in the algs_list(), the default value is used for that entry.

Here is an example of this option:

{preferred_algorithms, @@ -461,9 +462,9 @@ kex is implicit but public_key is set explicitly.

{compression,[none,zlib]} }
-

The example specifies different algorithms in the two directions (client2server and server2client), for cipher but specifies the same -algorithms for mac and compression in both directions. The kex (key exchange) and public key algorithms are set to their default values, -kex is implicit but public_key is set explicitly.

+

The example specifies different algorithms in the two directions (client2server and server2client), + for cipher but specifies the same algorithms for mac and compression in both directions. + The kex (key exchange) is implicit but public_key is set explicitly.

Changing the values can make a connection less secure. Do not change unless you -- cgit v1.2.3 From 8abb84f324d6302d720545ffd3955f524a38c219 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 3 Dec 2015 14:48:54 +0100 Subject: ssh: client pub key testcase --- lib/ssh/test/ssh_basic_SUITE.erl | 90 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index d4cb03f2f2..5ce6d172e1 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -41,6 +41,10 @@ double_close/1, exec/1, exec_compressed/1, + exec_key_differs1/1, + exec_key_differs2/1, + exec_key_differs3/1, + exec_key_differs_fail/1, idle_time/1, inet6_option/1, inet_option/1, @@ -86,6 +90,7 @@ all() -> {group, ecdsa_sha2_nistp521_key}, {group, dsa_pass_key}, {group, rsa_pass_key}, + {group, host_user_key_differs}, {group, key_cb}, {group, internal_error}, daemon_already_started, @@ -102,6 +107,10 @@ groups() -> {ecdsa_sha2_nistp256_key, [], basic_tests()}, {ecdsa_sha2_nistp384_key, [], basic_tests()}, {ecdsa_sha2_nistp521_key, [], basic_tests()}, + {host_user_key_differs, [], [exec_key_differs1, + exec_key_differs2, + exec_key_differs3, + exec_key_differs_fail]}, {dsa_pass_key, [], [pass_phrase]}, {rsa_pass_key, [], [pass_phrase]}, {key_cb, [], [key_callback, key_callback_options]}, @@ -184,6 +193,21 @@ init_per_group(dsa_pass_key, Config) -> PrivDir = ?config(priv_dir, Config), ssh_test_lib:setup_dsa_pass_pharse(DataDir, PrivDir, "Password"), [{pass_phrase, {dsa_pass_phrase, "Password"}}| Config]; +init_per_group(host_user_key_differs, Config) -> + Data = ?config(data_dir, Config), + Sys = filename:join(?config(priv_dir, Config), system_rsa), + SysUsr = filename:join(Sys, user), + Usr = filename:join(?config(priv_dir, Config), user_ecdsa_256), + file:make_dir(Sys), + file:make_dir(SysUsr), + file:make_dir(Usr), + file:copy(filename:join(Data, "ssh_host_rsa_key"), filename:join(Sys, "ssh_host_rsa_key")), + file:copy(filename:join(Data, "ssh_host_rsa_key.pub"), filename:join(Sys, "ssh_host_rsa_key.pub")), + file:copy(filename:join(Data, "id_ecdsa256"), filename:join(Usr, "id_ecdsa")), + file:copy(filename:join(Data, "id_ecdsa256.pub"), filename:join(Usr, "id_ecdsa.pub")), + ssh_test_lib:setup_ecdsa_auth_keys("256", Usr, SysUsr), + ssh_test_lib:setup_rsa_known_host(Sys, Usr), + Config; init_per_group(key_cb, Config) -> DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), @@ -490,6 +514,72 @@ shell(Config) when is_list(Config) -> 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) end. +%%-------------------------------------------------------------------- +%%% Test that we could user different types of host pubkey and user pubkey +exec_key_differs1(Config) -> exec_key_differs(Config, ['ecdsa-sha2-nistp256']). + +exec_key_differs2(Config) -> exec_key_differs(Config, ['ssh-dss','ecdsa-sha2-nistp256']). + +exec_key_differs3(Config) -> exec_key_differs(Config, ['ecdsa-sha2-nistp384','ecdsa-sha2-nistp256']). + + + +exec_key_differs(Config, UserPKAlgs) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system_rsa), + SystemUserDir = filename:join(SystemDir, user), + UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256), + + {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, SystemUserDir}, + {preferred_algorithms, + [{public_key,['ssh-rsa']}]}]), + ct:sleep(500), + + IO = ssh_test_lib:start_io_server(), + Shell = ssh_test_lib:start_shell(Port, IO, UserDir, + [{preferred_algorithms,[{public_key,['ssh-rsa']}]}, + {pref_public_key_algs,UserPKAlgs} + ]), + + + receive + {'EXIT', _, _} -> + ct:fail(no_ssh_connection); + ErlShellStart -> + ct:log("Erlang shell start: ~p~n", [ErlShellStart]), + do_shell(IO, Shell) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + end. + +%%-------------------------------------------------------------------- +exec_key_differs_fail(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system_rsa), + SystemUserDir = filename:join(SystemDir, user), + UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256), + + {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, SystemUserDir}, + {preferred_algorithms, + [{public_key,['ssh-rsa']}]}]), + ct:sleep(500), + + IO = ssh_test_lib:start_io_server(), + ssh_test_lib:start_shell(Port, IO, UserDir, + [{preferred_algorithms,[{public_key,['ssh-rsa']}]}, + {pref_public_key_algs,['ssh-dss']}]), + receive + {'EXIT', _, _} -> + ok; + ErlShellStart -> + ct:log("Erlang shell start: ~p~n", [ErlShellStart]), + ct:fail(connection_not_rejected) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + end. + %%-------------------------------------------------------------------- cli(Config) when is_list(Config) -> process_flag(trap_exit, true), -- cgit v1.2.3 From 1a6c8b90416e261b0429bbcc253347ce9fbac5ea Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 3 Dec 2015 15:56:03 +0100 Subject: ssh: client pub key opt implemented --- lib/ssh/src/ssh.erl | 74 +++++++++++++++++++++++++++--------------------- lib/ssh/src/ssh.hrl | 3 ++ lib/ssh/src/ssh_auth.erl | 6 +--- lib/ssh/src/ssh_auth.hrl | 1 - 4 files changed, 46 insertions(+), 38 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 1d29c95229..54f94acbdc 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -297,13 +297,6 @@ find_hostport(Fd) -> ok = inet:close(S), HostPort. -%% find_port(Fd) -> -%% %% Hack.... -%% {ok,TmpSock} = gen_tcp:listen(0,[{fd,Fd}]), -%% {ok, {_,ThePort}} = inet:sockname(TmpSock), -%% gen_tcp:close(TmpSock), -%% ThePort. - handle_options(Opts) -> try handle_option(algs_compatibility(proplists:unfold(Opts)), [], []) of @@ -315,32 +308,27 @@ handle_options(Opts) -> end. -algs_compatibility(Os) -> +algs_compatibility(Os0) -> %% Take care of old options 'public_key_alg' and 'pref_public_key_algs' - comp_pk(proplists:get_value(preferred_algorithms,Os), - proplists:get_value(pref_public_key_algs,Os), - proplists:get_value(public_key_alg, Os), - [{K,V} || {K,V} <- Os, - K =/= public_key_alg, - K =/= pref_public_key_algs] - ). - -comp_pk(undefined, undefined, undefined, Os) -> Os; -comp_pk( PrefAlgs, _, _, Os) when PrefAlgs =/= undefined -> Os; - -comp_pk(undefined, undefined, ssh_dsa, Os) -> comp_pk(undefined, undefined, 'ssh-dss', Os); -comp_pk(undefined, undefined, ssh_rsa, Os) -> comp_pk(undefined, undefined, 'ssh-rsa', Os); -comp_pk(undefined, undefined, PK, Os) -> - PKs = [PK | ssh_transport:supported_algorithms(public_key)--[PK]], - [{preferred_algorithms, [{public_key,PKs}] } | Os]; - -comp_pk(undefined, PrefPKs, _, Os) when PrefPKs =/= undefined -> - PKs = [case PK of - ssh_dsa -> 'ssh-dss'; - ssh_rsa -> 'ssh-rsa'; - _ -> PK - end || PK <- PrefPKs], - [{preferred_algorithms, [{public_key,PKs}]} | Os]. + case proplists:get_value(public_key_alg, Os0) of + undefined -> + Os0; + A when is_atom(A) -> + %% Skip public_key_alg if pref_public_key_algs is defined: + Os = lists:keydelete(public_key_alg, 1, Os0), + case proplists:get_value(pref_public_key_algs,Os) of + undefined when A == 'ssh-rsa' ; A==ssh_rsa -> + [{pref_public_key_algs,['ssh-rsa','ssh-dss']} | Os]; + undefined when A == 'ssh-dss' ; A==ssh_dsa -> + [{pref_public_key_algs,['ssh-dss','ssh-rsa']} | Os]; + undefined -> + throw({error, {eoptions, {public_key_alg,A} }}); + _ -> + Os + end; + V -> + throw({error, {eoptions, {public_key_alg,V} }}) + end. handle_option([], SocketOptions, SshOptions) -> @@ -411,6 +399,8 @@ handle_option([{auth_methods, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{auth_method_kb_interactive_data, _} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{pref_public_key_algs, _} = Opt | Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{preferred_algorithms,_} = Opt | Rest], SocketOptions, SshOptions) -> handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); handle_option([{dh_gex_groups,_} = Opt | Rest], SocketOptions, SshOptions) -> @@ -522,6 +512,13 @@ handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0 is_integer(Max), Max>=I -> %% Client Opt; +handle_ssh_option({pref_public_key_algs, Value} = Opt) when is_list(Value), length(Value) >= 1 -> + case handle_user_pref_pubkey_algs(Value, []) of + {true, NewOpts} -> + {pref_public_key_algs, NewOpts}; + _ -> + throw({error, {eoptions, Opt}}) + end; handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity -> Opt; handle_ssh_option({max_sessions, Value} = Opt) when is_integer(Value), Value>0 -> @@ -780,3 +777,16 @@ read_moduli_file(D, I, Acc) -> end end. +handle_user_pref_pubkey_algs([], Acc) -> + {true, lists:reverse(Acc)}; +handle_user_pref_pubkey_algs([H|T], Acc) -> + case lists:member(H, ?SUPPORTED_USER_KEYS) of + true -> + handle_user_pref_pubkey_algs(T, [H| Acc]); + + false when H==ssh_dsa -> handle_user_pref_pubkey_algs(T, ['ssh-dss'| Acc]); + false when H==ssh_rsa -> handle_user_pref_pubkey_algs(T, ['ssh-rsa'| Acc]); + + false -> + false + end. diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 8efc743b67..f88098819d 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -33,6 +33,9 @@ -define(REKEY_DATA_TIMOUT, 60000). -define(DEFAULT_PROFILE, default). +-define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password"). +-define(SUPPORTED_USER_KEYS, ['ssh-rsa','ssh-dss','ecdsa-sha2-nistp256','ecdsa-sha2-nistp384','ecdsa-sha2-nistp521']). + -define(FALSE, 0). -define(TRUE, 1). %% basic binary constructors diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 4967a2e4cd..0d38c563ba 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -118,11 +118,7 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) -> service = "ssh-connection", method = "none", data = <<>>}, - - - Algs = proplists:get_value(public_key, - proplists:get_value(preferred_algorithms, Opts, []), - ssh_transport:default_algorithms(public_key)), + Algs = proplists:get_value(pref_public_key_algs, Opts, ?SUPPORTED_USER_KEYS), Prefs = method_preference(Algs), ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User, userauth_preference = Prefs, diff --git a/lib/ssh/src/ssh_auth.hrl b/lib/ssh/src/ssh_auth.hrl index 5197a42fa4..449bc4fa45 100644 --- a/lib/ssh/src/ssh_auth.hrl +++ b/lib/ssh/src/ssh_auth.hrl @@ -22,7 +22,6 @@ %%% Description: Ssh User Authentication Protocol --define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password"). -define(SSH_MSG_USERAUTH_REQUEST, 50). -define(SSH_MSG_USERAUTH_FAILURE, 51). -- cgit v1.2.3 From ff76dce72f52c5fd2d06461414dac52a70ba43cc Mon Sep 17 00:00:00 2001 From: Vlad Dumitrescu Date: Thu, 3 Dec 2015 19:27:52 +0100 Subject: Improve sorting order of keys in a map The implementation sorted keys differently for different Java versions (probably due to different hashing algorithms), so we switch it to use LinkedHashMap where the order is deterministic. --- .../com/ericsson/otp/erlang/OtpErlangMap.java | 23 +++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java index 0fd7d3ce37..30126db3fd 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java @@ -19,7 +19,7 @@ */ package com.ericsson.otp.erlang; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -37,13 +37,22 @@ public class OtpErlangMap extends OtpErlangObject { // don't change this! private static final long serialVersionUID = -6410770117696198497L; - private HashMap map; + private OtpMap map; + + private static class OtpMap + extends LinkedHashMap { + private static final long serialVersionUID = -2666505810905455082L; + + public OtpMap() { + super(); + } + } /** * Create an empty map. */ public OtpErlangMap() { - map = new HashMap(); + map = new OtpMap(); } /** @@ -93,7 +102,7 @@ public class OtpErlangMap extends OtpErlangObject { throw new java.lang.IllegalArgumentException( "Map keys and values must have same arity"); } - map = new HashMap(vcount); + map = new OtpMap(); OtpErlangObject key, val; for (int i = 0; i < vcount; i++) { if ((key = keys[kstart + i]) == null) { @@ -125,7 +134,7 @@ public class OtpErlangMap extends OtpErlangObject { final int arity = buf.read_map_head(); if (arity > 0) { - map = new HashMap(arity); + map = new OtpMap(); for (int i = 0; i < arity; i++) { OtpErlangObject key, val; key = buf.read_any(); @@ -133,7 +142,7 @@ public class OtpErlangMap extends OtpErlangObject { put(key, val); } } else { - map = new HashMap(); + map = new OtpMap(); } } @@ -350,7 +359,7 @@ public class OtpErlangMap extends OtpErlangObject { @SuppressWarnings("unchecked") public Object clone() { final OtpErlangMap newMap = (OtpErlangMap) super.clone(); - newMap.map = (HashMap) map.clone(); + newMap.map = (OtpMap) map.clone(); return newMap; } } -- cgit v1.2.3 From 976214f8d738d4852348496df79f84264d899aba Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 27 Nov 2015 13:04:58 +0100 Subject: Extended table_trans timer in order to handle big data on slow machines The test case netconfc1_SUITE:get_a_lot often fails with table_trans_timeout in the netconf server (ns.erl) on virtual machines. The correction is to overcome this problem. Amount of data used in the test case is also reduced a bit. --- lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl | 2 +- lib/common_test/test/ct_netconfc_SUITE_data/ns.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl index 5f84634f74..2a8f8237bc 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -353,7 +353,7 @@ get(Config) -> get_a_lot(Config) -> DataDir = ?config(data_dir,Config), {ok,Client} = open_success(DataDir), - Descr = lists:append(lists:duplicate(1000,"Description of myserver! ")), + Descr = lists:append(lists:duplicate(100,"Description of myserver! ")), Server = {server,[{xmlns,"myns"}],[{name,[],["myserver"]}, {description,[],[Descr]}]}, Data = lists:duplicate(100,Server), diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl index 3fc99e5486..07893faabc 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl @@ -306,7 +306,7 @@ table_trans(Fun,Args) -> receive {table_trans_done,Result} -> Result - after 5000 -> + after 20000 -> exit(table_trans_timeout) end end. -- cgit v1.2.3 From 99f322eecb31ea23b7ff5dbb30c3b26f53bd6252 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Fri, 4 Dec 2015 14:52:33 +0100 Subject: observer: Handle truncated binaries Crashed when term was displayed --- lib/observer/src/observer_html_lib.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl index 9d8c2d998c..f646f8ed3e 100644 --- a/lib/observer/src/observer_html_lib.erl +++ b/lib/observer/src/observer_html_lib.erl @@ -387,7 +387,9 @@ remove_lgt(Deep) -> remove_lgt_1([$<,$<|Rest]) -> [$>,$>|BinStr] = lists:reverse(Rest), - replace_lgt(lists:reverse(BinStr)). + replace_lgt(lists:reverse(BinStr)); +remove_lgt_1(TruncBin) -> + TruncBin. replace_lgt([$<|R]) -> ["<"|replace_lgt(R)]; -- cgit v1.2.3 From 08401d7b2fc7ba8a50ac478ce6b99a8be646f9fb Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 4 Dec 2015 15:42:57 +0100 Subject: ssh: ssh_auth checks support for user pubkey alg --- lib/ssh/src/ssh_auth.erl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 0d38c563ba..fdbb5c152a 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -118,7 +118,16 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) -> service = "ssh-connection", method = "none", data = <<>>}, - Algs = proplists:get_value(pref_public_key_algs, Opts, ?SUPPORTED_USER_KEYS), + Algs0 = proplists:get_value(pref_public_key_algs, Opts, ?SUPPORTED_USER_KEYS), + %% The following line is not strictly correct. The call returns the + %% supported HOST key types while we are interested in USER keys. However, + %% they "happens" to be the same (for now). This could change.... + %% There is no danger as long as the set of user keys is a subset of the set + %% of host keys. + CryptoSupported = ssh_transport:supported_algorithms(public_key), + Algs = [A || A <- Algs0, + lists:member(A, CryptoSupported)], + Prefs = method_preference(Algs), ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User, userauth_preference = Prefs, -- cgit v1.2.3 From 58aff4fafed973059167ea64b6109ce2fec03fe1 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 4 Dec 2015 15:43:52 +0100 Subject: ssh: tests skips if not supported crypto --- lib/ssh/test/ssh_basic_SUITE.erl | 56 +++++++++++++++++++--------------- lib/ssh/test/ssh_renegotiate_SUITE.erl | 24 +++++++++++---- 2 files changed, 50 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 5ce6d172e1..85a6bac972 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -525,32 +525,40 @@ exec_key_differs3(Config) -> exec_key_differs(Config, ['ecdsa-sha2-nistp384','ec exec_key_differs(Config, UserPKAlgs) -> - process_flag(trap_exit, true), - SystemDir = filename:join(?config(priv_dir, Config), system_rsa), - SystemUserDir = filename:join(SystemDir, user), - UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256), + case lists:usort(['ssh-rsa'|UserPKAlgs]) + -- ssh_transport:supported_algorithms(public_key) + of + [] -> + process_flag(trap_exit, true), + SystemDir = filename:join(?config(priv_dir, Config), system_rsa), + SystemUserDir = filename:join(SystemDir, user), + UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256), - {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, - {user_dir, SystemUserDir}, - {preferred_algorithms, - [{public_key,['ssh-rsa']}]}]), - ct:sleep(500), - - IO = ssh_test_lib:start_io_server(), - Shell = ssh_test_lib:start_shell(Port, IO, UserDir, - [{preferred_algorithms,[{public_key,['ssh-rsa']}]}, - {pref_public_key_algs,UserPKAlgs} - ]), - + {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, SystemUserDir}, + {preferred_algorithms, + [{public_key,['ssh-rsa']}]}]), + ct:sleep(500), + + IO = ssh_test_lib:start_io_server(), + Shell = ssh_test_lib:start_shell(Port, IO, UserDir, + [{preferred_algorithms,[{public_key,['ssh-rsa']}]}, + {pref_public_key_algs,UserPKAlgs} + ]), + + + receive + {'EXIT', _, _} -> + ct:fail(no_ssh_connection); + ErlShellStart -> + ct:log("Erlang shell start: ~p~n", [ErlShellStart]), + do_shell(IO, Shell) + after + 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + end; - receive - {'EXIT', _, _} -> - ct:fail(no_ssh_connection); - ErlShellStart -> - ct:log("Erlang shell start: ~p~n", [ErlShellStart]), - do_shell(IO, Shell) - after - 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE]) + UnsupportedPubKeys -> + {skip, io_lib:format("~p unsupported",[UnsupportedPubKeys])} end. %%-------------------------------------------------------------------- diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl index 227dfcddcd..e5cfa58bad 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE.erl +++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl @@ -57,9 +57,15 @@ end_per_suite(_Config) -> %%-------------------------------------------------------------------- init_per_group(aes_gcm, Config) -> - [{preferred_algorithms, [{cipher,[{client2server,['aes128-gcm@openssh.com']}, - {server2client,['aes128-gcm@openssh.com']}]}]} - | Config]; + case lists:member({client2server,['aes128-gcm@openssh.com']}, + ssh_transport:supported_algorithms(cipher)) of + true -> + [{preferred_algorithms, [{cipher,[{client2server,['aes128-gcm@openssh.com']}, + {server2client,['aes128-gcm@openssh.com']}]}]} + | Config]; + false -> + {skip, "aes_gcm not supported"} + end; init_per_group(_, Config) -> [{preferred_algorithms, ssh:default_algorithms()} | Config]. @@ -107,7 +113,9 @@ rekey_limit(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "rekey.data"), - {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), + Algs = ?config(preferred_algorithms, Config), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 6000}, {max_random_length_padding,0}]), @@ -151,7 +159,9 @@ renegotiate1(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate1.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), + Algs = ?config(preferred_algorithms, Config), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), @@ -189,7 +199,9 @@ renegotiate2(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate2.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), + Algs = ?config(preferred_algorithms, Config), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}, + {preferred_algorithms,Algs}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), -- cgit v1.2.3 From 58f39f270f7cc3c01b6f6e6ef9453024edcf8739 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 4 Dec 2015 12:26:03 +0100 Subject: public_key: Add different upper bounds for diffrent string types At the bottom of the file PKIX1Explicit88.asn1 there is a commenet about upper bounds and diffrent types of strings. Adhere to this so that we can accept all certificates that openSSL does. For example: httpc:request("https://dl.sciencesocieties.org/"). --- lib/public_key/asn1/PKIX1Explicit88.asn1 | 109 +++++++++++++++++++------------ 1 file changed, 66 insertions(+), 43 deletions(-) (limited to 'lib') diff --git a/lib/public_key/asn1/PKIX1Explicit88.asn1 b/lib/public_key/asn1/PKIX1Explicit88.asn1 index 91758d7269..81fec8283e 100644 --- a/lib/public_key/asn1/PKIX1Explicit88.asn1 +++ b/lib/public_key/asn1/PKIX1Explicit88.asn1 @@ -86,22 +86,22 @@ id-at-initials AttributeType ::= { id-at 43 } id-at-generationQualifier AttributeType ::= { id-at 44 } X520name ::= CHOICE { - teletexString TeletexString (SIZE (1..ub-name)), - printableString PrintableString (SIZE (1..ub-name)), - universalString UniversalString (SIZE (1..ub-name)), - utf8String UTF8String (SIZE (1..ub-name)), - bmpString BMPString (SIZE (1..ub-name)) } + teletexString TeletexString (SIZE (1..ub-name-teletex)), + printableString PrintableString (SIZE (1..ub-name-printable)), + universalString UniversalString (SIZE (1..ub-name-universal)), + utf8String UTF8String (SIZE (1..ub-name-utf8)), + bmpString BMPString (SIZE (1..ub-name-universal)) } -- Naming attributes of type X520CommonName id-at-commonName AttributeType ::= { id-at 3 } X520CommonName ::= CHOICE { - teletexString TeletexString (SIZE (1..ub-common-name)), - printableString PrintableString (SIZE (1..ub-common-name)), - universalString UniversalString (SIZE (1..ub-common-name)), - utf8String UTF8String (SIZE (1..ub-common-name)), - bmpString BMPString (SIZE (1..ub-common-name)) } + teletexString TeletexString (SIZE (1..ub-common-name-teletex)), + printableString PrintableString (SIZE (1..ub-common-name-printable)), + universalString UniversalString (SIZE (1..ub-common-name-universal)), + utf8String UTF8String (SIZE (1..ub-common-name-utf8)), + bmpString BMPString (SIZE (1..ub-common-name-universal)) } -- Naming attributes of type X520LocalityName @@ -110,9 +110,9 @@ id-at-localityName AttributeType ::= { id-at 7 } X520LocalityName ::= CHOICE { teletexString TeletexString (SIZE (1..ub-locality-name)), printableString PrintableString (SIZE (1..ub-locality-name)), - universalString UniversalString (SIZE (1..ub-locality-name)), - utf8String UTF8String (SIZE (1..ub-locality-name)), - bmpString BMPString (SIZE (1..ub-locality-name)) } + universalString UniversalString (SIZE (1..ub-locality-name-universal)), + utf8String UTF8String (SIZE (1..ub-locality-name-utf8)), + bmpString BMPString (SIZE (1..ub-locality-name-universal)) } -- Naming attributes of type X520StateOrProvinceName @@ -121,9 +121,9 @@ id-at-stateOrProvinceName AttributeType ::= { id-at 8 } X520StateOrProvinceName ::= CHOICE { teletexString TeletexString (SIZE (1..ub-state-name)), printableString PrintableString (SIZE (1..ub-state-name)), - universalString UniversalString (SIZE (1..ub-state-name)), - utf8String UTF8String (SIZE (1..ub-state-name)), - bmpString BMPString (SIZE(1..ub-state-name)) } + universalString UniversalString (SIZE (1..ub-state-name-universal)), + utf8String UTF8String (SIZE (1..ub-state-name-utf8)), + bmpString BMPString (SIZE(1..ub-state-name-universal)) } -- Naming attributes of type X520OrganizationName @@ -131,15 +131,15 @@ id-at-organizationName AttributeType ::= { id-at 10 } X520OrganizationName ::= CHOICE { teletexString TeletexString - (SIZE (1..ub-organization-name)), + (SIZE (1..ub-organization-name-teletex)), printableString PrintableString - (SIZE (1..ub-organization-name)), + (SIZE (1..ub-organization-name-printable)), universalString UniversalString - (SIZE (1..ub-organization-name)), + (SIZE (1..ub-organization-name-universal)), utf8String UTF8String - (SIZE (1..ub-organization-name)), + (SIZE (1..ub-organization-name-utf8)), bmpString BMPString - (SIZE (1..ub-organization-name)) } + (SIZE (1..ub-organization-name-universal)) } -- Naming attributes of type X520OrganizationalUnitName @@ -147,26 +147,26 @@ id-at-organizationalUnitName AttributeType ::= { id-at 11 } X520OrganizationalUnitName ::= CHOICE { teletexString TeletexString - (SIZE (1..ub-organizational-unit-name)), + (SIZE (1..ub-organizational-unit-name-teletex)), printableString PrintableString - (SIZE (1..ub-organizational-unit-name)), + (SIZE (1..ub-organizational-unit-name-printable)), universalString UniversalString - (SIZE (1..ub-organizational-unit-name)), + (SIZE (1..ub-organizational-unit-name-universal)), utf8String UTF8String - (SIZE (1..ub-organizational-unit-name)), + (SIZE (1..ub-organizational-unit-name-utf8)), bmpString BMPString - (SIZE (1..ub-organizational-unit-name)) } + (SIZE (1..ub-organizational-unit-name-universal)) } -- Naming attributes of type X520Title id-at-title AttributeType ::= { id-at 12 } X520Title ::= CHOICE { - teletexString TeletexString (SIZE (1..ub-title)), - printableString PrintableString (SIZE (1..ub-title)), - universalString UniversalString (SIZE (1..ub-title)), - utf8String UTF8String (SIZE (1..ub-title)), - bmpString BMPString (SIZE (1..ub-title)) } + teletexString TeletexString (SIZE (1..ub-title-teletex)), + printableString PrintableString (SIZE (1..ub-title-printable)), + universalString UniversalString (SIZE (1..ub-title-universal)), + utf8String UTF8String (SIZE (1..ub-title-utf8)), + bmpString BMPString (SIZE (1..ub-title-universal)) } -- Naming attributes of type X520dnQualifier @@ -193,9 +193,9 @@ id-at-pseudonym AttributeType ::= { id-at 65 } X520Pseudonym ::= CHOICE { teletexString TeletexString (SIZE (1..ub-pseudonym)), printableString PrintableString (SIZE (1..ub-pseudonym)), - universalString UniversalString (SIZE (1..ub-pseudonym)), - utf8String UTF8String (SIZE (1..ub-pseudonym)), - bmpString BMPString (SIZE (1..ub-pseudonym)) } + universalString UniversalString (SIZE (1..ub-pseudonym-universal)), + utf8String UTF8String (SIZE (1..ub-pseudonym-utf8)), + bmpString BMPString (SIZE (1..ub-pseudonym-universal)) } -- Naming attributes of type DomainComponent (from RFC 2247) @@ -363,7 +363,7 @@ PrivateDomainName ::= CHOICE { printable PrintableString (SIZE (1..ub-domain-name-length)) } OrganizationName ::= PrintableString - (SIZE (1..ub-organization-name-length)) + (SIZE (1..ub-organization-name-printable)) -- see also teletex-organization-name NumericUserIdentifier ::= NumericString @@ -386,7 +386,7 @@ OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) -- see also teletex-organizational-unit-names OrganizationalUnitName ::= PrintableString (SIZE - (1..ub-organizational-unit-name-length)) + (1..ub-organizational-unit-name-printable)) -- Built-in Domain-defined Attributes @@ -415,16 +415,16 @@ ExtensionAttribute ::= SEQUENCE { common-name INTEGER ::= 1 -CommonName ::= PrintableString (SIZE (1..ub-common-name-length)) +CommonName ::= PrintableString (SIZE (1..ub-common-name-printable)) teletex-common-name INTEGER ::= 2 -TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length)) +TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-teletex)) teletex-organization-name INTEGER ::= 3 TeletexOrganizationName ::= - TeletexString (SIZE (1..ub-organization-name-length)) + TeletexString (SIZE (1..ub-organization-name-teletex)) teletex-personal-name INTEGER ::= 4 @@ -445,7 +445,7 @@ TeletexOrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF TeletexOrganizationalUnitName TeletexOrganizationalUnitName ::= TeletexString - (SIZE (1..ub-organizational-unit-name-length)) + (SIZE (1..ub-organizational-unit-name-teletex)) pds-name INTEGER ::= 7 @@ -570,16 +570,39 @@ TeletexDomainDefinedAttribute ::= SEQUENCE { -- Upper Bounds ub-name INTEGER ::= 32768 +ub-name-teletex INTEGER ::= 65536 +ub-name-printable INTEGER ::= 65536 +ub-name-universal INTEGER ::= 131072 +ub-name-utf8 INTEGER ::= 131072 ub-common-name INTEGER ::= 64 +ub-common-name-teletex INTEGER::= 128 +ub-common-name-printable INTEGER ::= 128 +ub-common-name-universal INTEGER ::= 256 +ub-common-name-utf8 INTEGER ::= 256 ub-locality-name INTEGER ::= 128 +ub-locality-name-utf8 INTEGER ::= 256 +ub-locality-name-universal INTEGER ::= 256 ub-state-name INTEGER ::= 128 +ub-state-name-universal INTEGER ::= 256 +ub-state-name-utf8 INTEGER ::= 256 ub-organization-name INTEGER ::= 64 +ub-organization-name-printable INTEGER ::= 128 +ub-organization-name-teletex INTEGER ::= 128 +ub-organization-name-universal INTEGER ::= 256 +ub-organization-name-utf8 INTEGER ::= 256 ub-organizational-unit-name INTEGER ::= 64 +ub-organizational-unit-name-printable INTEGER ::= 128 +ub-organizational-unit-name-teletex INTEGER ::= 128 +ub-organizational-unit-name-universal INTEGER ::= 256 +ub-organizational-unit-name-utf8 INTEGER ::= 256 ub-title INTEGER ::= 64 +ub-title-teletex INTEGER ::= 128 +ub-title-printable INTEGER ::= 128 +ub-title-universal INTEGER ::= 256 +ub-title-utf8 INTEGER ::= 256 ub-serial-number INTEGER ::= 64 ub-match INTEGER ::= 128 ub-emailaddress-length INTEGER ::= 255 -ub-common-name-length INTEGER ::= 64 ub-country-name-alpha-length INTEGER ::= 2 ub-country-name-numeric-length INTEGER ::= 3 ub-domain-defined-attributes INTEGER ::= 4 @@ -594,14 +617,14 @@ ub-given-name-length INTEGER ::= 16 ub-initials-length INTEGER ::= 5 ub-integer-options INTEGER ::= 256 ub-numeric-user-id-length INTEGER ::= 32 -ub-organization-name-length INTEGER ::= 64 -ub-organizational-unit-name-length INTEGER ::= 32 ub-organizational-units INTEGER ::= 4 ub-pds-name-length INTEGER ::= 16 ub-pds-parameter-length INTEGER ::= 30 ub-pds-physical-address-lines INTEGER ::= 6 ub-postal-code-length INTEGER ::= 16 ub-pseudonym INTEGER ::= 128 +ub-pseudonym-utf8 INTEGER ::= 256 +ub-pseudonym-universal INTEGER ::= 256 ub-surname-length INTEGER ::= 40 ub-terminal-id-length INTEGER ::= 24 ub-unformatted-address-length INTEGER ::= 180 -- cgit v1.2.3 From 0ad8b47ce2ec578eab64896a3ba8af3f71ce2fd1 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 5 Nov 2015 17:09:09 +0100 Subject: stdlib: Pretty-print constraints as 'V :: T' Print constraints as 'V :: T' rather than 'is_subtype(V, T)'. --- lib/stdlib/src/erl_pp.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index f7a969977a..9c812395e3 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -253,6 +253,8 @@ lattribute(import, Name, _Opts, _State) when is_list(Name) -> attr("import", [{var,a0(),pname(Name)}]); lattribute(import, {From,Falist}, _Opts, _State) -> attr("import",[{var,a0(),pname(From)},falist(Falist)]); +lattribute(export_type, Talist, _Opts, _State) -> + call({var,a0(),"-export_type"}, [falist(Talist)], 0, options(none)); lattribute(optional_callbacks, Falist, Opts, _State) -> ArgL = try falist(Falist) catch _:_ -> abstract(Falist, Opts) @@ -321,7 +323,6 @@ ltype({type,_,'fun',[{type,_,any},_]}=FunType, _) -> ltype({type,_Line,'fun',[{type,_,product,_},_]}=FunType, _) -> [fun_type(['fun',$(], FunType),$)]; ltype({type,Line,T,Ts}, _) -> - %% Compatibility. Before 18.0. simple_type({atom,Line,T}, Ts); ltype({user_type,Line,T,Ts}, _) -> simple_type({atom,Line,T}, Ts); @@ -399,6 +400,9 @@ guard_type(Before, Gs) -> Gl = {list,[{step,'when',expr_list(Gs, [$,], fun constraint/2, Opts)}]}, {list,[{step,Before,Gl}]}. +constraint({type,_Line,constraint,[{atom,_,is_subtype},[{var,_,_}=V,Type]]}, + _Opts) -> + typed(lexpr(V, options(none)), Type); constraint({type,_Line,constraint,[Tag,As]}, _Opts) -> simple_type(Tag, As). -- cgit v1.2.3 From b8a5a201389c117aaa8ddfa387dcb11fb6f5ae4a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 17 Nov 2015 14:09:59 +0100 Subject: stdlib: Correct pretty-printing of map types Add parentheses around annotated type union elements in map pair types. The bug was introduced in Erlang/OTP 18.0. --- lib/stdlib/src/erl_pp.erl | 15 ++------------- lib/stdlib/test/erl_pp_SUITE.erl | 3 +++ 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index 9c812395e3..c5177aca90 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -347,16 +347,8 @@ map_type(Fs) -> map_pair_types(Fs) -> tuple_type(Fs, fun map_pair_type/2). -map_pair_type({type,_Line,map_field_assoc,[Ktype,Vtype]}, Prec) -> - map_assoc_typed(ltype(Ktype), Vtype, Prec). - -map_assoc_typed(B, {type,_,union,Ts}, Prec) -> - {first,[B,$\s],{seq,[],[],[],map_assoc_union_type(Ts, Prec)}}; -map_assoc_typed(B, Type, Prec) -> - {list,[{cstep,[B," =>"],ltype(Type, Prec)}]}. - -map_assoc_union_type([T|Ts], Prec) -> - [[leaf("=> "),ltype(T)] | ltypes(Ts, fun union_elem/2, Prec)]. +map_pair_type({type,_Line,map_field_assoc,[KType,VType]}, Prec) -> + {list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]}. record_type(Name, Fields) -> {first,[record_name(Name)],field_types(Fields)}. @@ -371,9 +363,6 @@ typed(B, Type) -> {_L,_P,R} = type_inop_prec('::'), {list,[{cstep,[B,' ::'],ltype(Type, R)}]}. -union_elem(T, Prec) -> - [leaf(" | "),ltype(T, Prec)]. - tuple_type(Ts, F) -> {seq,${,$},[$,],ltypes(Ts, F, 0)}. diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 389fd059f6..92e2764c65 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -960,6 +960,9 @@ maps_syntax(Config) when is_list(Config) -> "-compile(export_all).\n" "-type t1() :: map().\n" "-type t2() :: #{ atom() => integer(), atom() => float() }.\n" + "-type u() :: #{a => (I :: integer()) | (A :: atom()),\n" + " (X :: atom()) | (Y :: atom()) =>\n" + " (I :: integer()) | (A :: atom())}.\n" "-spec f1(t1()) -> 'true'.\n" "f1(M) when is_map(M) -> true.\n" "-spec f2(t2()) -> integer().\n" -- cgit v1.2.3 From 55569124ac815eedc21c234c447e346b97f3c8fe Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 7 Dec 2015 10:31:35 +0100 Subject: ssl: Fix documentation mistakes --- lib/ssl/doc/src/ssl.xml | 4 ++-- lib/ssl/doc/src/ssl_app.xml | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 22ac98c24e..3a541ed162 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -84,7 +84,7 @@ gen_tcp(3) manual pages in Kernel.

- ssloption() = + ssloption() =

{verify, verify_type()}

| {verify_fun, {fun(), term()}}

@@ -160,7 +160,7 @@ sslsocket() =

opaque()

- protocol() = + protocol() =

sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2'

ciphers() = diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index 257175a33f..24b0f5300e 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -58,7 +58,7 @@

erl -ssl protocol_version "['tlsv1.2', 'tlsv1.1']"

- ssl:protocol() ]]>. + protocol_version = ssl:protocol() ]]>

Protocol supported by started clients and servers. If this option is not set, it defaults to all protocols currently supported by the SSL application. @@ -71,7 +71,7 @@ ]]>

Name of the session cache callback module that implements the ssl_session_cache_api behavior. Defaults to - ssl_session_cache.erl.

+ ssl_session_cache.

]]> @@ -110,7 +110,10 @@
ERROR LOGGER AND EVENT HANDLERS -

The SSL application uses the default OTP error logger to log unexpected errors and TLS alerts. The logging of TLS alerts may be turned off with the log_alert option.

+

The SSL application uses the default OTP error logger to log + unexpected errors and TLS alerts. The logging of TLS alerts may be + turned off with the log_alert option.

-- cgit v1.2.3 From 807f0c8904be14c9088ebc41ade885ffac142b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 4 Dec 2015 14:34:20 +0100 Subject: Correct rand:export_seed/0 when there is no prior seed According to the documentation, rand:export_seed/0 should return 'undefined' if the seed has not been intialized. However, it will create and return a seed. That means that the following code will not work as expected: case rand:export_seed() of undefined -> rand:seen({1,2,3}); _ -> ok end, rand:uniform(Range) --- lib/stdlib/src/rand.erl | 2 +- lib/stdlib/test/rand_SUITE.erl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl index 8e8d0bc801..dc060e82d9 100644 --- a/lib/stdlib/src/rand.erl +++ b/lib/stdlib/src/rand.erl @@ -63,7 +63,7 @@ %% Return algorithm and seed so that RNG state can be recreated with seed/1 -spec export_seed() -> undefined | export_state(). export_seed() -> - case seed_get() of + case get(?SEED_DICT) of {#{type:=Alg}, Seed} -> {Alg, Seed}; _ -> undefined end. diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl index 111bf620de..03b5ce1a25 100644 --- a/lib/stdlib/test/rand_SUITE.erl +++ b/lib/stdlib/test/rand_SUITE.erl @@ -126,6 +126,9 @@ seed_1(Alg) -> false = (S1 =:= rand:seed_s(Alg)), %% Negative integers works _ = rand:seed_s(Alg, {-1,-1,-1}), + %% Check that export_seed/1 returns 'undefined' if there is no seed + erase(rand_seed), + undefined = rand:export_seed(), %% Other term do not work {'EXIT', _} = (catch rand:seed_s(foobar, os:timestamp())), -- cgit v1.2.3 From dee396ffd32dcd68c47cab983c75ba32f921b9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 4 Dec 2015 12:10:42 +0100 Subject: compile: Eliminate use of the obsolete 'random' module The 'random' module is used to pad the end of a block with random bytes. The appropriate function to use in this case crypto:rand_bytes/1. --- lib/compiler/src/compile.erl | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index a2a23a2b90..b61c104b3c 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -1306,21 +1306,12 @@ generate_key(String) when is_list(String) -> encrypt({des3_cbc=Type,Key,IVec,BlockSize}, Bin0) -> Bin1 = case byte_size(Bin0) rem BlockSize of 0 -> Bin0; - N -> list_to_binary([Bin0,random_bytes(BlockSize-N)]) + N -> list_to_binary([Bin0,crypto:rand_bytes(BlockSize-N)]) end, Bin = crypto:block_encrypt(Type, Key, IVec, Bin1), TypeString = atom_to_list(Type), list_to_binary([0,length(TypeString),TypeString,Bin]). -random_bytes(N) -> - _ = random:seed(erlang:time_offset(), - erlang:monotonic_time(), - erlang:unique_integer()), - random_bytes_1(N, []). - -random_bytes_1(0, Acc) -> Acc; -random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]). - save_core_code(St) -> {ok,St#compile{core_code=cerl:from_records(St#compile.code)}}. -- cgit v1.2.3 From b7d8e2d89cfcc4c4265f45adc5ffc425e43c90fe Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 18 Nov 2015 09:34:17 +0100 Subject: ssl: SSLv3 completeness We are considering removing default support for DES cipher suites. However this cipher suite is currently allowed in TLS and missing from SSL. --- lib/ssl/src/ssl_v3.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/ssl/src/ssl_v3.erl b/lib/ssl/src/ssl_v3.erl index 5e043624a7..f169059a75 100644 --- a/lib/ssl/src/ssl_v3.erl +++ b/lib/ssl/src/ssl_v3.erl @@ -144,6 +144,7 @@ suites() -> ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA, ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA, ?TLS_RSA_WITH_AES_128_CBC_SHA, + ?TLS_DHE_RSA_WITH_DES_CBC_SHA, ?TLS_RSA_WITH_DES_CBC_SHA ]. -- cgit v1.2.3 From da80d59e56bc8318c6561173b13a4f6904d4758d Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Mon, 7 Dec 2015 11:28:10 +0100 Subject: wx: Add toolbar stretchablespace Available since 3.0 --- lib/wx/api_gen/wx_extra/added_func.h | 6 + lib/wx/api_gen/wxapi.conf | 2 + lib/wx/c_src/gen/wxe_funcs.cpp | 19 + lib/wx/c_src/gen/wxe_macros.h | 5016 +++++++++++++++++----------------- lib/wx/src/gen/wxToolBar.erl | 36 +- lib/wx/src/gen/wxe_debug.hrl | 5016 +++++++++++++++++----------------- lib/wx/src/gen/wxe_funcs.hrl | 5016 +++++++++++++++++----------------- lib/wx/test/wx_class_SUITE.erl | 13 +- 8 files changed, 7590 insertions(+), 7534 deletions(-) (limited to 'lib') diff --git a/lib/wx/api_gen/wx_extra/added_func.h b/lib/wx/api_gen/wx_extra/added_func.h index 2323529368..0698621c5f 100644 --- a/lib/wx/api_gen/wx_extra/added_func.h +++ b/lib/wx/api_gen/wx_extra/added_func.h @@ -26,3 +26,9 @@ class WXDLLIMPEXP_AUI wxAuiPaneInfo wxPoint GetFloatingPosition(); wxSize GetFloatingSize(); }; + +class wxToolBar { + public: + wxToolBarToolBase * AddStretchableSpace(); + wxToolBarToolBase * InsertStretchableSpace(size_t pos); +}; diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index eabbec3297..f5a6751696 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -493,6 +493,8 @@ {class, wxToolBar, wxControl, [], ['AddControl','AddSeparator','AddTool','AddCheckTool','AddRadioTool', + {'AddStretchableSpace', [{test_if, "wxCHECK_VERSION(3,0,0)"}]}, + {'InsertStretchableSpace', [{test_if, "wxCHECK_VERSION(3,0,0)"}]}, 'DeleteTool','DeleteToolByPos','EnableTool','FindById','FindControl', 'FindToolForPosition','GetToolSize','GetToolBitmapSize','GetMargins', %%'GetToolClientData' , %%'SetToolClientData', diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index 4025fb1c16..b2830dbc63 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -8520,6 +8520,25 @@ data = (wxObject *) getPtr(bp,memenv); bp += 4; rt.addRef(getRef((void *)Result,memenv), "wx"); break; } +#if wxCHECK_VERSION(3,0,0) +case wxToolBar_AddStretchableSpace: { // wxToolBar::AddStretchableSpace + wxToolBar *This = (wxToolBar *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + wxToolBarToolBase * Result = (wxToolBarToolBase*)This->AddStretchableSpace(); + rt.addRef(getRef((void *)Result,memenv), "wx"); + break; +} +#endif +#if wxCHECK_VERSION(3,0,0) +case wxToolBar_InsertStretchableSpace: { // wxToolBar::InsertStretchableSpace + wxToolBar *This = (wxToolBar *) getPtr(bp,memenv); bp += 4; + int * pos = (int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + wxToolBarToolBase * Result = (wxToolBarToolBase*)This->InsertStretchableSpace(*pos); + rt.addRef(getRef((void *)Result,memenv), "wx"); + break; +} +#endif case wxToolBar_DeleteTool: { // wxToolBar::DeleteTool wxToolBar *This = (wxToolBar *) getPtr(bp,memenv); bp += 4; int * toolid = (int *) bp; bp += 4; diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h index 5f51ac5f91..1d50278360 100644 --- a/lib/wx/c_src/gen/wxe_macros.h +++ b/lib/wx/c_src/gen/wxe_macros.h @@ -912,2512 +912,2514 @@ #define wxToolBar_AddTool_6 981 #define wxToolBar_AddCheckTool 982 #define wxToolBar_AddRadioTool 983 -#define wxToolBar_DeleteTool 984 -#define wxToolBar_DeleteToolByPos 985 -#define wxToolBar_EnableTool 986 -#define wxToolBar_FindById 987 -#define wxToolBar_FindControl 988 -#define wxToolBar_FindToolForPosition 989 -#define wxToolBar_GetToolSize 990 -#define wxToolBar_GetToolBitmapSize 991 -#define wxToolBar_GetMargins 992 -#define wxToolBar_GetToolEnabled 993 -#define wxToolBar_GetToolLongHelp 994 -#define wxToolBar_GetToolPacking 995 -#define wxToolBar_GetToolPos 996 -#define wxToolBar_GetToolSeparation 997 -#define wxToolBar_GetToolShortHelp 998 -#define wxToolBar_GetToolState 999 -#define wxToolBar_InsertControl 1000 -#define wxToolBar_InsertSeparator 1001 -#define wxToolBar_InsertTool_5 1002 -#define wxToolBar_InsertTool_2 1003 -#define wxToolBar_InsertTool_4 1004 -#define wxToolBar_Realize 1005 -#define wxToolBar_RemoveTool 1006 -#define wxToolBar_SetMargins 1007 -#define wxToolBar_SetToolBitmapSize 1008 -#define wxToolBar_SetToolLongHelp 1009 -#define wxToolBar_SetToolPacking 1010 -#define wxToolBar_SetToolShortHelp 1011 -#define wxToolBar_SetToolSeparation 1012 -#define wxToolBar_ToggleTool 1013 -#define wxStatusBar_new_0 1015 -#define wxStatusBar_new_2 1016 -#define wxStatusBar_destruct 1018 -#define wxStatusBar_Create 1019 -#define wxStatusBar_GetFieldRect 1020 -#define wxStatusBar_GetFieldsCount 1021 -#define wxStatusBar_GetStatusText 1022 -#define wxStatusBar_PopStatusText 1023 -#define wxStatusBar_PushStatusText 1024 -#define wxStatusBar_SetFieldsCount 1025 -#define wxStatusBar_SetMinHeight 1026 -#define wxStatusBar_SetStatusText 1027 -#define wxStatusBar_SetStatusWidths 1028 -#define wxStatusBar_SetStatusStyles 1029 -#define wxBitmap_new_0 1030 -#define wxBitmap_new_3 1031 -#define wxBitmap_new_4 1032 -#define wxBitmap_new_2_0 1033 -#define wxBitmap_new_2_1 1034 -#define wxBitmap_destruct 1035 -#define wxBitmap_ConvertToImage 1036 -#define wxBitmap_CopyFromIcon 1037 -#define wxBitmap_Create 1038 -#define wxBitmap_GetDepth 1039 -#define wxBitmap_GetHeight 1040 -#define wxBitmap_GetPalette 1041 -#define wxBitmap_GetMask 1042 -#define wxBitmap_GetWidth 1043 -#define wxBitmap_GetSubBitmap 1044 -#define wxBitmap_LoadFile 1045 -#define wxBitmap_Ok 1046 -#define wxBitmap_SaveFile 1047 -#define wxBitmap_SetDepth 1048 -#define wxBitmap_SetHeight 1049 -#define wxBitmap_SetMask 1050 -#define wxBitmap_SetPalette 1051 -#define wxBitmap_SetWidth 1052 -#define wxIcon_new_0 1053 -#define wxIcon_new_2 1054 -#define wxIcon_new_1 1055 -#define wxIcon_CopyFromBitmap 1056 -#define wxIcon_destroy 1057 -#define wxIconBundle_new_0 1058 -#define wxIconBundle_new_2 1059 -#define wxIconBundle_new_1_0 1060 -#define wxIconBundle_new_1_1 1061 -#define wxIconBundle_destruct 1062 -#define wxIconBundle_AddIcon_2 1063 -#define wxIconBundle_AddIcon_1 1064 -#define wxIconBundle_GetIcon_1_1 1065 -#define wxIconBundle_GetIcon_1_0 1066 -#define wxCursor_new_0 1067 -#define wxCursor_new_1_0 1068 -#define wxCursor_new_1_1 1069 -#define wxCursor_new_4 1070 -#define wxCursor_destruct 1071 -#define wxCursor_Ok 1072 -#define wxMask_new_0 1073 -#define wxMask_new_2_1 1074 -#define wxMask_new_2_0 1075 -#define wxMask_new_1 1076 -#define wxMask_destruct 1077 -#define wxMask_Create_2_1 1078 -#define wxMask_Create_2_0 1079 -#define wxMask_Create_1 1080 -#define wxImage_new_0 1081 -#define wxImage_new_3_0 1082 -#define wxImage_new_4 1083 -#define wxImage_new_5 1084 -#define wxImage_new_2 1085 -#define wxImage_new_3_1 1086 -#define wxImage_Blur 1087 -#define wxImage_BlurHorizontal 1088 -#define wxImage_BlurVertical 1089 -#define wxImage_ConvertAlphaToMask 1090 -#define wxImage_ConvertToGreyscale 1091 -#define wxImage_ConvertToMono 1092 -#define wxImage_Copy 1093 -#define wxImage_Create_3 1094 -#define wxImage_Create_4 1095 -#define wxImage_Create_5 1096 -#define wxImage_Destroy 1097 -#define wxImage_FindFirstUnusedColour 1098 -#define wxImage_GetImageExtWildcard 1099 -#define wxImage_GetAlpha_2 1100 -#define wxImage_GetAlpha_0 1101 -#define wxImage_GetBlue 1102 -#define wxImage_GetData 1103 -#define wxImage_GetGreen 1104 -#define wxImage_GetImageCount 1105 -#define wxImage_GetHeight 1106 -#define wxImage_GetMaskBlue 1107 -#define wxImage_GetMaskGreen 1108 -#define wxImage_GetMaskRed 1109 -#define wxImage_GetOrFindMaskColour 1110 -#define wxImage_GetPalette 1111 -#define wxImage_GetRed 1112 -#define wxImage_GetSubImage 1113 -#define wxImage_GetWidth 1114 -#define wxImage_HasAlpha 1115 -#define wxImage_HasMask 1116 -#define wxImage_GetOption 1117 -#define wxImage_GetOptionInt 1118 -#define wxImage_HasOption 1119 -#define wxImage_InitAlpha 1120 -#define wxImage_InitStandardHandlers 1121 -#define wxImage_IsTransparent 1122 -#define wxImage_LoadFile_2 1123 -#define wxImage_LoadFile_3 1124 -#define wxImage_Ok 1125 -#define wxImage_RemoveHandler 1126 -#define wxImage_Mirror 1127 -#define wxImage_Replace 1128 -#define wxImage_Rescale 1129 -#define wxImage_Resize 1130 -#define wxImage_Rotate 1131 -#define wxImage_RotateHue 1132 -#define wxImage_Rotate90 1133 -#define wxImage_SaveFile_1 1134 -#define wxImage_SaveFile_2_0 1135 -#define wxImage_SaveFile_2_1 1136 -#define wxImage_Scale 1137 -#define wxImage_Size 1138 -#define wxImage_SetAlpha_3 1139 -#define wxImage_SetAlpha_2 1140 -#define wxImage_SetData_2 1141 -#define wxImage_SetData_4 1142 -#define wxImage_SetMask 1143 -#define wxImage_SetMaskColour 1144 -#define wxImage_SetMaskFromImage 1145 -#define wxImage_SetOption_2_1 1146 -#define wxImage_SetOption_2_0 1147 -#define wxImage_SetPalette 1148 -#define wxImage_SetRGB_5 1149 -#define wxImage_SetRGB_4 1150 -#define wxImage_destroy 1151 -#define wxBrush_new_0 1152 -#define wxBrush_new_2 1153 -#define wxBrush_new_1 1154 -#define wxBrush_destruct 1156 -#define wxBrush_GetColour 1157 -#define wxBrush_GetStipple 1158 -#define wxBrush_GetStyle 1159 -#define wxBrush_IsHatch 1160 -#define wxBrush_IsOk 1161 -#define wxBrush_SetColour_1 1162 -#define wxBrush_SetColour_3 1163 -#define wxBrush_SetStipple 1164 -#define wxBrush_SetStyle 1165 -#define wxPen_new_0 1166 -#define wxPen_new_2 1167 -#define wxPen_destruct 1168 -#define wxPen_GetCap 1169 -#define wxPen_GetColour 1170 -#define wxPen_GetJoin 1171 -#define wxPen_GetStyle 1172 -#define wxPen_GetWidth 1173 -#define wxPen_IsOk 1174 -#define wxPen_SetCap 1175 -#define wxPen_SetColour_1 1176 -#define wxPen_SetColour_3 1177 -#define wxPen_SetJoin 1178 -#define wxPen_SetStyle 1179 -#define wxPen_SetWidth 1180 -#define wxRegion_new_0 1181 -#define wxRegion_new_4 1182 -#define wxRegion_new_2 1183 -#define wxRegion_new_1_1 1184 -#define wxRegion_new_1_0 1186 -#define wxRegion_destruct 1188 -#define wxRegion_Clear 1189 -#define wxRegion_Contains_2 1190 -#define wxRegion_Contains_1_0 1191 -#define wxRegion_Contains_4 1192 -#define wxRegion_Contains_1_1 1193 -#define wxRegion_ConvertToBitmap 1194 -#define wxRegion_GetBox 1195 -#define wxRegion_Intersect_4 1196 -#define wxRegion_Intersect_1_1 1197 -#define wxRegion_Intersect_1_0 1198 -#define wxRegion_IsEmpty 1199 -#define wxRegion_Subtract_4 1200 -#define wxRegion_Subtract_1_1 1201 -#define wxRegion_Subtract_1_0 1202 -#define wxRegion_Offset_2 1203 -#define wxRegion_Offset_1 1204 -#define wxRegion_Union_4 1205 -#define wxRegion_Union_1_2 1206 -#define wxRegion_Union_1_1 1207 -#define wxRegion_Union_1_0 1208 -#define wxRegion_Union_3 1209 -#define wxRegion_Xor_4 1210 -#define wxRegion_Xor_1_1 1211 -#define wxRegion_Xor_1_0 1212 -#define wxAcceleratorTable_new_0 1213 -#define wxAcceleratorTable_new_2 1214 -#define wxAcceleratorTable_destruct 1215 -#define wxAcceleratorTable_Ok 1216 -#define wxAcceleratorEntry_new_1_0 1217 -#define wxAcceleratorEntry_new_1_1 1218 -#define wxAcceleratorEntry_GetCommand 1219 -#define wxAcceleratorEntry_GetFlags 1220 -#define wxAcceleratorEntry_GetKeyCode 1221 -#define wxAcceleratorEntry_Set 1222 -#define wxAcceleratorEntry_destroy 1223 -#define wxCaret_new_3 1228 -#define wxCaret_new_2 1229 -#define wxCaret_destruct 1231 -#define wxCaret_Create_3 1232 -#define wxCaret_Create_2 1233 -#define wxCaret_GetBlinkTime 1234 -#define wxCaret_GetPosition 1236 -#define wxCaret_GetSize 1238 -#define wxCaret_GetWindow 1239 -#define wxCaret_Hide 1240 -#define wxCaret_IsOk 1241 -#define wxCaret_IsVisible 1242 -#define wxCaret_Move_2 1243 -#define wxCaret_Move_1 1244 -#define wxCaret_SetBlinkTime 1245 -#define wxCaret_SetSize_2 1246 -#define wxCaret_SetSize_1 1247 -#define wxCaret_Show 1248 -#define wxSizer_Add_2_1 1249 -#define wxSizer_Add_2_0 1250 -#define wxSizer_Add_3 1251 -#define wxSizer_Add_2_3 1252 -#define wxSizer_Add_2_2 1253 -#define wxSizer_AddSpacer 1254 -#define wxSizer_AddStretchSpacer 1255 -#define wxSizer_CalcMin 1256 -#define wxSizer_Clear 1257 -#define wxSizer_Detach_1_2 1258 -#define wxSizer_Detach_1_1 1259 -#define wxSizer_Detach_1_0 1260 -#define wxSizer_Fit 1261 -#define wxSizer_FitInside 1262 -#define wxSizer_GetChildren 1263 -#define wxSizer_GetItem_2_1 1264 -#define wxSizer_GetItem_2_0 1265 -#define wxSizer_GetItem_1 1266 -#define wxSizer_GetSize 1267 -#define wxSizer_GetPosition 1268 -#define wxSizer_GetMinSize 1269 -#define wxSizer_Hide_2_0 1270 -#define wxSizer_Hide_2_1 1271 -#define wxSizer_Hide_1 1272 -#define wxSizer_Insert_3_1 1273 -#define wxSizer_Insert_3_0 1274 -#define wxSizer_Insert_4 1275 -#define wxSizer_Insert_3_3 1276 -#define wxSizer_Insert_3_2 1277 -#define wxSizer_Insert_2 1278 -#define wxSizer_InsertSpacer 1279 -#define wxSizer_InsertStretchSpacer 1280 -#define wxSizer_IsShown_1_2 1281 -#define wxSizer_IsShown_1_1 1282 -#define wxSizer_IsShown_1_0 1283 -#define wxSizer_Layout 1284 -#define wxSizer_Prepend_2_1 1285 -#define wxSizer_Prepend_2_0 1286 -#define wxSizer_Prepend_3 1287 -#define wxSizer_Prepend_2_3 1288 -#define wxSizer_Prepend_2_2 1289 -#define wxSizer_Prepend_1 1290 -#define wxSizer_PrependSpacer 1291 -#define wxSizer_PrependStretchSpacer 1292 -#define wxSizer_RecalcSizes 1293 -#define wxSizer_Remove_1_1 1294 -#define wxSizer_Remove_1_0 1295 -#define wxSizer_Replace_3_1 1296 -#define wxSizer_Replace_3_0 1297 -#define wxSizer_Replace_2 1298 -#define wxSizer_SetDimension 1299 -#define wxSizer_SetMinSize_2 1300 -#define wxSizer_SetMinSize_1 1301 -#define wxSizer_SetItemMinSize_3_2 1302 -#define wxSizer_SetItemMinSize_2_2 1303 -#define wxSizer_SetItemMinSize_3_1 1304 -#define wxSizer_SetItemMinSize_2_1 1305 -#define wxSizer_SetItemMinSize_3_0 1306 -#define wxSizer_SetItemMinSize_2_0 1307 -#define wxSizer_SetSizeHints 1308 -#define wxSizer_SetVirtualSizeHints 1309 -#define wxSizer_Show_2_2 1310 -#define wxSizer_Show_2_1 1311 -#define wxSizer_Show_2_0 1312 -#define wxSizer_Show_1 1313 -#define wxSizerFlags_new 1314 -#define wxSizerFlags_Align 1315 -#define wxSizerFlags_Border_2 1316 -#define wxSizerFlags_Border_1 1317 -#define wxSizerFlags_Center 1318 -#define wxSizerFlags_Centre 1319 -#define wxSizerFlags_Expand 1320 -#define wxSizerFlags_Left 1321 -#define wxSizerFlags_Proportion 1322 -#define wxSizerFlags_Right 1323 -#define wxSizerFlags_destroy 1324 -#define wxSizerItem_new_5_1 1325 -#define wxSizerItem_new_2_1 1326 -#define wxSizerItem_new_5_0 1327 -#define wxSizerItem_new_2_0 1328 -#define wxSizerItem_new_6 1329 -#define wxSizerItem_new_3 1330 -#define wxSizerItem_new_0 1331 -#define wxSizerItem_destruct 1332 -#define wxSizerItem_CalcMin 1333 -#define wxSizerItem_DeleteWindows 1334 -#define wxSizerItem_DetachSizer 1335 -#define wxSizerItem_GetBorder 1336 -#define wxSizerItem_GetFlag 1337 -#define wxSizerItem_GetMinSize 1338 -#define wxSizerItem_GetPosition 1339 -#define wxSizerItem_GetProportion 1340 -#define wxSizerItem_GetRatio 1341 -#define wxSizerItem_GetRect 1342 -#define wxSizerItem_GetSize 1343 -#define wxSizerItem_GetSizer 1344 -#define wxSizerItem_GetSpacer 1345 -#define wxSizerItem_GetUserData 1346 -#define wxSizerItem_GetWindow 1347 -#define wxSizerItem_IsSizer 1348 -#define wxSizerItem_IsShown 1349 -#define wxSizerItem_IsSpacer 1350 -#define wxSizerItem_IsWindow 1351 -#define wxSizerItem_SetBorder 1352 -#define wxSizerItem_SetDimension 1353 -#define wxSizerItem_SetFlag 1354 -#define wxSizerItem_SetInitSize 1355 -#define wxSizerItem_SetMinSize_1 1356 -#define wxSizerItem_SetMinSize_2 1357 -#define wxSizerItem_SetProportion 1358 -#define wxSizerItem_SetRatio_2 1359 -#define wxSizerItem_SetRatio_1_1 1360 -#define wxSizerItem_SetRatio_1_0 1361 -#define wxSizerItem_SetSizer 1362 -#define wxSizerItem_SetSpacer_1 1363 -#define wxSizerItem_SetSpacer_2 1364 -#define wxSizerItem_SetWindow 1365 -#define wxSizerItem_Show 1366 -#define wxBoxSizer_new 1367 -#define wxBoxSizer_GetOrientation 1368 -#define wxBoxSizer_destroy 1369 -#define wxStaticBoxSizer_new_2 1370 -#define wxStaticBoxSizer_new_3 1371 -#define wxStaticBoxSizer_GetStaticBox 1372 -#define wxStaticBoxSizer_destroy 1373 -#define wxGridSizer_new_4 1374 -#define wxGridSizer_new_2 1375 -#define wxGridSizer_GetCols 1376 -#define wxGridSizer_GetHGap 1377 -#define wxGridSizer_GetRows 1378 -#define wxGridSizer_GetVGap 1379 -#define wxGridSizer_SetCols 1380 -#define wxGridSizer_SetHGap 1381 -#define wxGridSizer_SetRows 1382 -#define wxGridSizer_SetVGap 1383 -#define wxGridSizer_destroy 1384 -#define wxFlexGridSizer_new_4 1385 -#define wxFlexGridSizer_new_2 1386 -#define wxFlexGridSizer_AddGrowableCol 1387 -#define wxFlexGridSizer_AddGrowableRow 1388 -#define wxFlexGridSizer_GetFlexibleDirection 1389 -#define wxFlexGridSizer_GetNonFlexibleGrowMode 1390 -#define wxFlexGridSizer_RemoveGrowableCol 1391 -#define wxFlexGridSizer_RemoveGrowableRow 1392 -#define wxFlexGridSizer_SetFlexibleDirection 1393 -#define wxFlexGridSizer_SetNonFlexibleGrowMode 1394 -#define wxFlexGridSizer_destroy 1395 -#define wxGridBagSizer_new 1396 -#define wxGridBagSizer_Add_3_2 1397 -#define wxGridBagSizer_Add_3_1 1398 -#define wxGridBagSizer_Add_4 1399 -#define wxGridBagSizer_Add_1_0 1400 -#define wxGridBagSizer_Add_2_1 1401 -#define wxGridBagSizer_Add_2_0 1402 -#define wxGridBagSizer_Add_3_0 1403 -#define wxGridBagSizer_Add_1_1 1404 -#define wxGridBagSizer_CalcMin 1405 -#define wxGridBagSizer_CheckForIntersection_2 1406 -#define wxGridBagSizer_CheckForIntersection_3 1407 -#define wxGridBagSizer_FindItem_1_1 1408 -#define wxGridBagSizer_FindItem_1_0 1409 -#define wxGridBagSizer_FindItemAtPoint 1410 -#define wxGridBagSizer_FindItemAtPosition 1411 -#define wxGridBagSizer_FindItemWithData 1412 -#define wxGridBagSizer_GetCellSize 1413 -#define wxGridBagSizer_GetEmptyCellSize 1414 -#define wxGridBagSizer_GetItemPosition_1_2 1415 -#define wxGridBagSizer_GetItemPosition_1_1 1416 -#define wxGridBagSizer_GetItemPosition_1_0 1417 -#define wxGridBagSizer_GetItemSpan_1_2 1418 -#define wxGridBagSizer_GetItemSpan_1_1 1419 -#define wxGridBagSizer_GetItemSpan_1_0 1420 -#define wxGridBagSizer_SetEmptyCellSize 1421 -#define wxGridBagSizer_SetItemPosition_2_2 1422 -#define wxGridBagSizer_SetItemPosition_2_1 1423 -#define wxGridBagSizer_SetItemPosition_2_0 1424 -#define wxGridBagSizer_SetItemSpan_2_2 1425 -#define wxGridBagSizer_SetItemSpan_2_1 1426 -#define wxGridBagSizer_SetItemSpan_2_0 1427 -#define wxGridBagSizer_destroy 1428 -#define wxStdDialogButtonSizer_new 1429 -#define wxStdDialogButtonSizer_AddButton 1430 -#define wxStdDialogButtonSizer_Realize 1431 -#define wxStdDialogButtonSizer_SetAffirmativeButton 1432 -#define wxStdDialogButtonSizer_SetCancelButton 1433 -#define wxStdDialogButtonSizer_SetNegativeButton 1434 -#define wxStdDialogButtonSizer_destroy 1435 -#define wxFont_new_0 1436 -#define wxFont_new_1 1437 -#define wxFont_new_5 1438 -#define wxFont_destruct 1440 -#define wxFont_IsFixedWidth 1441 -#define wxFont_GetDefaultEncoding 1442 -#define wxFont_GetFaceName 1443 -#define wxFont_GetFamily 1444 -#define wxFont_GetNativeFontInfoDesc 1445 -#define wxFont_GetNativeFontInfoUserDesc 1446 -#define wxFont_GetPointSize 1447 -#define wxFont_GetStyle 1448 -#define wxFont_GetUnderlined 1449 -#define wxFont_GetWeight 1450 -#define wxFont_Ok 1451 -#define wxFont_SetDefaultEncoding 1452 -#define wxFont_SetFaceName 1453 -#define wxFont_SetFamily 1454 -#define wxFont_SetPointSize 1455 -#define wxFont_SetStyle 1456 -#define wxFont_SetUnderlined 1457 -#define wxFont_SetWeight 1458 -#define wxToolTip_Enable 1459 -#define wxToolTip_SetDelay 1460 -#define wxToolTip_new 1461 -#define wxToolTip_SetTip 1462 -#define wxToolTip_GetTip 1463 -#define wxToolTip_GetWindow 1464 -#define wxToolTip_destroy 1465 -#define wxButton_new_3 1467 -#define wxButton_new_0 1468 -#define wxButton_destruct 1469 -#define wxButton_Create 1470 -#define wxButton_GetDefaultSize 1471 -#define wxButton_SetDefault 1472 -#define wxButton_SetLabel 1473 -#define wxBitmapButton_new_4 1475 -#define wxBitmapButton_new_0 1476 -#define wxBitmapButton_Create 1477 -#define wxBitmapButton_GetBitmapDisabled 1478 -#define wxBitmapButton_GetBitmapFocus 1480 -#define wxBitmapButton_GetBitmapLabel 1482 -#define wxBitmapButton_GetBitmapSelected 1484 -#define wxBitmapButton_SetBitmapDisabled 1486 -#define wxBitmapButton_SetBitmapFocus 1487 -#define wxBitmapButton_SetBitmapLabel 1488 -#define wxBitmapButton_SetBitmapSelected 1489 -#define wxBitmapButton_destroy 1490 -#define wxToggleButton_new_0 1491 -#define wxToggleButton_new_4 1492 -#define wxToggleButton_Create 1493 -#define wxToggleButton_GetValue 1494 -#define wxToggleButton_SetValue 1495 -#define wxToggleButton_destroy 1496 -#define wxCalendarCtrl_new_0 1497 -#define wxCalendarCtrl_new_3 1498 -#define wxCalendarCtrl_Create 1499 -#define wxCalendarCtrl_destruct 1500 -#define wxCalendarCtrl_SetDate 1501 -#define wxCalendarCtrl_GetDate 1502 -#define wxCalendarCtrl_EnableYearChange 1503 -#define wxCalendarCtrl_EnableMonthChange 1504 -#define wxCalendarCtrl_EnableHolidayDisplay 1505 -#define wxCalendarCtrl_SetHeaderColours 1506 -#define wxCalendarCtrl_GetHeaderColourFg 1507 -#define wxCalendarCtrl_GetHeaderColourBg 1508 -#define wxCalendarCtrl_SetHighlightColours 1509 -#define wxCalendarCtrl_GetHighlightColourFg 1510 -#define wxCalendarCtrl_GetHighlightColourBg 1511 -#define wxCalendarCtrl_SetHolidayColours 1512 -#define wxCalendarCtrl_GetHolidayColourFg 1513 -#define wxCalendarCtrl_GetHolidayColourBg 1514 -#define wxCalendarCtrl_GetAttr 1515 -#define wxCalendarCtrl_SetAttr 1516 -#define wxCalendarCtrl_SetHoliday 1517 -#define wxCalendarCtrl_ResetAttr 1518 -#define wxCalendarCtrl_HitTest 1519 -#define wxCalendarDateAttr_new_0 1520 -#define wxCalendarDateAttr_new_2_1 1521 -#define wxCalendarDateAttr_new_2_0 1522 -#define wxCalendarDateAttr_SetTextColour 1523 -#define wxCalendarDateAttr_SetBackgroundColour 1524 -#define wxCalendarDateAttr_SetBorderColour 1525 -#define wxCalendarDateAttr_SetFont 1526 -#define wxCalendarDateAttr_SetBorder 1527 -#define wxCalendarDateAttr_SetHoliday 1528 -#define wxCalendarDateAttr_HasTextColour 1529 -#define wxCalendarDateAttr_HasBackgroundColour 1530 -#define wxCalendarDateAttr_HasBorderColour 1531 -#define wxCalendarDateAttr_HasFont 1532 -#define wxCalendarDateAttr_HasBorder 1533 -#define wxCalendarDateAttr_IsHoliday 1534 -#define wxCalendarDateAttr_GetTextColour 1535 -#define wxCalendarDateAttr_GetBackgroundColour 1536 -#define wxCalendarDateAttr_GetBorderColour 1537 -#define wxCalendarDateAttr_GetFont 1538 -#define wxCalendarDateAttr_GetBorder 1539 -#define wxCalendarDateAttr_destroy 1540 -#define wxCheckBox_new_4 1542 -#define wxCheckBox_new_0 1543 -#define wxCheckBox_Create 1544 -#define wxCheckBox_GetValue 1545 -#define wxCheckBox_Get3StateValue 1546 -#define wxCheckBox_Is3rdStateAllowedForUser 1547 -#define wxCheckBox_Is3State 1548 -#define wxCheckBox_IsChecked 1549 -#define wxCheckBox_SetValue 1550 -#define wxCheckBox_Set3StateValue 1551 -#define wxCheckBox_destroy 1552 -#define wxCheckListBox_new_0 1553 -#define wxCheckListBox_new_3 1555 -#define wxCheckListBox_Check 1556 -#define wxCheckListBox_IsChecked 1557 -#define wxCheckListBox_destroy 1558 -#define wxChoice_new_3 1561 -#define wxChoice_new_0 1562 -#define wxChoice_destruct 1564 -#define wxChoice_Create 1566 -#define wxChoice_Delete 1567 -#define wxChoice_GetColumns 1568 -#define wxChoice_SetColumns 1569 -#define wxComboBox_new_0 1570 -#define wxComboBox_new_3 1572 -#define wxComboBox_destruct 1573 -#define wxComboBox_Create 1575 -#define wxComboBox_CanCopy 1576 -#define wxComboBox_CanCut 1577 -#define wxComboBox_CanPaste 1578 -#define wxComboBox_CanRedo 1579 -#define wxComboBox_CanUndo 1580 -#define wxComboBox_Copy 1581 -#define wxComboBox_Cut 1582 -#define wxComboBox_GetInsertionPoint 1583 -#define wxComboBox_GetLastPosition 1584 -#define wxComboBox_GetValue 1585 -#define wxComboBox_Paste 1586 -#define wxComboBox_Redo 1587 -#define wxComboBox_Replace 1588 -#define wxComboBox_Remove 1589 -#define wxComboBox_SetInsertionPoint 1590 -#define wxComboBox_SetInsertionPointEnd 1591 -#define wxComboBox_SetSelection_1 1592 -#define wxComboBox_SetSelection_2 1593 -#define wxComboBox_SetValue 1594 -#define wxComboBox_Undo 1595 -#define wxGauge_new_0 1596 -#define wxGauge_new_4 1597 -#define wxGauge_Create 1598 -#define wxGauge_GetBezelFace 1599 -#define wxGauge_GetRange 1600 -#define wxGauge_GetShadowWidth 1601 -#define wxGauge_GetValue 1602 -#define wxGauge_IsVertical 1603 -#define wxGauge_SetBezelFace 1604 -#define wxGauge_SetRange 1605 -#define wxGauge_SetShadowWidth 1606 -#define wxGauge_SetValue 1607 -#define wxGauge_Pulse 1608 -#define wxGauge_destroy 1609 -#define wxGenericDirCtrl_new_0 1610 -#define wxGenericDirCtrl_new_2 1611 -#define wxGenericDirCtrl_destruct 1612 -#define wxGenericDirCtrl_Create 1613 -#define wxGenericDirCtrl_Init 1614 -#define wxGenericDirCtrl_CollapseTree 1615 -#define wxGenericDirCtrl_ExpandPath 1616 -#define wxGenericDirCtrl_GetDefaultPath 1617 -#define wxGenericDirCtrl_GetPath 1618 -#define wxGenericDirCtrl_GetFilePath 1619 -#define wxGenericDirCtrl_GetFilter 1620 -#define wxGenericDirCtrl_GetFilterIndex 1621 -#define wxGenericDirCtrl_GetRootId 1622 -#define wxGenericDirCtrl_GetTreeCtrl 1623 -#define wxGenericDirCtrl_ReCreateTree 1624 -#define wxGenericDirCtrl_SetDefaultPath 1625 -#define wxGenericDirCtrl_SetFilter 1626 -#define wxGenericDirCtrl_SetFilterIndex 1627 -#define wxGenericDirCtrl_SetPath 1628 -#define wxStaticBox_new_4 1630 -#define wxStaticBox_new_0 1631 -#define wxStaticBox_Create 1632 -#define wxStaticBox_destroy 1633 -#define wxStaticLine_new_2 1635 -#define wxStaticLine_new_0 1636 -#define wxStaticLine_Create 1637 -#define wxStaticLine_IsVertical 1638 -#define wxStaticLine_GetDefaultSize 1639 -#define wxStaticLine_destroy 1640 -#define wxListBox_new_3 1643 -#define wxListBox_new_0 1644 -#define wxListBox_destruct 1646 -#define wxListBox_Create 1648 -#define wxListBox_Deselect 1649 -#define wxListBox_GetSelections 1650 -#define wxListBox_InsertItems 1651 -#define wxListBox_IsSelected 1652 -#define wxListBox_Set 1653 -#define wxListBox_HitTest 1654 -#define wxListBox_SetFirstItem_1_0 1655 -#define wxListBox_SetFirstItem_1_1 1656 -#define wxListCtrl_new_0 1657 -#define wxListCtrl_new_2 1658 -#define wxListCtrl_Arrange 1659 -#define wxListCtrl_AssignImageList 1660 -#define wxListCtrl_ClearAll 1661 -#define wxListCtrl_Create 1662 -#define wxListCtrl_DeleteAllItems 1663 -#define wxListCtrl_DeleteColumn 1664 -#define wxListCtrl_DeleteItem 1665 -#define wxListCtrl_EditLabel 1666 -#define wxListCtrl_EnsureVisible 1667 -#define wxListCtrl_FindItem_3_0 1668 -#define wxListCtrl_FindItem_3_1 1669 -#define wxListCtrl_GetColumn 1670 -#define wxListCtrl_GetColumnCount 1671 -#define wxListCtrl_GetColumnWidth 1672 -#define wxListCtrl_GetCountPerPage 1673 -#define wxListCtrl_GetEditControl 1674 -#define wxListCtrl_GetImageList 1675 -#define wxListCtrl_GetItem 1676 -#define wxListCtrl_GetItemBackgroundColour 1677 -#define wxListCtrl_GetItemCount 1678 -#define wxListCtrl_GetItemData 1679 -#define wxListCtrl_GetItemFont 1680 -#define wxListCtrl_GetItemPosition 1681 -#define wxListCtrl_GetItemRect 1682 -#define wxListCtrl_GetItemSpacing 1683 -#define wxListCtrl_GetItemState 1684 -#define wxListCtrl_GetItemText 1685 -#define wxListCtrl_GetItemTextColour 1686 -#define wxListCtrl_GetNextItem 1687 -#define wxListCtrl_GetSelectedItemCount 1688 -#define wxListCtrl_GetTextColour 1689 -#define wxListCtrl_GetTopItem 1690 -#define wxListCtrl_GetViewRect 1691 -#define wxListCtrl_HitTest 1692 -#define wxListCtrl_InsertColumn_2 1693 -#define wxListCtrl_InsertColumn_3 1694 -#define wxListCtrl_InsertItem_1 1695 -#define wxListCtrl_InsertItem_2_1 1696 -#define wxListCtrl_InsertItem_2_0 1697 -#define wxListCtrl_InsertItem_3 1698 -#define wxListCtrl_RefreshItem 1699 -#define wxListCtrl_RefreshItems 1700 -#define wxListCtrl_ScrollList 1701 -#define wxListCtrl_SetBackgroundColour 1702 -#define wxListCtrl_SetColumn 1703 -#define wxListCtrl_SetColumnWidth 1704 -#define wxListCtrl_SetImageList 1705 -#define wxListCtrl_SetItem_1 1706 -#define wxListCtrl_SetItem_4 1707 -#define wxListCtrl_SetItemBackgroundColour 1708 -#define wxListCtrl_SetItemCount 1709 -#define wxListCtrl_SetItemData 1710 -#define wxListCtrl_SetItemFont 1711 -#define wxListCtrl_SetItemImage 1712 -#define wxListCtrl_SetItemColumnImage 1713 -#define wxListCtrl_SetItemPosition 1714 -#define wxListCtrl_SetItemState 1715 -#define wxListCtrl_SetItemText 1716 -#define wxListCtrl_SetItemTextColour 1717 -#define wxListCtrl_SetSingleStyle 1718 -#define wxListCtrl_SetTextColour 1719 -#define wxListCtrl_SetWindowStyleFlag 1720 -#define wxListCtrl_SortItems 1721 -#define wxListCtrl_destroy 1722 -#define wxListView_ClearColumnImage 1723 -#define wxListView_Focus 1724 -#define wxListView_GetFirstSelected 1725 -#define wxListView_GetFocusedItem 1726 -#define wxListView_GetNextSelected 1727 -#define wxListView_IsSelected 1728 -#define wxListView_Select 1729 -#define wxListView_SetColumnImage 1730 -#define wxListItem_new_0 1731 -#define wxListItem_new_1 1732 -#define wxListItem_destruct 1733 -#define wxListItem_Clear 1734 -#define wxListItem_GetAlign 1735 -#define wxListItem_GetBackgroundColour 1736 -#define wxListItem_GetColumn 1737 -#define wxListItem_GetFont 1738 -#define wxListItem_GetId 1739 -#define wxListItem_GetImage 1740 -#define wxListItem_GetMask 1741 -#define wxListItem_GetState 1742 -#define wxListItem_GetText 1743 -#define wxListItem_GetTextColour 1744 -#define wxListItem_GetWidth 1745 -#define wxListItem_SetAlign 1746 -#define wxListItem_SetBackgroundColour 1747 -#define wxListItem_SetColumn 1748 -#define wxListItem_SetFont 1749 -#define wxListItem_SetId 1750 -#define wxListItem_SetImage 1751 -#define wxListItem_SetMask 1752 -#define wxListItem_SetState 1753 -#define wxListItem_SetStateMask 1754 -#define wxListItem_SetText 1755 -#define wxListItem_SetTextColour 1756 -#define wxListItem_SetWidth 1757 -#define wxListItemAttr_new_0 1758 -#define wxListItemAttr_new_3 1759 -#define wxListItemAttr_GetBackgroundColour 1760 -#define wxListItemAttr_GetFont 1761 -#define wxListItemAttr_GetTextColour 1762 -#define wxListItemAttr_HasBackgroundColour 1763 -#define wxListItemAttr_HasFont 1764 -#define wxListItemAttr_HasTextColour 1765 -#define wxListItemAttr_SetBackgroundColour 1766 -#define wxListItemAttr_SetFont 1767 -#define wxListItemAttr_SetTextColour 1768 -#define wxListItemAttr_destroy 1769 -#define wxImageList_new_0 1770 -#define wxImageList_new_3 1771 -#define wxImageList_Add_1 1772 -#define wxImageList_Add_2_0 1773 -#define wxImageList_Add_2_1 1774 -#define wxImageList_Create 1775 -#define wxImageList_Draw 1777 -#define wxImageList_GetBitmap 1778 -#define wxImageList_GetIcon 1779 -#define wxImageList_GetImageCount 1780 -#define wxImageList_GetSize 1781 -#define wxImageList_Remove 1782 -#define wxImageList_RemoveAll 1783 -#define wxImageList_Replace_2 1784 -#define wxImageList_Replace_3 1785 -#define wxImageList_destroy 1786 -#define wxTextAttr_new_0 1787 -#define wxTextAttr_new_2 1788 -#define wxTextAttr_GetAlignment 1789 -#define wxTextAttr_GetBackgroundColour 1790 -#define wxTextAttr_GetFont 1791 -#define wxTextAttr_GetLeftIndent 1792 -#define wxTextAttr_GetLeftSubIndent 1793 -#define wxTextAttr_GetRightIndent 1794 -#define wxTextAttr_GetTabs 1795 -#define wxTextAttr_GetTextColour 1796 -#define wxTextAttr_HasBackgroundColour 1797 -#define wxTextAttr_HasFont 1798 -#define wxTextAttr_HasTextColour 1799 -#define wxTextAttr_GetFlags 1800 -#define wxTextAttr_IsDefault 1801 -#define wxTextAttr_SetAlignment 1802 -#define wxTextAttr_SetBackgroundColour 1803 -#define wxTextAttr_SetFlags 1804 -#define wxTextAttr_SetFont 1805 -#define wxTextAttr_SetLeftIndent 1806 -#define wxTextAttr_SetRightIndent 1807 -#define wxTextAttr_SetTabs 1808 -#define wxTextAttr_SetTextColour 1809 -#define wxTextAttr_destroy 1810 -#define wxTextCtrl_new_3 1812 -#define wxTextCtrl_new_0 1813 -#define wxTextCtrl_destruct 1815 -#define wxTextCtrl_AppendText 1816 -#define wxTextCtrl_CanCopy 1817 -#define wxTextCtrl_CanCut 1818 -#define wxTextCtrl_CanPaste 1819 -#define wxTextCtrl_CanRedo 1820 -#define wxTextCtrl_CanUndo 1821 -#define wxTextCtrl_Clear 1822 -#define wxTextCtrl_Copy 1823 -#define wxTextCtrl_Create 1824 -#define wxTextCtrl_Cut 1825 -#define wxTextCtrl_DiscardEdits 1826 -#define wxTextCtrl_ChangeValue 1827 -#define wxTextCtrl_EmulateKeyPress 1828 -#define wxTextCtrl_GetDefaultStyle 1829 -#define wxTextCtrl_GetInsertionPoint 1830 -#define wxTextCtrl_GetLastPosition 1831 -#define wxTextCtrl_GetLineLength 1832 -#define wxTextCtrl_GetLineText 1833 -#define wxTextCtrl_GetNumberOfLines 1834 -#define wxTextCtrl_GetRange 1835 -#define wxTextCtrl_GetSelection 1836 -#define wxTextCtrl_GetStringSelection 1837 -#define wxTextCtrl_GetStyle 1838 -#define wxTextCtrl_GetValue 1839 -#define wxTextCtrl_IsEditable 1840 -#define wxTextCtrl_IsModified 1841 -#define wxTextCtrl_IsMultiLine 1842 -#define wxTextCtrl_IsSingleLine 1843 -#define wxTextCtrl_LoadFile 1844 -#define wxTextCtrl_MarkDirty 1845 -#define wxTextCtrl_Paste 1846 -#define wxTextCtrl_PositionToXY 1847 -#define wxTextCtrl_Redo 1848 -#define wxTextCtrl_Remove 1849 -#define wxTextCtrl_Replace 1850 -#define wxTextCtrl_SaveFile 1851 -#define wxTextCtrl_SetDefaultStyle 1852 -#define wxTextCtrl_SetEditable 1853 -#define wxTextCtrl_SetInsertionPoint 1854 -#define wxTextCtrl_SetInsertionPointEnd 1855 -#define wxTextCtrl_SetMaxLength 1857 -#define wxTextCtrl_SetSelection 1858 -#define wxTextCtrl_SetStyle 1859 -#define wxTextCtrl_SetValue 1860 -#define wxTextCtrl_ShowPosition 1861 -#define wxTextCtrl_Undo 1862 -#define wxTextCtrl_WriteText 1863 -#define wxTextCtrl_XYToPosition 1864 -#define wxNotebook_new_0 1867 -#define wxNotebook_new_3 1868 -#define wxNotebook_destruct 1869 -#define wxNotebook_AddPage 1870 -#define wxNotebook_AdvanceSelection 1871 -#define wxNotebook_AssignImageList 1872 -#define wxNotebook_Create 1873 -#define wxNotebook_DeleteAllPages 1874 -#define wxNotebook_DeletePage 1875 -#define wxNotebook_RemovePage 1876 -#define wxNotebook_GetCurrentPage 1877 -#define wxNotebook_GetImageList 1878 -#define wxNotebook_GetPage 1880 -#define wxNotebook_GetPageCount 1881 -#define wxNotebook_GetPageImage 1882 -#define wxNotebook_GetPageText 1883 -#define wxNotebook_GetRowCount 1884 -#define wxNotebook_GetSelection 1885 -#define wxNotebook_GetThemeBackgroundColour 1886 -#define wxNotebook_HitTest 1888 -#define wxNotebook_InsertPage 1890 -#define wxNotebook_SetImageList 1891 -#define wxNotebook_SetPadding 1892 -#define wxNotebook_SetPageSize 1893 -#define wxNotebook_SetPageImage 1894 -#define wxNotebook_SetPageText 1895 -#define wxNotebook_SetSelection 1896 -#define wxNotebook_ChangeSelection 1897 -#define wxChoicebook_new_0 1898 -#define wxChoicebook_new_3 1899 -#define wxChoicebook_AddPage 1900 -#define wxChoicebook_AdvanceSelection 1901 -#define wxChoicebook_AssignImageList 1902 -#define wxChoicebook_Create 1903 -#define wxChoicebook_DeleteAllPages 1904 -#define wxChoicebook_DeletePage 1905 -#define wxChoicebook_RemovePage 1906 -#define wxChoicebook_GetCurrentPage 1907 -#define wxChoicebook_GetImageList 1908 -#define wxChoicebook_GetPage 1910 -#define wxChoicebook_GetPageCount 1911 -#define wxChoicebook_GetPageImage 1912 -#define wxChoicebook_GetPageText 1913 -#define wxChoicebook_GetSelection 1914 -#define wxChoicebook_HitTest 1915 -#define wxChoicebook_InsertPage 1916 -#define wxChoicebook_SetImageList 1917 -#define wxChoicebook_SetPageSize 1918 -#define wxChoicebook_SetPageImage 1919 -#define wxChoicebook_SetPageText 1920 -#define wxChoicebook_SetSelection 1921 -#define wxChoicebook_ChangeSelection 1922 -#define wxChoicebook_destroy 1923 -#define wxToolbook_new_0 1924 -#define wxToolbook_new_3 1925 -#define wxToolbook_AddPage 1926 -#define wxToolbook_AdvanceSelection 1927 -#define wxToolbook_AssignImageList 1928 -#define wxToolbook_Create 1929 -#define wxToolbook_DeleteAllPages 1930 -#define wxToolbook_DeletePage 1931 -#define wxToolbook_RemovePage 1932 -#define wxToolbook_GetCurrentPage 1933 -#define wxToolbook_GetImageList 1934 -#define wxToolbook_GetPage 1936 -#define wxToolbook_GetPageCount 1937 -#define wxToolbook_GetPageImage 1938 -#define wxToolbook_GetPageText 1939 -#define wxToolbook_GetSelection 1940 -#define wxToolbook_HitTest 1942 -#define wxToolbook_InsertPage 1943 -#define wxToolbook_SetImageList 1944 -#define wxToolbook_SetPageSize 1945 -#define wxToolbook_SetPageImage 1946 -#define wxToolbook_SetPageText 1947 -#define wxToolbook_SetSelection 1948 -#define wxToolbook_ChangeSelection 1949 -#define wxToolbook_destroy 1950 -#define wxListbook_new_0 1951 -#define wxListbook_new_3 1952 -#define wxListbook_AddPage 1953 -#define wxListbook_AdvanceSelection 1954 -#define wxListbook_AssignImageList 1955 -#define wxListbook_Create 1956 -#define wxListbook_DeleteAllPages 1957 -#define wxListbook_DeletePage 1958 -#define wxListbook_RemovePage 1959 -#define wxListbook_GetCurrentPage 1960 -#define wxListbook_GetImageList 1961 -#define wxListbook_GetPage 1963 -#define wxListbook_GetPageCount 1964 -#define wxListbook_GetPageImage 1965 -#define wxListbook_GetPageText 1966 -#define wxListbook_GetSelection 1967 -#define wxListbook_HitTest 1969 -#define wxListbook_InsertPage 1970 -#define wxListbook_SetImageList 1971 -#define wxListbook_SetPageSize 1972 -#define wxListbook_SetPageImage 1973 -#define wxListbook_SetPageText 1974 -#define wxListbook_SetSelection 1975 -#define wxListbook_ChangeSelection 1976 -#define wxListbook_destroy 1977 -#define wxTreebook_new_0 1978 -#define wxTreebook_new_3 1979 -#define wxTreebook_AddPage 1980 -#define wxTreebook_AdvanceSelection 1981 -#define wxTreebook_AssignImageList 1982 -#define wxTreebook_Create 1983 -#define wxTreebook_DeleteAllPages 1984 -#define wxTreebook_DeletePage 1985 -#define wxTreebook_RemovePage 1986 -#define wxTreebook_GetCurrentPage 1987 -#define wxTreebook_GetImageList 1988 -#define wxTreebook_GetPage 1990 -#define wxTreebook_GetPageCount 1991 -#define wxTreebook_GetPageImage 1992 -#define wxTreebook_GetPageText 1993 -#define wxTreebook_GetSelection 1994 -#define wxTreebook_ExpandNode 1995 -#define wxTreebook_IsNodeExpanded 1996 -#define wxTreebook_HitTest 1998 -#define wxTreebook_InsertPage 1999 -#define wxTreebook_InsertSubPage 2000 -#define wxTreebook_SetImageList 2001 -#define wxTreebook_SetPageSize 2002 -#define wxTreebook_SetPageImage 2003 -#define wxTreebook_SetPageText 2004 -#define wxTreebook_SetSelection 2005 -#define wxTreebook_ChangeSelection 2006 -#define wxTreebook_destroy 2007 -#define wxTreeCtrl_new_2 2010 -#define wxTreeCtrl_new_0 2011 -#define wxTreeCtrl_destruct 2013 -#define wxTreeCtrl_AddRoot 2014 -#define wxTreeCtrl_AppendItem 2015 -#define wxTreeCtrl_AssignImageList 2016 -#define wxTreeCtrl_AssignStateImageList 2017 -#define wxTreeCtrl_Collapse 2018 -#define wxTreeCtrl_CollapseAndReset 2019 -#define wxTreeCtrl_Create 2020 -#define wxTreeCtrl_Delete 2021 -#define wxTreeCtrl_DeleteAllItems 2022 -#define wxTreeCtrl_DeleteChildren 2023 -#define wxTreeCtrl_EditLabel 2024 -#define wxTreeCtrl_EnsureVisible 2025 -#define wxTreeCtrl_Expand 2026 -#define wxTreeCtrl_GetBoundingRect 2027 -#define wxTreeCtrl_GetChildrenCount 2029 -#define wxTreeCtrl_GetCount 2030 -#define wxTreeCtrl_GetEditControl 2031 -#define wxTreeCtrl_GetFirstChild 2032 -#define wxTreeCtrl_GetNextChild 2033 -#define wxTreeCtrl_GetFirstVisibleItem 2034 -#define wxTreeCtrl_GetImageList 2035 -#define wxTreeCtrl_GetIndent 2036 -#define wxTreeCtrl_GetItemBackgroundColour 2037 -#define wxTreeCtrl_GetItemData 2038 -#define wxTreeCtrl_GetItemFont 2039 -#define wxTreeCtrl_GetItemImage_1 2040 -#define wxTreeCtrl_GetItemImage_2 2041 -#define wxTreeCtrl_GetItemText 2042 -#define wxTreeCtrl_GetItemTextColour 2043 -#define wxTreeCtrl_GetLastChild 2044 -#define wxTreeCtrl_GetNextSibling 2045 -#define wxTreeCtrl_GetNextVisible 2046 -#define wxTreeCtrl_GetItemParent 2047 -#define wxTreeCtrl_GetPrevSibling 2048 -#define wxTreeCtrl_GetPrevVisible 2049 -#define wxTreeCtrl_GetRootItem 2050 -#define wxTreeCtrl_GetSelection 2051 -#define wxTreeCtrl_GetSelections 2052 -#define wxTreeCtrl_GetStateImageList 2053 -#define wxTreeCtrl_HitTest 2054 -#define wxTreeCtrl_InsertItem 2056 -#define wxTreeCtrl_IsBold 2057 -#define wxTreeCtrl_IsExpanded 2058 -#define wxTreeCtrl_IsSelected 2059 -#define wxTreeCtrl_IsVisible 2060 -#define wxTreeCtrl_ItemHasChildren 2061 -#define wxTreeCtrl_IsTreeItemIdOk 2062 -#define wxTreeCtrl_PrependItem 2063 -#define wxTreeCtrl_ScrollTo 2064 -#define wxTreeCtrl_SelectItem_1 2065 -#define wxTreeCtrl_SelectItem_2 2066 -#define wxTreeCtrl_SetIndent 2067 -#define wxTreeCtrl_SetImageList 2068 -#define wxTreeCtrl_SetItemBackgroundColour 2069 -#define wxTreeCtrl_SetItemBold 2070 -#define wxTreeCtrl_SetItemData 2071 -#define wxTreeCtrl_SetItemDropHighlight 2072 -#define wxTreeCtrl_SetItemFont 2073 -#define wxTreeCtrl_SetItemHasChildren 2074 -#define wxTreeCtrl_SetItemImage_2 2075 -#define wxTreeCtrl_SetItemImage_3 2076 -#define wxTreeCtrl_SetItemText 2077 -#define wxTreeCtrl_SetItemTextColour 2078 -#define wxTreeCtrl_SetStateImageList 2079 -#define wxTreeCtrl_SetWindowStyle 2080 -#define wxTreeCtrl_SortChildren 2081 -#define wxTreeCtrl_Toggle 2082 -#define wxTreeCtrl_ToggleItemSelection 2083 -#define wxTreeCtrl_Unselect 2084 -#define wxTreeCtrl_UnselectAll 2085 -#define wxTreeCtrl_UnselectItem 2086 -#define wxScrollBar_new_0 2087 -#define wxScrollBar_new_3 2088 -#define wxScrollBar_destruct 2089 -#define wxScrollBar_Create 2090 -#define wxScrollBar_GetRange 2091 -#define wxScrollBar_GetPageSize 2092 -#define wxScrollBar_GetThumbPosition 2093 -#define wxScrollBar_GetThumbSize 2094 -#define wxScrollBar_SetThumbPosition 2095 -#define wxScrollBar_SetScrollbar 2096 -#define wxSpinButton_new_2 2098 -#define wxSpinButton_new_0 2099 -#define wxSpinButton_Create 2100 -#define wxSpinButton_GetMax 2101 -#define wxSpinButton_GetMin 2102 -#define wxSpinButton_GetValue 2103 -#define wxSpinButton_SetRange 2104 -#define wxSpinButton_SetValue 2105 -#define wxSpinButton_destroy 2106 -#define wxSpinCtrl_new_0 2107 -#define wxSpinCtrl_new_2 2108 -#define wxSpinCtrl_Create 2110 -#define wxSpinCtrl_SetValue_1_1 2113 -#define wxSpinCtrl_SetValue_1_0 2114 -#define wxSpinCtrl_GetValue 2116 -#define wxSpinCtrl_SetRange 2118 -#define wxSpinCtrl_SetSelection 2119 -#define wxSpinCtrl_GetMin 2121 -#define wxSpinCtrl_GetMax 2123 -#define wxSpinCtrl_destroy 2124 -#define wxStaticText_new_0 2125 -#define wxStaticText_new_4 2126 -#define wxStaticText_Create 2127 -#define wxStaticText_GetLabel 2128 -#define wxStaticText_SetLabel 2129 -#define wxStaticText_Wrap 2130 -#define wxStaticText_destroy 2131 -#define wxStaticBitmap_new_0 2132 -#define wxStaticBitmap_new_4 2133 -#define wxStaticBitmap_Create 2134 -#define wxStaticBitmap_GetBitmap 2135 -#define wxStaticBitmap_SetBitmap 2136 -#define wxStaticBitmap_destroy 2137 -#define wxRadioBox_new 2138 -#define wxRadioBox_destruct 2140 -#define wxRadioBox_Create 2141 -#define wxRadioBox_Enable_2 2142 -#define wxRadioBox_Enable_1 2143 -#define wxRadioBox_GetSelection 2144 -#define wxRadioBox_GetString 2145 -#define wxRadioBox_SetSelection 2146 -#define wxRadioBox_Show_2 2147 -#define wxRadioBox_Show_1 2148 -#define wxRadioBox_GetColumnCount 2149 -#define wxRadioBox_GetItemHelpText 2150 -#define wxRadioBox_GetItemToolTip 2151 -#define wxRadioBox_GetItemFromPoint 2153 -#define wxRadioBox_GetRowCount 2154 -#define wxRadioBox_IsItemEnabled 2155 -#define wxRadioBox_IsItemShown 2156 -#define wxRadioBox_SetItemHelpText 2157 -#define wxRadioBox_SetItemToolTip 2158 -#define wxRadioButton_new_0 2159 -#define wxRadioButton_new_4 2160 -#define wxRadioButton_Create 2161 -#define wxRadioButton_GetValue 2162 -#define wxRadioButton_SetValue 2163 -#define wxRadioButton_destroy 2164 -#define wxSlider_new_6 2166 -#define wxSlider_new_0 2167 -#define wxSlider_Create 2168 -#define wxSlider_GetLineSize 2169 -#define wxSlider_GetMax 2170 -#define wxSlider_GetMin 2171 -#define wxSlider_GetPageSize 2172 -#define wxSlider_GetThumbLength 2173 -#define wxSlider_GetValue 2174 -#define wxSlider_SetLineSize 2175 -#define wxSlider_SetPageSize 2176 -#define wxSlider_SetRange 2177 -#define wxSlider_SetThumbLength 2178 -#define wxSlider_SetValue 2179 -#define wxSlider_destroy 2180 -#define wxDialog_new_4 2182 -#define wxDialog_new_0 2183 -#define wxDialog_destruct 2185 -#define wxDialog_Create 2186 -#define wxDialog_CreateButtonSizer 2187 -#define wxDialog_CreateStdDialogButtonSizer 2188 -#define wxDialog_EndModal 2189 -#define wxDialog_GetAffirmativeId 2190 -#define wxDialog_GetReturnCode 2191 -#define wxDialog_IsModal 2192 -#define wxDialog_SetAffirmativeId 2193 -#define wxDialog_SetReturnCode 2194 -#define wxDialog_Show 2195 -#define wxDialog_ShowModal 2196 -#define wxColourDialog_new_0 2197 -#define wxColourDialog_new_2 2198 -#define wxColourDialog_destruct 2199 -#define wxColourDialog_Create 2200 -#define wxColourDialog_GetColourData 2201 -#define wxColourData_new_0 2202 -#define wxColourData_new_1 2203 -#define wxColourData_destruct 2204 -#define wxColourData_GetChooseFull 2205 -#define wxColourData_GetColour 2206 -#define wxColourData_GetCustomColour 2208 -#define wxColourData_SetChooseFull 2209 -#define wxColourData_SetColour 2210 -#define wxColourData_SetCustomColour 2211 -#define wxPalette_new_0 2212 -#define wxPalette_new_4 2213 -#define wxPalette_destruct 2215 -#define wxPalette_Create 2216 -#define wxPalette_GetColoursCount 2217 -#define wxPalette_GetPixel 2218 -#define wxPalette_GetRGB 2219 -#define wxPalette_IsOk 2220 -#define wxDirDialog_new 2224 -#define wxDirDialog_destruct 2225 -#define wxDirDialog_GetPath 2226 -#define wxDirDialog_GetMessage 2227 -#define wxDirDialog_SetMessage 2228 -#define wxDirDialog_SetPath 2229 -#define wxFileDialog_new 2233 -#define wxFileDialog_destruct 2234 -#define wxFileDialog_GetDirectory 2235 -#define wxFileDialog_GetFilename 2236 -#define wxFileDialog_GetFilenames 2237 -#define wxFileDialog_GetFilterIndex 2238 -#define wxFileDialog_GetMessage 2239 -#define wxFileDialog_GetPath 2240 -#define wxFileDialog_GetPaths 2241 -#define wxFileDialog_GetWildcard 2242 -#define wxFileDialog_SetDirectory 2243 -#define wxFileDialog_SetFilename 2244 -#define wxFileDialog_SetFilterIndex 2245 -#define wxFileDialog_SetMessage 2246 -#define wxFileDialog_SetPath 2247 -#define wxFileDialog_SetWildcard 2248 -#define wxPickerBase_SetInternalMargin 2249 -#define wxPickerBase_GetInternalMargin 2250 -#define wxPickerBase_SetTextCtrlProportion 2251 -#define wxPickerBase_SetPickerCtrlProportion 2252 -#define wxPickerBase_GetTextCtrlProportion 2253 -#define wxPickerBase_GetPickerCtrlProportion 2254 -#define wxPickerBase_HasTextCtrl 2255 -#define wxPickerBase_GetTextCtrl 2256 -#define wxPickerBase_IsTextCtrlGrowable 2257 -#define wxPickerBase_SetPickerCtrlGrowable 2258 -#define wxPickerBase_SetTextCtrlGrowable 2259 -#define wxPickerBase_IsPickerCtrlGrowable 2260 -#define wxFilePickerCtrl_new_0 2261 -#define wxFilePickerCtrl_new_3 2262 -#define wxFilePickerCtrl_Create 2263 -#define wxFilePickerCtrl_GetPath 2264 -#define wxFilePickerCtrl_SetPath 2265 -#define wxFilePickerCtrl_destroy 2266 -#define wxDirPickerCtrl_new_0 2267 -#define wxDirPickerCtrl_new_3 2268 -#define wxDirPickerCtrl_Create 2269 -#define wxDirPickerCtrl_GetPath 2270 -#define wxDirPickerCtrl_SetPath 2271 -#define wxDirPickerCtrl_destroy 2272 -#define wxColourPickerCtrl_new_0 2273 -#define wxColourPickerCtrl_new_3 2274 -#define wxColourPickerCtrl_Create 2275 -#define wxColourPickerCtrl_GetColour 2276 -#define wxColourPickerCtrl_SetColour_1_1 2277 -#define wxColourPickerCtrl_SetColour_1_0 2278 -#define wxColourPickerCtrl_destroy 2279 -#define wxDatePickerCtrl_new_0 2280 -#define wxDatePickerCtrl_new_3 2281 -#define wxDatePickerCtrl_GetRange 2282 -#define wxDatePickerCtrl_GetValue 2283 -#define wxDatePickerCtrl_SetRange 2284 -#define wxDatePickerCtrl_SetValue 2285 -#define wxDatePickerCtrl_destroy 2286 -#define wxFontPickerCtrl_new_0 2287 -#define wxFontPickerCtrl_new_3 2288 -#define wxFontPickerCtrl_Create 2289 -#define wxFontPickerCtrl_GetSelectedFont 2290 -#define wxFontPickerCtrl_SetSelectedFont 2291 -#define wxFontPickerCtrl_GetMaxPointSize 2292 -#define wxFontPickerCtrl_SetMaxPointSize 2293 -#define wxFontPickerCtrl_destroy 2294 -#define wxFindReplaceDialog_new_0 2297 -#define wxFindReplaceDialog_new_4 2298 -#define wxFindReplaceDialog_destruct 2299 -#define wxFindReplaceDialog_Create 2300 -#define wxFindReplaceDialog_GetData 2301 -#define wxFindReplaceData_new_0 2302 -#define wxFindReplaceData_new_1 2303 -#define wxFindReplaceData_GetFindString 2304 -#define wxFindReplaceData_GetReplaceString 2305 -#define wxFindReplaceData_GetFlags 2306 -#define wxFindReplaceData_SetFlags 2307 -#define wxFindReplaceData_SetFindString 2308 -#define wxFindReplaceData_SetReplaceString 2309 -#define wxFindReplaceData_destroy 2310 -#define wxMultiChoiceDialog_new_0 2311 -#define wxMultiChoiceDialog_new_5 2313 -#define wxMultiChoiceDialog_GetSelections 2314 -#define wxMultiChoiceDialog_SetSelections 2315 -#define wxMultiChoiceDialog_destroy 2316 -#define wxSingleChoiceDialog_new_0 2317 -#define wxSingleChoiceDialog_new_5 2319 -#define wxSingleChoiceDialog_GetSelection 2320 -#define wxSingleChoiceDialog_GetStringSelection 2321 -#define wxSingleChoiceDialog_SetSelection 2322 -#define wxSingleChoiceDialog_destroy 2323 -#define wxTextEntryDialog_new 2324 -#define wxTextEntryDialog_GetValue 2325 -#define wxTextEntryDialog_SetValue 2326 -#define wxTextEntryDialog_destroy 2327 -#define wxPasswordEntryDialog_new 2328 -#define wxPasswordEntryDialog_destroy 2329 -#define wxFontData_new_0 2330 -#define wxFontData_new_1 2331 -#define wxFontData_destruct 2332 -#define wxFontData_EnableEffects 2333 -#define wxFontData_GetAllowSymbols 2334 -#define wxFontData_GetColour 2335 -#define wxFontData_GetChosenFont 2336 -#define wxFontData_GetEnableEffects 2337 -#define wxFontData_GetInitialFont 2338 -#define wxFontData_GetShowHelp 2339 -#define wxFontData_SetAllowSymbols 2340 -#define wxFontData_SetChosenFont 2341 -#define wxFontData_SetColour 2342 -#define wxFontData_SetInitialFont 2343 -#define wxFontData_SetRange 2344 -#define wxFontData_SetShowHelp 2345 -#define wxFontDialog_new_0 2349 -#define wxFontDialog_new_2 2351 -#define wxFontDialog_Create 2353 -#define wxFontDialog_GetFontData 2354 -#define wxFontDialog_destroy 2356 -#define wxProgressDialog_new 2357 -#define wxProgressDialog_destruct 2358 -#define wxProgressDialog_Resume 2359 -#define wxProgressDialog_Update_2 2360 -#define wxProgressDialog_Update_0 2361 -#define wxMessageDialog_new 2362 -#define wxMessageDialog_destruct 2363 -#define wxPageSetupDialog_new 2364 -#define wxPageSetupDialog_destruct 2365 -#define wxPageSetupDialog_GetPageSetupData 2366 -#define wxPageSetupDialog_ShowModal 2367 -#define wxPageSetupDialogData_new_0 2368 -#define wxPageSetupDialogData_new_1_0 2369 -#define wxPageSetupDialogData_new_1_1 2370 -#define wxPageSetupDialogData_destruct 2371 -#define wxPageSetupDialogData_EnableHelp 2372 -#define wxPageSetupDialogData_EnableMargins 2373 -#define wxPageSetupDialogData_EnableOrientation 2374 -#define wxPageSetupDialogData_EnablePaper 2375 -#define wxPageSetupDialogData_EnablePrinter 2376 -#define wxPageSetupDialogData_GetDefaultMinMargins 2377 -#define wxPageSetupDialogData_GetEnableMargins 2378 -#define wxPageSetupDialogData_GetEnableOrientation 2379 -#define wxPageSetupDialogData_GetEnablePaper 2380 -#define wxPageSetupDialogData_GetEnablePrinter 2381 -#define wxPageSetupDialogData_GetEnableHelp 2382 -#define wxPageSetupDialogData_GetDefaultInfo 2383 -#define wxPageSetupDialogData_GetMarginTopLeft 2384 -#define wxPageSetupDialogData_GetMarginBottomRight 2385 -#define wxPageSetupDialogData_GetMinMarginTopLeft 2386 -#define wxPageSetupDialogData_GetMinMarginBottomRight 2387 -#define wxPageSetupDialogData_GetPaperId 2388 -#define wxPageSetupDialogData_GetPaperSize 2389 -#define wxPageSetupDialogData_GetPrintData 2391 -#define wxPageSetupDialogData_IsOk 2392 -#define wxPageSetupDialogData_SetDefaultInfo 2393 -#define wxPageSetupDialogData_SetDefaultMinMargins 2394 -#define wxPageSetupDialogData_SetMarginTopLeft 2395 -#define wxPageSetupDialogData_SetMarginBottomRight 2396 -#define wxPageSetupDialogData_SetMinMarginTopLeft 2397 -#define wxPageSetupDialogData_SetMinMarginBottomRight 2398 -#define wxPageSetupDialogData_SetPaperId 2399 -#define wxPageSetupDialogData_SetPaperSize_1_1 2400 -#define wxPageSetupDialogData_SetPaperSize_1_0 2401 -#define wxPageSetupDialogData_SetPrintData 2402 -#define wxPrintDialog_new_2_0 2403 -#define wxPrintDialog_new_2_1 2404 -#define wxPrintDialog_destruct 2405 -#define wxPrintDialog_GetPrintDialogData 2406 -#define wxPrintDialog_GetPrintDC 2407 -#define wxPrintDialogData_new_0 2408 -#define wxPrintDialogData_new_1_1 2409 -#define wxPrintDialogData_new_1_0 2410 -#define wxPrintDialogData_destruct 2411 -#define wxPrintDialogData_EnableHelp 2412 -#define wxPrintDialogData_EnablePageNumbers 2413 -#define wxPrintDialogData_EnablePrintToFile 2414 -#define wxPrintDialogData_EnableSelection 2415 -#define wxPrintDialogData_GetAllPages 2416 -#define wxPrintDialogData_GetCollate 2417 -#define wxPrintDialogData_GetFromPage 2418 -#define wxPrintDialogData_GetMaxPage 2419 -#define wxPrintDialogData_GetMinPage 2420 -#define wxPrintDialogData_GetNoCopies 2421 -#define wxPrintDialogData_GetPrintData 2422 -#define wxPrintDialogData_GetPrintToFile 2423 -#define wxPrintDialogData_GetSelection 2424 -#define wxPrintDialogData_GetToPage 2425 -#define wxPrintDialogData_IsOk 2426 -#define wxPrintDialogData_SetCollate 2427 -#define wxPrintDialogData_SetFromPage 2428 -#define wxPrintDialogData_SetMaxPage 2429 -#define wxPrintDialogData_SetMinPage 2430 -#define wxPrintDialogData_SetNoCopies 2431 -#define wxPrintDialogData_SetPrintData 2432 -#define wxPrintDialogData_SetPrintToFile 2433 -#define wxPrintDialogData_SetSelection 2434 -#define wxPrintDialogData_SetToPage 2435 -#define wxPrintData_new_0 2436 -#define wxPrintData_new_1 2437 -#define wxPrintData_destruct 2438 -#define wxPrintData_GetCollate 2439 -#define wxPrintData_GetBin 2440 -#define wxPrintData_GetColour 2441 -#define wxPrintData_GetDuplex 2442 -#define wxPrintData_GetNoCopies 2443 -#define wxPrintData_GetOrientation 2444 -#define wxPrintData_GetPaperId 2445 -#define wxPrintData_GetPrinterName 2446 -#define wxPrintData_GetQuality 2447 -#define wxPrintData_IsOk 2448 -#define wxPrintData_SetBin 2449 -#define wxPrintData_SetCollate 2450 -#define wxPrintData_SetColour 2451 -#define wxPrintData_SetDuplex 2452 -#define wxPrintData_SetNoCopies 2453 -#define wxPrintData_SetOrientation 2454 -#define wxPrintData_SetPaperId 2455 -#define wxPrintData_SetPrinterName 2456 -#define wxPrintData_SetQuality 2457 -#define wxPrintPreview_new_2 2460 -#define wxPrintPreview_new_3 2461 -#define wxPrintPreview_destruct 2463 -#define wxPrintPreview_GetCanvas 2464 -#define wxPrintPreview_GetCurrentPage 2465 -#define wxPrintPreview_GetFrame 2466 -#define wxPrintPreview_GetMaxPage 2467 -#define wxPrintPreview_GetMinPage 2468 -#define wxPrintPreview_GetPrintout 2469 -#define wxPrintPreview_GetPrintoutForPrinting 2470 -#define wxPrintPreview_IsOk 2471 -#define wxPrintPreview_PaintPage 2472 -#define wxPrintPreview_Print 2473 -#define wxPrintPreview_RenderPage 2474 -#define wxPrintPreview_SetCanvas 2475 -#define wxPrintPreview_SetCurrentPage 2476 -#define wxPrintPreview_SetFrame 2477 -#define wxPrintPreview_SetPrintout 2478 -#define wxPrintPreview_SetZoom 2479 -#define wxPreviewFrame_new 2480 -#define wxPreviewFrame_destruct 2481 -#define wxPreviewFrame_CreateControlBar 2482 -#define wxPreviewFrame_CreateCanvas 2483 -#define wxPreviewFrame_Initialize 2484 -#define wxPreviewFrame_OnCloseWindow 2485 -#define wxPreviewControlBar_new 2486 -#define wxPreviewControlBar_destruct 2487 -#define wxPreviewControlBar_CreateButtons 2488 -#define wxPreviewControlBar_GetPrintPreview 2489 -#define wxPreviewControlBar_GetZoomControl 2490 -#define wxPreviewControlBar_SetZoomControl 2491 -#define wxPrinter_new 2493 -#define wxPrinter_CreateAbortWindow 2494 -#define wxPrinter_GetAbort 2495 -#define wxPrinter_GetLastError 2496 -#define wxPrinter_GetPrintDialogData 2497 -#define wxPrinter_Print 2498 -#define wxPrinter_PrintDialog 2499 -#define wxPrinter_ReportError 2500 -#define wxPrinter_Setup 2501 -#define wxPrinter_destroy 2502 -#define wxXmlResource_new_1 2503 -#define wxXmlResource_new_2 2504 -#define wxXmlResource_destruct 2505 -#define wxXmlResource_AttachUnknownControl 2506 -#define wxXmlResource_ClearHandlers 2507 -#define wxXmlResource_CompareVersion 2508 -#define wxXmlResource_Get 2509 -#define wxXmlResource_GetFlags 2510 -#define wxXmlResource_GetVersion 2511 -#define wxXmlResource_GetXRCID 2512 -#define wxXmlResource_InitAllHandlers 2513 -#define wxXmlResource_Load 2514 -#define wxXmlResource_LoadBitmap 2515 -#define wxXmlResource_LoadDialog_2 2516 -#define wxXmlResource_LoadDialog_3 2517 -#define wxXmlResource_LoadFrame_2 2518 -#define wxXmlResource_LoadFrame_3 2519 -#define wxXmlResource_LoadIcon 2520 -#define wxXmlResource_LoadMenu 2521 -#define wxXmlResource_LoadMenuBar_2 2522 -#define wxXmlResource_LoadMenuBar_1 2523 -#define wxXmlResource_LoadPanel_2 2524 -#define wxXmlResource_LoadPanel_3 2525 -#define wxXmlResource_LoadToolBar 2526 -#define wxXmlResource_Set 2527 -#define wxXmlResource_SetFlags 2528 -#define wxXmlResource_Unload 2529 -#define wxXmlResource_xrcctrl 2530 -#define wxHtmlEasyPrinting_new 2531 -#define wxHtmlEasyPrinting_destruct 2532 -#define wxHtmlEasyPrinting_GetPrintData 2533 -#define wxHtmlEasyPrinting_GetPageSetupData 2534 -#define wxHtmlEasyPrinting_PreviewFile 2535 -#define wxHtmlEasyPrinting_PreviewText 2536 -#define wxHtmlEasyPrinting_PrintFile 2537 -#define wxHtmlEasyPrinting_PrintText 2538 -#define wxHtmlEasyPrinting_PageSetup 2539 -#define wxHtmlEasyPrinting_SetFonts 2540 -#define wxHtmlEasyPrinting_SetHeader 2541 -#define wxHtmlEasyPrinting_SetFooter 2542 -#define wxGLCanvas_new_2 2544 -#define wxGLCanvas_new_3_1 2545 -#define wxGLCanvas_new_3_0 2546 -#define wxGLCanvas_GetContext 2547 -#define wxGLCanvas_SetCurrent 2549 -#define wxGLCanvas_SwapBuffers 2550 -#define wxGLCanvas_destroy 2551 -#define wxAuiManager_new 2552 -#define wxAuiManager_destruct 2553 -#define wxAuiManager_AddPane_2_1 2554 -#define wxAuiManager_AddPane_3 2555 -#define wxAuiManager_AddPane_2_0 2556 -#define wxAuiManager_DetachPane 2557 -#define wxAuiManager_GetAllPanes 2558 -#define wxAuiManager_GetArtProvider 2559 -#define wxAuiManager_GetDockSizeConstraint 2560 -#define wxAuiManager_GetFlags 2561 -#define wxAuiManager_GetManagedWindow 2562 -#define wxAuiManager_GetManager 2563 -#define wxAuiManager_GetPane_1_1 2564 -#define wxAuiManager_GetPane_1_0 2565 -#define wxAuiManager_HideHint 2566 -#define wxAuiManager_InsertPane 2567 -#define wxAuiManager_LoadPaneInfo 2568 -#define wxAuiManager_LoadPerspective 2569 -#define wxAuiManager_SavePaneInfo 2570 -#define wxAuiManager_SavePerspective 2571 -#define wxAuiManager_SetArtProvider 2572 -#define wxAuiManager_SetDockSizeConstraint 2573 -#define wxAuiManager_SetFlags 2574 -#define wxAuiManager_SetManagedWindow 2575 -#define wxAuiManager_ShowHint 2576 -#define wxAuiManager_UnInit 2577 -#define wxAuiManager_Update 2578 -#define wxAuiPaneInfo_new_0 2579 -#define wxAuiPaneInfo_new_1 2580 -#define wxAuiPaneInfo_destruct 2581 -#define wxAuiPaneInfo_BestSize_1 2582 -#define wxAuiPaneInfo_BestSize_2 2583 -#define wxAuiPaneInfo_Bottom 2584 -#define wxAuiPaneInfo_BottomDockable 2585 -#define wxAuiPaneInfo_Caption 2586 -#define wxAuiPaneInfo_CaptionVisible 2587 -#define wxAuiPaneInfo_Centre 2588 -#define wxAuiPaneInfo_CentrePane 2589 -#define wxAuiPaneInfo_CloseButton 2590 -#define wxAuiPaneInfo_DefaultPane 2591 -#define wxAuiPaneInfo_DestroyOnClose 2592 -#define wxAuiPaneInfo_Direction 2593 -#define wxAuiPaneInfo_Dock 2594 -#define wxAuiPaneInfo_Dockable 2595 -#define wxAuiPaneInfo_Fixed 2596 -#define wxAuiPaneInfo_Float 2597 -#define wxAuiPaneInfo_Floatable 2598 -#define wxAuiPaneInfo_FloatingPosition_1 2599 -#define wxAuiPaneInfo_FloatingPosition_2 2600 -#define wxAuiPaneInfo_FloatingSize_1 2601 -#define wxAuiPaneInfo_FloatingSize_2 2602 -#define wxAuiPaneInfo_Gripper 2603 -#define wxAuiPaneInfo_GripperTop 2604 -#define wxAuiPaneInfo_HasBorder 2605 -#define wxAuiPaneInfo_HasCaption 2606 -#define wxAuiPaneInfo_HasCloseButton 2607 -#define wxAuiPaneInfo_HasFlag 2608 -#define wxAuiPaneInfo_HasGripper 2609 -#define wxAuiPaneInfo_HasGripperTop 2610 -#define wxAuiPaneInfo_HasMaximizeButton 2611 -#define wxAuiPaneInfo_HasMinimizeButton 2612 -#define wxAuiPaneInfo_HasPinButton 2613 -#define wxAuiPaneInfo_Hide 2614 -#define wxAuiPaneInfo_IsBottomDockable 2615 -#define wxAuiPaneInfo_IsDocked 2616 -#define wxAuiPaneInfo_IsFixed 2617 -#define wxAuiPaneInfo_IsFloatable 2618 -#define wxAuiPaneInfo_IsFloating 2619 -#define wxAuiPaneInfo_IsLeftDockable 2620 -#define wxAuiPaneInfo_IsMovable 2621 -#define wxAuiPaneInfo_IsOk 2622 -#define wxAuiPaneInfo_IsResizable 2623 -#define wxAuiPaneInfo_IsRightDockable 2624 -#define wxAuiPaneInfo_IsShown 2625 -#define wxAuiPaneInfo_IsToolbar 2626 -#define wxAuiPaneInfo_IsTopDockable 2627 -#define wxAuiPaneInfo_Layer 2628 -#define wxAuiPaneInfo_Left 2629 -#define wxAuiPaneInfo_LeftDockable 2630 -#define wxAuiPaneInfo_MaxSize_1 2631 -#define wxAuiPaneInfo_MaxSize_2 2632 -#define wxAuiPaneInfo_MaximizeButton 2633 -#define wxAuiPaneInfo_MinSize_1 2634 -#define wxAuiPaneInfo_MinSize_2 2635 -#define wxAuiPaneInfo_MinimizeButton 2636 -#define wxAuiPaneInfo_Movable 2637 -#define wxAuiPaneInfo_Name 2638 -#define wxAuiPaneInfo_PaneBorder 2639 -#define wxAuiPaneInfo_PinButton 2640 -#define wxAuiPaneInfo_Position 2641 -#define wxAuiPaneInfo_Resizable 2642 -#define wxAuiPaneInfo_Right 2643 -#define wxAuiPaneInfo_RightDockable 2644 -#define wxAuiPaneInfo_Row 2645 -#define wxAuiPaneInfo_SafeSet 2646 -#define wxAuiPaneInfo_SetFlag 2647 -#define wxAuiPaneInfo_Show 2648 -#define wxAuiPaneInfo_ToolbarPane 2649 -#define wxAuiPaneInfo_Top 2650 -#define wxAuiPaneInfo_TopDockable 2651 -#define wxAuiPaneInfo_Window 2652 -#define wxAuiPaneInfo_GetWindow 2653 -#define wxAuiPaneInfo_GetFrame 2654 -#define wxAuiPaneInfo_GetDirection 2655 -#define wxAuiPaneInfo_GetLayer 2656 -#define wxAuiPaneInfo_GetRow 2657 -#define wxAuiPaneInfo_GetPosition 2658 -#define wxAuiPaneInfo_GetFloatingPosition 2659 -#define wxAuiPaneInfo_GetFloatingSize 2660 -#define wxAuiNotebook_new_0 2661 -#define wxAuiNotebook_new_2 2662 -#define wxAuiNotebook_AddPage 2663 -#define wxAuiNotebook_Create 2664 -#define wxAuiNotebook_DeletePage 2665 -#define wxAuiNotebook_GetArtProvider 2666 -#define wxAuiNotebook_GetPage 2667 -#define wxAuiNotebook_GetPageBitmap 2668 -#define wxAuiNotebook_GetPageCount 2669 -#define wxAuiNotebook_GetPageIndex 2670 -#define wxAuiNotebook_GetPageText 2671 -#define wxAuiNotebook_GetSelection 2672 -#define wxAuiNotebook_InsertPage 2673 -#define wxAuiNotebook_RemovePage 2674 -#define wxAuiNotebook_SetArtProvider 2675 -#define wxAuiNotebook_SetFont 2676 -#define wxAuiNotebook_SetPageBitmap 2677 -#define wxAuiNotebook_SetPageText 2678 -#define wxAuiNotebook_SetSelection 2679 -#define wxAuiNotebook_SetTabCtrlHeight 2680 -#define wxAuiNotebook_SetUniformBitmapSize 2681 -#define wxAuiNotebook_destroy 2682 -#define wxAuiTabArt_SetFlags 2683 -#define wxAuiTabArt_SetMeasuringFont 2684 -#define wxAuiTabArt_SetNormalFont 2685 -#define wxAuiTabArt_SetSelectedFont 2686 -#define wxAuiTabArt_SetColour 2687 -#define wxAuiTabArt_SetActiveColour 2688 -#define wxAuiDockArt_GetColour 2689 -#define wxAuiDockArt_GetFont 2690 -#define wxAuiDockArt_GetMetric 2691 -#define wxAuiDockArt_SetColour 2692 -#define wxAuiDockArt_SetFont 2693 -#define wxAuiDockArt_SetMetric 2694 -#define wxAuiSimpleTabArt_new 2695 -#define wxAuiSimpleTabArt_destroy 2696 -#define wxMDIParentFrame_new_0 2697 -#define wxMDIParentFrame_new_4 2698 -#define wxMDIParentFrame_destruct 2699 -#define wxMDIParentFrame_ActivateNext 2700 -#define wxMDIParentFrame_ActivatePrevious 2701 -#define wxMDIParentFrame_ArrangeIcons 2702 -#define wxMDIParentFrame_Cascade 2703 -#define wxMDIParentFrame_Create 2704 -#define wxMDIParentFrame_GetActiveChild 2705 -#define wxMDIParentFrame_GetClientWindow 2706 -#define wxMDIParentFrame_Tile 2707 -#define wxMDIChildFrame_new_0 2708 -#define wxMDIChildFrame_new_4 2709 -#define wxMDIChildFrame_destruct 2710 -#define wxMDIChildFrame_Activate 2711 -#define wxMDIChildFrame_Create 2712 -#define wxMDIChildFrame_Maximize 2713 -#define wxMDIChildFrame_Restore 2714 -#define wxMDIClientWindow_new_0 2715 -#define wxMDIClientWindow_new_2 2716 -#define wxMDIClientWindow_destruct 2717 -#define wxMDIClientWindow_CreateClient 2718 -#define wxLayoutAlgorithm_new 2719 -#define wxLayoutAlgorithm_LayoutFrame 2720 -#define wxLayoutAlgorithm_LayoutMDIFrame 2721 -#define wxLayoutAlgorithm_LayoutWindow 2722 -#define wxLayoutAlgorithm_destroy 2723 -#define wxEvent_GetId 2724 -#define wxEvent_GetSkipped 2725 -#define wxEvent_GetTimestamp 2726 -#define wxEvent_IsCommandEvent 2727 -#define wxEvent_ResumePropagation 2728 -#define wxEvent_ShouldPropagate 2729 -#define wxEvent_Skip 2730 -#define wxEvent_StopPropagation 2731 -#define wxCommandEvent_getClientData 2732 -#define wxCommandEvent_GetExtraLong 2733 -#define wxCommandEvent_GetInt 2734 -#define wxCommandEvent_GetSelection 2735 -#define wxCommandEvent_GetString 2736 -#define wxCommandEvent_IsChecked 2737 -#define wxCommandEvent_IsSelection 2738 -#define wxCommandEvent_SetInt 2739 -#define wxCommandEvent_SetString 2740 -#define wxScrollEvent_GetOrientation 2741 -#define wxScrollEvent_GetPosition 2742 -#define wxScrollWinEvent_GetOrientation 2743 -#define wxScrollWinEvent_GetPosition 2744 -#define wxMouseEvent_AltDown 2745 -#define wxMouseEvent_Button 2746 -#define wxMouseEvent_ButtonDClick 2747 -#define wxMouseEvent_ButtonDown 2748 -#define wxMouseEvent_ButtonUp 2749 -#define wxMouseEvent_CmdDown 2750 -#define wxMouseEvent_ControlDown 2751 -#define wxMouseEvent_Dragging 2752 -#define wxMouseEvent_Entering 2753 -#define wxMouseEvent_GetButton 2754 -#define wxMouseEvent_GetPosition 2757 -#define wxMouseEvent_GetLogicalPosition 2758 -#define wxMouseEvent_GetLinesPerAction 2759 -#define wxMouseEvent_GetWheelRotation 2760 -#define wxMouseEvent_GetWheelDelta 2761 -#define wxMouseEvent_GetX 2762 -#define wxMouseEvent_GetY 2763 -#define wxMouseEvent_IsButton 2764 -#define wxMouseEvent_IsPageScroll 2765 -#define wxMouseEvent_Leaving 2766 -#define wxMouseEvent_LeftDClick 2767 -#define wxMouseEvent_LeftDown 2768 -#define wxMouseEvent_LeftIsDown 2769 -#define wxMouseEvent_LeftUp 2770 -#define wxMouseEvent_MetaDown 2771 -#define wxMouseEvent_MiddleDClick 2772 -#define wxMouseEvent_MiddleDown 2773 -#define wxMouseEvent_MiddleIsDown 2774 -#define wxMouseEvent_MiddleUp 2775 -#define wxMouseEvent_Moving 2776 -#define wxMouseEvent_RightDClick 2777 -#define wxMouseEvent_RightDown 2778 -#define wxMouseEvent_RightIsDown 2779 -#define wxMouseEvent_RightUp 2780 -#define wxMouseEvent_ShiftDown 2781 -#define wxSetCursorEvent_GetCursor 2782 -#define wxSetCursorEvent_GetX 2783 -#define wxSetCursorEvent_GetY 2784 -#define wxSetCursorEvent_HasCursor 2785 -#define wxSetCursorEvent_SetCursor 2786 -#define wxKeyEvent_AltDown 2787 -#define wxKeyEvent_CmdDown 2788 -#define wxKeyEvent_ControlDown 2789 -#define wxKeyEvent_GetKeyCode 2790 -#define wxKeyEvent_GetModifiers 2791 -#define wxKeyEvent_GetPosition 2794 -#define wxKeyEvent_GetRawKeyCode 2795 -#define wxKeyEvent_GetRawKeyFlags 2796 -#define wxKeyEvent_GetUnicodeKey 2797 -#define wxKeyEvent_GetX 2798 -#define wxKeyEvent_GetY 2799 -#define wxKeyEvent_HasModifiers 2800 -#define wxKeyEvent_MetaDown 2801 -#define wxKeyEvent_ShiftDown 2802 -#define wxSizeEvent_GetSize 2803 -#define wxMoveEvent_GetPosition 2804 -#define wxEraseEvent_GetDC 2805 -#define wxFocusEvent_GetWindow 2806 -#define wxChildFocusEvent_GetWindow 2807 -#define wxMenuEvent_GetMenu 2808 -#define wxMenuEvent_GetMenuId 2809 -#define wxMenuEvent_IsPopup 2810 -#define wxCloseEvent_CanVeto 2811 -#define wxCloseEvent_GetLoggingOff 2812 -#define wxCloseEvent_SetCanVeto 2813 -#define wxCloseEvent_SetLoggingOff 2814 -#define wxCloseEvent_Veto 2815 -#define wxShowEvent_SetShow 2816 -#define wxShowEvent_GetShow 2817 -#define wxIconizeEvent_Iconized 2818 -#define wxJoystickEvent_ButtonDown 2819 -#define wxJoystickEvent_ButtonIsDown 2820 -#define wxJoystickEvent_ButtonUp 2821 -#define wxJoystickEvent_GetButtonChange 2822 -#define wxJoystickEvent_GetButtonState 2823 -#define wxJoystickEvent_GetJoystick 2824 -#define wxJoystickEvent_GetPosition 2825 -#define wxJoystickEvent_GetZPosition 2826 -#define wxJoystickEvent_IsButton 2827 -#define wxJoystickEvent_IsMove 2828 -#define wxJoystickEvent_IsZMove 2829 -#define wxUpdateUIEvent_CanUpdate 2830 -#define wxUpdateUIEvent_Check 2831 -#define wxUpdateUIEvent_Enable 2832 -#define wxUpdateUIEvent_Show 2833 -#define wxUpdateUIEvent_GetChecked 2834 -#define wxUpdateUIEvent_GetEnabled 2835 -#define wxUpdateUIEvent_GetShown 2836 -#define wxUpdateUIEvent_GetSetChecked 2837 -#define wxUpdateUIEvent_GetSetEnabled 2838 -#define wxUpdateUIEvent_GetSetShown 2839 -#define wxUpdateUIEvent_GetSetText 2840 -#define wxUpdateUIEvent_GetText 2841 -#define wxUpdateUIEvent_GetMode 2842 -#define wxUpdateUIEvent_GetUpdateInterval 2843 -#define wxUpdateUIEvent_ResetUpdateTime 2844 -#define wxUpdateUIEvent_SetMode 2845 -#define wxUpdateUIEvent_SetText 2846 -#define wxUpdateUIEvent_SetUpdateInterval 2847 -#define wxMouseCaptureChangedEvent_GetCapturedWindow 2848 -#define wxPaletteChangedEvent_SetChangedWindow 2849 -#define wxPaletteChangedEvent_GetChangedWindow 2850 -#define wxQueryNewPaletteEvent_SetPaletteRealized 2851 -#define wxQueryNewPaletteEvent_GetPaletteRealized 2852 -#define wxNavigationKeyEvent_GetDirection 2853 -#define wxNavigationKeyEvent_SetDirection 2854 -#define wxNavigationKeyEvent_IsWindowChange 2855 -#define wxNavigationKeyEvent_SetWindowChange 2856 -#define wxNavigationKeyEvent_IsFromTab 2857 -#define wxNavigationKeyEvent_SetFromTab 2858 -#define wxNavigationKeyEvent_GetCurrentFocus 2859 -#define wxNavigationKeyEvent_SetCurrentFocus 2860 -#define wxHelpEvent_GetOrigin 2861 -#define wxHelpEvent_GetPosition 2862 -#define wxHelpEvent_SetOrigin 2863 -#define wxHelpEvent_SetPosition 2864 -#define wxContextMenuEvent_GetPosition 2865 -#define wxContextMenuEvent_SetPosition 2866 -#define wxIdleEvent_CanSend 2867 -#define wxIdleEvent_GetMode 2868 -#define wxIdleEvent_RequestMore 2869 -#define wxIdleEvent_MoreRequested 2870 -#define wxIdleEvent_SetMode 2871 -#define wxGridEvent_AltDown 2872 -#define wxGridEvent_ControlDown 2873 -#define wxGridEvent_GetCol 2874 -#define wxGridEvent_GetPosition 2875 -#define wxGridEvent_GetRow 2876 -#define wxGridEvent_MetaDown 2877 -#define wxGridEvent_Selecting 2878 -#define wxGridEvent_ShiftDown 2879 -#define wxNotifyEvent_Allow 2880 -#define wxNotifyEvent_IsAllowed 2881 -#define wxNotifyEvent_Veto 2882 -#define wxSashEvent_GetEdge 2883 -#define wxSashEvent_GetDragRect 2884 -#define wxSashEvent_GetDragStatus 2885 -#define wxListEvent_GetCacheFrom 2886 -#define wxListEvent_GetCacheTo 2887 -#define wxListEvent_GetKeyCode 2888 -#define wxListEvent_GetIndex 2889 -#define wxListEvent_GetColumn 2890 -#define wxListEvent_GetPoint 2891 -#define wxListEvent_GetLabel 2892 -#define wxListEvent_GetText 2893 -#define wxListEvent_GetImage 2894 -#define wxListEvent_GetData 2895 -#define wxListEvent_GetMask 2896 -#define wxListEvent_GetItem 2897 -#define wxListEvent_IsEditCancelled 2898 -#define wxDateEvent_GetDate 2899 -#define wxCalendarEvent_GetWeekDay 2900 -#define wxFileDirPickerEvent_GetPath 2901 -#define wxColourPickerEvent_GetColour 2902 -#define wxFontPickerEvent_GetFont 2903 -#define wxStyledTextEvent_GetPosition 2904 -#define wxStyledTextEvent_GetKey 2905 -#define wxStyledTextEvent_GetModifiers 2906 -#define wxStyledTextEvent_GetModificationType 2907 -#define wxStyledTextEvent_GetText 2908 -#define wxStyledTextEvent_GetLength 2909 -#define wxStyledTextEvent_GetLinesAdded 2910 -#define wxStyledTextEvent_GetLine 2911 -#define wxStyledTextEvent_GetFoldLevelNow 2912 -#define wxStyledTextEvent_GetFoldLevelPrev 2913 -#define wxStyledTextEvent_GetMargin 2914 -#define wxStyledTextEvent_GetMessage 2915 -#define wxStyledTextEvent_GetWParam 2916 -#define wxStyledTextEvent_GetLParam 2917 -#define wxStyledTextEvent_GetListType 2918 -#define wxStyledTextEvent_GetX 2919 -#define wxStyledTextEvent_GetY 2920 -#define wxStyledTextEvent_GetDragText 2921 -#define wxStyledTextEvent_GetDragAllowMove 2922 -#define wxStyledTextEvent_GetDragResult 2923 -#define wxStyledTextEvent_GetShift 2924 -#define wxStyledTextEvent_GetControl 2925 -#define wxStyledTextEvent_GetAlt 2926 -#define utils_wxGetKeyState 2927 -#define utils_wxGetMousePosition 2928 -#define utils_wxGetMouseState 2929 -#define utils_wxSetDetectableAutoRepeat 2930 -#define utils_wxBell 2931 -#define utils_wxFindMenuItemId 2932 -#define utils_wxGenericFindWindowAtPoint 2933 -#define utils_wxFindWindowAtPoint 2934 -#define utils_wxBeginBusyCursor 2935 -#define utils_wxEndBusyCursor 2936 -#define utils_wxIsBusy 2937 -#define utils_wxShutdown 2938 -#define utils_wxShell 2939 -#define utils_wxLaunchDefaultBrowser 2940 -#define utils_wxGetEmailAddress 2941 -#define utils_wxGetUserId 2942 -#define utils_wxGetHomeDir 2943 -#define utils_wxNewId 2944 -#define utils_wxRegisterId 2945 -#define utils_wxGetCurrentId 2946 -#define utils_wxGetOsDescription 2947 -#define utils_wxIsPlatformLittleEndian 2948 -#define utils_wxIsPlatform64Bit 2949 -#define gdicmn_wxDisplaySize 2950 -#define gdicmn_wxSetCursor 2951 -#define wxPrintout_new 2952 -#define wxPrintout_destruct 2953 -#define wxPrintout_GetDC 2954 -#define wxPrintout_GetPageSizeMM 2955 -#define wxPrintout_GetPageSizePixels 2956 -#define wxPrintout_GetPaperRectPixels 2957 -#define wxPrintout_GetPPIPrinter 2958 -#define wxPrintout_GetPPIScreen 2959 -#define wxPrintout_GetTitle 2960 -#define wxPrintout_IsPreview 2961 -#define wxPrintout_FitThisSizeToPaper 2962 -#define wxPrintout_FitThisSizeToPage 2963 -#define wxPrintout_FitThisSizeToPageMargins 2964 -#define wxPrintout_MapScreenSizeToPaper 2965 -#define wxPrintout_MapScreenSizeToPage 2966 -#define wxPrintout_MapScreenSizeToPageMargins 2967 -#define wxPrintout_MapScreenSizeToDevice 2968 -#define wxPrintout_GetLogicalPaperRect 2969 -#define wxPrintout_GetLogicalPageRect 2970 -#define wxPrintout_GetLogicalPageMarginsRect 2971 -#define wxPrintout_SetLogicalOrigin 2972 -#define wxPrintout_OffsetLogicalOrigin 2973 -#define wxStyledTextCtrl_new_2 2974 -#define wxStyledTextCtrl_new_0 2975 -#define wxStyledTextCtrl_destruct 2976 -#define wxStyledTextCtrl_Create 2977 -#define wxStyledTextCtrl_AddText 2978 -#define wxStyledTextCtrl_AddStyledText 2979 -#define wxStyledTextCtrl_InsertText 2980 -#define wxStyledTextCtrl_ClearAll 2981 -#define wxStyledTextCtrl_ClearDocumentStyle 2982 -#define wxStyledTextCtrl_GetLength 2983 -#define wxStyledTextCtrl_GetCharAt 2984 -#define wxStyledTextCtrl_GetCurrentPos 2985 -#define wxStyledTextCtrl_GetAnchor 2986 -#define wxStyledTextCtrl_GetStyleAt 2987 -#define wxStyledTextCtrl_Redo 2988 -#define wxStyledTextCtrl_SetUndoCollection 2989 -#define wxStyledTextCtrl_SelectAll 2990 -#define wxStyledTextCtrl_SetSavePoint 2991 -#define wxStyledTextCtrl_GetStyledText 2992 -#define wxStyledTextCtrl_CanRedo 2993 -#define wxStyledTextCtrl_MarkerLineFromHandle 2994 -#define wxStyledTextCtrl_MarkerDeleteHandle 2995 -#define wxStyledTextCtrl_GetUndoCollection 2996 -#define wxStyledTextCtrl_GetViewWhiteSpace 2997 -#define wxStyledTextCtrl_SetViewWhiteSpace 2998 -#define wxStyledTextCtrl_PositionFromPoint 2999 -#define wxStyledTextCtrl_PositionFromPointClose 3000 -#define wxStyledTextCtrl_GotoLine 3001 -#define wxStyledTextCtrl_GotoPos 3002 -#define wxStyledTextCtrl_SetAnchor 3003 -#define wxStyledTextCtrl_GetCurLine 3004 -#define wxStyledTextCtrl_GetEndStyled 3005 -#define wxStyledTextCtrl_ConvertEOLs 3006 -#define wxStyledTextCtrl_GetEOLMode 3007 -#define wxStyledTextCtrl_SetEOLMode 3008 -#define wxStyledTextCtrl_StartStyling 3009 -#define wxStyledTextCtrl_SetStyling 3010 -#define wxStyledTextCtrl_GetBufferedDraw 3011 -#define wxStyledTextCtrl_SetBufferedDraw 3012 -#define wxStyledTextCtrl_SetTabWidth 3013 -#define wxStyledTextCtrl_GetTabWidth 3014 -#define wxStyledTextCtrl_SetCodePage 3015 -#define wxStyledTextCtrl_MarkerDefine 3016 -#define wxStyledTextCtrl_MarkerSetForeground 3017 -#define wxStyledTextCtrl_MarkerSetBackground 3018 -#define wxStyledTextCtrl_MarkerAdd 3019 -#define wxStyledTextCtrl_MarkerDelete 3020 -#define wxStyledTextCtrl_MarkerDeleteAll 3021 -#define wxStyledTextCtrl_MarkerGet 3022 -#define wxStyledTextCtrl_MarkerNext 3023 -#define wxStyledTextCtrl_MarkerPrevious 3024 -#define wxStyledTextCtrl_MarkerDefineBitmap 3025 -#define wxStyledTextCtrl_MarkerAddSet 3026 -#define wxStyledTextCtrl_MarkerSetAlpha 3027 -#define wxStyledTextCtrl_SetMarginType 3028 -#define wxStyledTextCtrl_GetMarginType 3029 -#define wxStyledTextCtrl_SetMarginWidth 3030 -#define wxStyledTextCtrl_GetMarginWidth 3031 -#define wxStyledTextCtrl_SetMarginMask 3032 -#define wxStyledTextCtrl_GetMarginMask 3033 -#define wxStyledTextCtrl_SetMarginSensitive 3034 -#define wxStyledTextCtrl_GetMarginSensitive 3035 -#define wxStyledTextCtrl_StyleClearAll 3036 -#define wxStyledTextCtrl_StyleSetForeground 3037 -#define wxStyledTextCtrl_StyleSetBackground 3038 -#define wxStyledTextCtrl_StyleSetBold 3039 -#define wxStyledTextCtrl_StyleSetItalic 3040 -#define wxStyledTextCtrl_StyleSetSize 3041 -#define wxStyledTextCtrl_StyleSetFaceName 3042 -#define wxStyledTextCtrl_StyleSetEOLFilled 3043 -#define wxStyledTextCtrl_StyleResetDefault 3044 -#define wxStyledTextCtrl_StyleSetUnderline 3045 -#define wxStyledTextCtrl_StyleSetCase 3046 -#define wxStyledTextCtrl_StyleSetHotSpot 3047 -#define wxStyledTextCtrl_SetSelForeground 3048 -#define wxStyledTextCtrl_SetSelBackground 3049 -#define wxStyledTextCtrl_GetSelAlpha 3050 -#define wxStyledTextCtrl_SetSelAlpha 3051 -#define wxStyledTextCtrl_SetCaretForeground 3052 -#define wxStyledTextCtrl_CmdKeyAssign 3053 -#define wxStyledTextCtrl_CmdKeyClear 3054 -#define wxStyledTextCtrl_CmdKeyClearAll 3055 -#define wxStyledTextCtrl_SetStyleBytes 3056 -#define wxStyledTextCtrl_StyleSetVisible 3057 -#define wxStyledTextCtrl_GetCaretPeriod 3058 -#define wxStyledTextCtrl_SetCaretPeriod 3059 -#define wxStyledTextCtrl_SetWordChars 3060 -#define wxStyledTextCtrl_BeginUndoAction 3061 -#define wxStyledTextCtrl_EndUndoAction 3062 -#define wxStyledTextCtrl_IndicatorSetStyle 3063 -#define wxStyledTextCtrl_IndicatorGetStyle 3064 -#define wxStyledTextCtrl_IndicatorSetForeground 3065 -#define wxStyledTextCtrl_IndicatorGetForeground 3066 -#define wxStyledTextCtrl_SetWhitespaceForeground 3067 -#define wxStyledTextCtrl_SetWhitespaceBackground 3068 -#define wxStyledTextCtrl_GetStyleBits 3069 -#define wxStyledTextCtrl_SetLineState 3070 -#define wxStyledTextCtrl_GetLineState 3071 -#define wxStyledTextCtrl_GetMaxLineState 3072 -#define wxStyledTextCtrl_GetCaretLineVisible 3073 -#define wxStyledTextCtrl_SetCaretLineVisible 3074 -#define wxStyledTextCtrl_GetCaretLineBackground 3075 -#define wxStyledTextCtrl_SetCaretLineBackground 3076 -#define wxStyledTextCtrl_AutoCompShow 3077 -#define wxStyledTextCtrl_AutoCompCancel 3078 -#define wxStyledTextCtrl_AutoCompActive 3079 -#define wxStyledTextCtrl_AutoCompPosStart 3080 -#define wxStyledTextCtrl_AutoCompComplete 3081 -#define wxStyledTextCtrl_AutoCompStops 3082 -#define wxStyledTextCtrl_AutoCompSetSeparator 3083 -#define wxStyledTextCtrl_AutoCompGetSeparator 3084 -#define wxStyledTextCtrl_AutoCompSelect 3085 -#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3086 -#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3087 -#define wxStyledTextCtrl_AutoCompSetFillUps 3088 -#define wxStyledTextCtrl_AutoCompSetChooseSingle 3089 -#define wxStyledTextCtrl_AutoCompGetChooseSingle 3090 -#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3091 -#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3092 -#define wxStyledTextCtrl_UserListShow 3093 -#define wxStyledTextCtrl_AutoCompSetAutoHide 3094 -#define wxStyledTextCtrl_AutoCompGetAutoHide 3095 -#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3096 -#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3097 -#define wxStyledTextCtrl_RegisterImage 3098 -#define wxStyledTextCtrl_ClearRegisteredImages 3099 -#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3100 -#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3101 -#define wxStyledTextCtrl_AutoCompSetMaxWidth 3102 -#define wxStyledTextCtrl_AutoCompGetMaxWidth 3103 -#define wxStyledTextCtrl_AutoCompSetMaxHeight 3104 -#define wxStyledTextCtrl_AutoCompGetMaxHeight 3105 -#define wxStyledTextCtrl_SetIndent 3106 -#define wxStyledTextCtrl_GetIndent 3107 -#define wxStyledTextCtrl_SetUseTabs 3108 -#define wxStyledTextCtrl_GetUseTabs 3109 -#define wxStyledTextCtrl_SetLineIndentation 3110 -#define wxStyledTextCtrl_GetLineIndentation 3111 -#define wxStyledTextCtrl_GetLineIndentPosition 3112 -#define wxStyledTextCtrl_GetColumn 3113 -#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3114 -#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3115 -#define wxStyledTextCtrl_SetIndentationGuides 3116 -#define wxStyledTextCtrl_GetIndentationGuides 3117 -#define wxStyledTextCtrl_SetHighlightGuide 3118 -#define wxStyledTextCtrl_GetHighlightGuide 3119 -#define wxStyledTextCtrl_GetLineEndPosition 3120 -#define wxStyledTextCtrl_GetCodePage 3121 -#define wxStyledTextCtrl_GetCaretForeground 3122 -#define wxStyledTextCtrl_GetReadOnly 3123 -#define wxStyledTextCtrl_SetCurrentPos 3124 -#define wxStyledTextCtrl_SetSelectionStart 3125 -#define wxStyledTextCtrl_GetSelectionStart 3126 -#define wxStyledTextCtrl_SetSelectionEnd 3127 -#define wxStyledTextCtrl_GetSelectionEnd 3128 -#define wxStyledTextCtrl_SetPrintMagnification 3129 -#define wxStyledTextCtrl_GetPrintMagnification 3130 -#define wxStyledTextCtrl_SetPrintColourMode 3131 -#define wxStyledTextCtrl_GetPrintColourMode 3132 -#define wxStyledTextCtrl_FindText 3133 -#define wxStyledTextCtrl_FormatRange 3134 -#define wxStyledTextCtrl_GetFirstVisibleLine 3135 -#define wxStyledTextCtrl_GetLine 3136 -#define wxStyledTextCtrl_GetLineCount 3137 -#define wxStyledTextCtrl_SetMarginLeft 3138 -#define wxStyledTextCtrl_GetMarginLeft 3139 -#define wxStyledTextCtrl_SetMarginRight 3140 -#define wxStyledTextCtrl_GetMarginRight 3141 -#define wxStyledTextCtrl_GetModify 3142 -#define wxStyledTextCtrl_SetSelection 3143 -#define wxStyledTextCtrl_GetSelectedText 3144 -#define wxStyledTextCtrl_GetTextRange 3145 -#define wxStyledTextCtrl_HideSelection 3146 -#define wxStyledTextCtrl_LineFromPosition 3147 -#define wxStyledTextCtrl_PositionFromLine 3148 -#define wxStyledTextCtrl_LineScroll 3149 -#define wxStyledTextCtrl_EnsureCaretVisible 3150 -#define wxStyledTextCtrl_ReplaceSelection 3151 -#define wxStyledTextCtrl_SetReadOnly 3152 -#define wxStyledTextCtrl_CanPaste 3153 -#define wxStyledTextCtrl_CanUndo 3154 -#define wxStyledTextCtrl_EmptyUndoBuffer 3155 -#define wxStyledTextCtrl_Undo 3156 -#define wxStyledTextCtrl_Cut 3157 -#define wxStyledTextCtrl_Copy 3158 -#define wxStyledTextCtrl_Paste 3159 -#define wxStyledTextCtrl_Clear 3160 -#define wxStyledTextCtrl_SetText 3161 -#define wxStyledTextCtrl_GetText 3162 -#define wxStyledTextCtrl_GetTextLength 3163 -#define wxStyledTextCtrl_GetOvertype 3164 -#define wxStyledTextCtrl_SetCaretWidth 3165 -#define wxStyledTextCtrl_GetCaretWidth 3166 -#define wxStyledTextCtrl_SetTargetStart 3167 -#define wxStyledTextCtrl_GetTargetStart 3168 -#define wxStyledTextCtrl_SetTargetEnd 3169 -#define wxStyledTextCtrl_GetTargetEnd 3170 -#define wxStyledTextCtrl_ReplaceTarget 3171 -#define wxStyledTextCtrl_SearchInTarget 3172 -#define wxStyledTextCtrl_SetSearchFlags 3173 -#define wxStyledTextCtrl_GetSearchFlags 3174 -#define wxStyledTextCtrl_CallTipShow 3175 -#define wxStyledTextCtrl_CallTipCancel 3176 -#define wxStyledTextCtrl_CallTipActive 3177 -#define wxStyledTextCtrl_CallTipPosAtStart 3178 -#define wxStyledTextCtrl_CallTipSetHighlight 3179 -#define wxStyledTextCtrl_CallTipSetBackground 3180 -#define wxStyledTextCtrl_CallTipSetForeground 3181 -#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3182 -#define wxStyledTextCtrl_CallTipUseStyle 3183 -#define wxStyledTextCtrl_VisibleFromDocLine 3184 -#define wxStyledTextCtrl_DocLineFromVisible 3185 -#define wxStyledTextCtrl_WrapCount 3186 -#define wxStyledTextCtrl_SetFoldLevel 3187 -#define wxStyledTextCtrl_GetFoldLevel 3188 -#define wxStyledTextCtrl_GetLastChild 3189 -#define wxStyledTextCtrl_GetFoldParent 3190 -#define wxStyledTextCtrl_ShowLines 3191 -#define wxStyledTextCtrl_HideLines 3192 -#define wxStyledTextCtrl_GetLineVisible 3193 -#define wxStyledTextCtrl_SetFoldExpanded 3194 -#define wxStyledTextCtrl_GetFoldExpanded 3195 -#define wxStyledTextCtrl_ToggleFold 3196 -#define wxStyledTextCtrl_EnsureVisible 3197 -#define wxStyledTextCtrl_SetFoldFlags 3198 -#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3199 -#define wxStyledTextCtrl_SetTabIndents 3200 -#define wxStyledTextCtrl_GetTabIndents 3201 -#define wxStyledTextCtrl_SetBackSpaceUnIndents 3202 -#define wxStyledTextCtrl_GetBackSpaceUnIndents 3203 -#define wxStyledTextCtrl_SetMouseDwellTime 3204 -#define wxStyledTextCtrl_GetMouseDwellTime 3205 -#define wxStyledTextCtrl_WordStartPosition 3206 -#define wxStyledTextCtrl_WordEndPosition 3207 -#define wxStyledTextCtrl_SetWrapMode 3208 -#define wxStyledTextCtrl_GetWrapMode 3209 -#define wxStyledTextCtrl_SetWrapVisualFlags 3210 -#define wxStyledTextCtrl_GetWrapVisualFlags 3211 -#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3212 -#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3213 -#define wxStyledTextCtrl_SetWrapStartIndent 3214 -#define wxStyledTextCtrl_GetWrapStartIndent 3215 -#define wxStyledTextCtrl_SetLayoutCache 3216 -#define wxStyledTextCtrl_GetLayoutCache 3217 -#define wxStyledTextCtrl_SetScrollWidth 3218 -#define wxStyledTextCtrl_GetScrollWidth 3219 -#define wxStyledTextCtrl_TextWidth 3220 -#define wxStyledTextCtrl_GetEndAtLastLine 3221 -#define wxStyledTextCtrl_TextHeight 3222 -#define wxStyledTextCtrl_SetUseVerticalScrollBar 3223 -#define wxStyledTextCtrl_GetUseVerticalScrollBar 3224 -#define wxStyledTextCtrl_AppendText 3225 -#define wxStyledTextCtrl_GetTwoPhaseDraw 3226 -#define wxStyledTextCtrl_SetTwoPhaseDraw 3227 -#define wxStyledTextCtrl_TargetFromSelection 3228 -#define wxStyledTextCtrl_LinesJoin 3229 -#define wxStyledTextCtrl_LinesSplit 3230 -#define wxStyledTextCtrl_SetFoldMarginColour 3231 -#define wxStyledTextCtrl_SetFoldMarginHiColour 3232 -#define wxStyledTextCtrl_LineDown 3233 -#define wxStyledTextCtrl_LineDownExtend 3234 -#define wxStyledTextCtrl_LineUp 3235 -#define wxStyledTextCtrl_LineUpExtend 3236 -#define wxStyledTextCtrl_CharLeft 3237 -#define wxStyledTextCtrl_CharLeftExtend 3238 -#define wxStyledTextCtrl_CharRight 3239 -#define wxStyledTextCtrl_CharRightExtend 3240 -#define wxStyledTextCtrl_WordLeft 3241 -#define wxStyledTextCtrl_WordLeftExtend 3242 -#define wxStyledTextCtrl_WordRight 3243 -#define wxStyledTextCtrl_WordRightExtend 3244 -#define wxStyledTextCtrl_Home 3245 -#define wxStyledTextCtrl_HomeExtend 3246 -#define wxStyledTextCtrl_LineEnd 3247 -#define wxStyledTextCtrl_LineEndExtend 3248 -#define wxStyledTextCtrl_DocumentStart 3249 -#define wxStyledTextCtrl_DocumentStartExtend 3250 -#define wxStyledTextCtrl_DocumentEnd 3251 -#define wxStyledTextCtrl_DocumentEndExtend 3252 -#define wxStyledTextCtrl_PageUp 3253 -#define wxStyledTextCtrl_PageUpExtend 3254 -#define wxStyledTextCtrl_PageDown 3255 -#define wxStyledTextCtrl_PageDownExtend 3256 -#define wxStyledTextCtrl_EditToggleOvertype 3257 -#define wxStyledTextCtrl_Cancel 3258 -#define wxStyledTextCtrl_DeleteBack 3259 -#define wxStyledTextCtrl_Tab 3260 -#define wxStyledTextCtrl_BackTab 3261 -#define wxStyledTextCtrl_NewLine 3262 -#define wxStyledTextCtrl_FormFeed 3263 -#define wxStyledTextCtrl_VCHome 3264 -#define wxStyledTextCtrl_VCHomeExtend 3265 -#define wxStyledTextCtrl_ZoomIn 3266 -#define wxStyledTextCtrl_ZoomOut 3267 -#define wxStyledTextCtrl_DelWordLeft 3268 -#define wxStyledTextCtrl_DelWordRight 3269 -#define wxStyledTextCtrl_LineCut 3270 -#define wxStyledTextCtrl_LineDelete 3271 -#define wxStyledTextCtrl_LineTranspose 3272 -#define wxStyledTextCtrl_LineDuplicate 3273 -#define wxStyledTextCtrl_LowerCase 3274 -#define wxStyledTextCtrl_UpperCase 3275 -#define wxStyledTextCtrl_LineScrollDown 3276 -#define wxStyledTextCtrl_LineScrollUp 3277 -#define wxStyledTextCtrl_DeleteBackNotLine 3278 -#define wxStyledTextCtrl_HomeDisplay 3279 -#define wxStyledTextCtrl_HomeDisplayExtend 3280 -#define wxStyledTextCtrl_LineEndDisplay 3281 -#define wxStyledTextCtrl_LineEndDisplayExtend 3282 -#define wxStyledTextCtrl_HomeWrapExtend 3283 -#define wxStyledTextCtrl_LineEndWrap 3284 -#define wxStyledTextCtrl_LineEndWrapExtend 3285 -#define wxStyledTextCtrl_VCHomeWrap 3286 -#define wxStyledTextCtrl_VCHomeWrapExtend 3287 -#define wxStyledTextCtrl_LineCopy 3288 -#define wxStyledTextCtrl_MoveCaretInsideView 3289 -#define wxStyledTextCtrl_LineLength 3290 -#define wxStyledTextCtrl_BraceHighlight 3291 -#define wxStyledTextCtrl_BraceBadLight 3292 -#define wxStyledTextCtrl_BraceMatch 3293 -#define wxStyledTextCtrl_GetViewEOL 3294 -#define wxStyledTextCtrl_SetViewEOL 3295 -#define wxStyledTextCtrl_SetModEventMask 3296 -#define wxStyledTextCtrl_GetEdgeColumn 3297 -#define wxStyledTextCtrl_SetEdgeColumn 3298 -#define wxStyledTextCtrl_SetEdgeMode 3299 -#define wxStyledTextCtrl_GetEdgeMode 3300 -#define wxStyledTextCtrl_GetEdgeColour 3301 -#define wxStyledTextCtrl_SetEdgeColour 3302 -#define wxStyledTextCtrl_SearchAnchor 3303 -#define wxStyledTextCtrl_SearchNext 3304 -#define wxStyledTextCtrl_SearchPrev 3305 -#define wxStyledTextCtrl_LinesOnScreen 3306 -#define wxStyledTextCtrl_UsePopUp 3307 -#define wxStyledTextCtrl_SelectionIsRectangle 3308 -#define wxStyledTextCtrl_SetZoom 3309 -#define wxStyledTextCtrl_GetZoom 3310 -#define wxStyledTextCtrl_GetModEventMask 3311 -#define wxStyledTextCtrl_SetSTCFocus 3312 -#define wxStyledTextCtrl_GetSTCFocus 3313 -#define wxStyledTextCtrl_SetStatus 3314 -#define wxStyledTextCtrl_GetStatus 3315 -#define wxStyledTextCtrl_SetMouseDownCaptures 3316 -#define wxStyledTextCtrl_GetMouseDownCaptures 3317 -#define wxStyledTextCtrl_SetSTCCursor 3318 -#define wxStyledTextCtrl_GetSTCCursor 3319 -#define wxStyledTextCtrl_SetControlCharSymbol 3320 -#define wxStyledTextCtrl_GetControlCharSymbol 3321 -#define wxStyledTextCtrl_WordPartLeft 3322 -#define wxStyledTextCtrl_WordPartLeftExtend 3323 -#define wxStyledTextCtrl_WordPartRight 3324 -#define wxStyledTextCtrl_WordPartRightExtend 3325 -#define wxStyledTextCtrl_SetVisiblePolicy 3326 -#define wxStyledTextCtrl_DelLineLeft 3327 -#define wxStyledTextCtrl_DelLineRight 3328 -#define wxStyledTextCtrl_GetXOffset 3329 -#define wxStyledTextCtrl_ChooseCaretX 3330 -#define wxStyledTextCtrl_SetXCaretPolicy 3331 -#define wxStyledTextCtrl_SetYCaretPolicy 3332 -#define wxStyledTextCtrl_GetPrintWrapMode 3333 -#define wxStyledTextCtrl_SetHotspotActiveForeground 3334 -#define wxStyledTextCtrl_SetHotspotActiveBackground 3335 -#define wxStyledTextCtrl_SetHotspotActiveUnderline 3336 -#define wxStyledTextCtrl_SetHotspotSingleLine 3337 -#define wxStyledTextCtrl_ParaDownExtend 3338 -#define wxStyledTextCtrl_ParaUp 3339 -#define wxStyledTextCtrl_ParaUpExtend 3340 -#define wxStyledTextCtrl_PositionBefore 3341 -#define wxStyledTextCtrl_PositionAfter 3342 -#define wxStyledTextCtrl_CopyRange 3343 -#define wxStyledTextCtrl_CopyText 3344 -#define wxStyledTextCtrl_SetSelectionMode 3345 -#define wxStyledTextCtrl_GetSelectionMode 3346 -#define wxStyledTextCtrl_LineDownRectExtend 3347 -#define wxStyledTextCtrl_LineUpRectExtend 3348 -#define wxStyledTextCtrl_CharLeftRectExtend 3349 -#define wxStyledTextCtrl_CharRightRectExtend 3350 -#define wxStyledTextCtrl_HomeRectExtend 3351 -#define wxStyledTextCtrl_VCHomeRectExtend 3352 -#define wxStyledTextCtrl_LineEndRectExtend 3353 -#define wxStyledTextCtrl_PageUpRectExtend 3354 -#define wxStyledTextCtrl_PageDownRectExtend 3355 -#define wxStyledTextCtrl_StutteredPageUp 3356 -#define wxStyledTextCtrl_StutteredPageUpExtend 3357 -#define wxStyledTextCtrl_StutteredPageDown 3358 -#define wxStyledTextCtrl_StutteredPageDownExtend 3359 -#define wxStyledTextCtrl_WordLeftEnd 3360 -#define wxStyledTextCtrl_WordLeftEndExtend 3361 -#define wxStyledTextCtrl_WordRightEnd 3362 -#define wxStyledTextCtrl_WordRightEndExtend 3363 -#define wxStyledTextCtrl_SetWhitespaceChars 3364 -#define wxStyledTextCtrl_SetCharsDefault 3365 -#define wxStyledTextCtrl_AutoCompGetCurrent 3366 -#define wxStyledTextCtrl_Allocate 3367 -#define wxStyledTextCtrl_FindColumn 3368 -#define wxStyledTextCtrl_GetCaretSticky 3369 -#define wxStyledTextCtrl_SetCaretSticky 3370 -#define wxStyledTextCtrl_ToggleCaretSticky 3371 -#define wxStyledTextCtrl_SetPasteConvertEndings 3372 -#define wxStyledTextCtrl_GetPasteConvertEndings 3373 -#define wxStyledTextCtrl_SelectionDuplicate 3374 -#define wxStyledTextCtrl_SetCaretLineBackAlpha 3375 -#define wxStyledTextCtrl_GetCaretLineBackAlpha 3376 -#define wxStyledTextCtrl_StartRecord 3377 -#define wxStyledTextCtrl_StopRecord 3378 -#define wxStyledTextCtrl_SetLexer 3379 -#define wxStyledTextCtrl_GetLexer 3380 -#define wxStyledTextCtrl_Colourise 3381 -#define wxStyledTextCtrl_SetProperty 3382 -#define wxStyledTextCtrl_SetKeyWords 3383 -#define wxStyledTextCtrl_SetLexerLanguage 3384 -#define wxStyledTextCtrl_GetProperty 3385 -#define wxStyledTextCtrl_GetStyleBitsNeeded 3386 -#define wxStyledTextCtrl_GetCurrentLine 3387 -#define wxStyledTextCtrl_StyleSetSpec 3388 -#define wxStyledTextCtrl_StyleSetFont 3389 -#define wxStyledTextCtrl_StyleSetFontAttr 3390 -#define wxStyledTextCtrl_StyleSetCharacterSet 3391 -#define wxStyledTextCtrl_StyleSetFontEncoding 3392 -#define wxStyledTextCtrl_CmdKeyExecute 3393 -#define wxStyledTextCtrl_SetMargins 3394 -#define wxStyledTextCtrl_GetSelection 3395 -#define wxStyledTextCtrl_PointFromPosition 3396 -#define wxStyledTextCtrl_ScrollToLine 3397 -#define wxStyledTextCtrl_ScrollToColumn 3398 -#define wxStyledTextCtrl_SetVScrollBar 3399 -#define wxStyledTextCtrl_SetHScrollBar 3400 -#define wxStyledTextCtrl_GetLastKeydownProcessed 3401 -#define wxStyledTextCtrl_SetLastKeydownProcessed 3402 -#define wxStyledTextCtrl_SaveFile 3403 -#define wxStyledTextCtrl_LoadFile 3404 -#define wxStyledTextCtrl_DoDragOver 3405 -#define wxStyledTextCtrl_DoDropText 3406 -#define wxStyledTextCtrl_GetUseAntiAliasing 3407 -#define wxStyledTextCtrl_AddTextRaw 3408 -#define wxStyledTextCtrl_InsertTextRaw 3409 -#define wxStyledTextCtrl_GetCurLineRaw 3410 -#define wxStyledTextCtrl_GetLineRaw 3411 -#define wxStyledTextCtrl_GetSelectedTextRaw 3412 -#define wxStyledTextCtrl_GetTextRangeRaw 3413 -#define wxStyledTextCtrl_SetTextRaw 3414 -#define wxStyledTextCtrl_GetTextRaw 3415 -#define wxStyledTextCtrl_AppendTextRaw 3416 -#define wxArtProvider_GetBitmap 3417 -#define wxArtProvider_GetIcon 3418 -#define wxTreeEvent_GetKeyCode 3419 -#define wxTreeEvent_GetItem 3420 -#define wxTreeEvent_GetKeyEvent 3421 -#define wxTreeEvent_GetLabel 3422 -#define wxTreeEvent_GetOldItem 3423 -#define wxTreeEvent_GetPoint 3424 -#define wxTreeEvent_IsEditCancelled 3425 -#define wxTreeEvent_SetToolTip 3426 -#define wxNotebookEvent_GetOldSelection 3427 -#define wxNotebookEvent_GetSelection 3428 -#define wxNotebookEvent_SetOldSelection 3429 -#define wxNotebookEvent_SetSelection 3430 -#define wxFileDataObject_new 3431 -#define wxFileDataObject_AddFile 3432 -#define wxFileDataObject_GetFilenames 3433 -#define wxFileDataObject_destroy 3434 -#define wxTextDataObject_new 3435 -#define wxTextDataObject_GetTextLength 3436 -#define wxTextDataObject_GetText 3437 -#define wxTextDataObject_SetText 3438 -#define wxTextDataObject_destroy 3439 -#define wxBitmapDataObject_new_1_1 3440 -#define wxBitmapDataObject_new_1_0 3441 -#define wxBitmapDataObject_GetBitmap 3442 -#define wxBitmapDataObject_SetBitmap 3443 -#define wxBitmapDataObject_destroy 3444 -#define wxClipboard_new 3446 -#define wxClipboard_destruct 3447 -#define wxClipboard_AddData 3448 -#define wxClipboard_Clear 3449 -#define wxClipboard_Close 3450 -#define wxClipboard_Flush 3451 -#define wxClipboard_GetData 3452 -#define wxClipboard_IsOpened 3453 -#define wxClipboard_Open 3454 -#define wxClipboard_SetData 3455 -#define wxClipboard_UsePrimarySelection 3457 -#define wxClipboard_IsSupported 3458 -#define wxClipboard_Get 3459 -#define wxSpinEvent_GetPosition 3460 -#define wxSpinEvent_SetPosition 3461 -#define wxSplitterWindow_new_0 3462 -#define wxSplitterWindow_new_2 3463 -#define wxSplitterWindow_destruct 3464 -#define wxSplitterWindow_Create 3465 -#define wxSplitterWindow_GetMinimumPaneSize 3466 -#define wxSplitterWindow_GetSashGravity 3467 -#define wxSplitterWindow_GetSashPosition 3468 -#define wxSplitterWindow_GetSplitMode 3469 -#define wxSplitterWindow_GetWindow1 3470 -#define wxSplitterWindow_GetWindow2 3471 -#define wxSplitterWindow_Initialize 3472 -#define wxSplitterWindow_IsSplit 3473 -#define wxSplitterWindow_ReplaceWindow 3474 -#define wxSplitterWindow_SetSashGravity 3475 -#define wxSplitterWindow_SetSashPosition 3476 -#define wxSplitterWindow_SetSashSize 3477 -#define wxSplitterWindow_SetMinimumPaneSize 3478 -#define wxSplitterWindow_SetSplitMode 3479 -#define wxSplitterWindow_SplitHorizontally 3480 -#define wxSplitterWindow_SplitVertically 3481 -#define wxSplitterWindow_Unsplit 3482 -#define wxSplitterWindow_UpdateSize 3483 -#define wxSplitterEvent_GetSashPosition 3484 -#define wxSplitterEvent_GetX 3485 -#define wxSplitterEvent_GetY 3486 -#define wxSplitterEvent_GetWindowBeingRemoved 3487 -#define wxSplitterEvent_SetSashPosition 3488 -#define wxHtmlWindow_new_0 3489 -#define wxHtmlWindow_new_2 3490 -#define wxHtmlWindow_AppendToPage 3491 -#define wxHtmlWindow_GetOpenedAnchor 3492 -#define wxHtmlWindow_GetOpenedPage 3493 -#define wxHtmlWindow_GetOpenedPageTitle 3494 -#define wxHtmlWindow_GetRelatedFrame 3495 -#define wxHtmlWindow_HistoryBack 3496 -#define wxHtmlWindow_HistoryCanBack 3497 -#define wxHtmlWindow_HistoryCanForward 3498 -#define wxHtmlWindow_HistoryClear 3499 -#define wxHtmlWindow_HistoryForward 3500 -#define wxHtmlWindow_LoadFile 3501 -#define wxHtmlWindow_LoadPage 3502 -#define wxHtmlWindow_SelectAll 3503 -#define wxHtmlWindow_SelectionToText 3504 -#define wxHtmlWindow_SelectLine 3505 -#define wxHtmlWindow_SelectWord 3506 -#define wxHtmlWindow_SetBorders 3507 -#define wxHtmlWindow_SetFonts 3508 -#define wxHtmlWindow_SetPage 3509 -#define wxHtmlWindow_SetRelatedFrame 3510 -#define wxHtmlWindow_SetRelatedStatusBar 3511 -#define wxHtmlWindow_ToText 3512 -#define wxHtmlWindow_destroy 3513 -#define wxHtmlLinkEvent_GetLinkInfo 3514 -#define wxSystemSettings_GetColour 3515 -#define wxSystemSettings_GetFont 3516 -#define wxSystemSettings_GetMetric 3517 -#define wxSystemSettings_GetScreenType 3518 -#define wxSystemOptions_GetOption 3519 -#define wxSystemOptions_GetOptionInt 3520 -#define wxSystemOptions_HasOption 3521 -#define wxSystemOptions_IsFalse 3522 -#define wxSystemOptions_SetOption_2_1 3523 -#define wxSystemOptions_SetOption_2_0 3524 -#define wxAuiNotebookEvent_SetSelection 3525 -#define wxAuiNotebookEvent_GetSelection 3526 -#define wxAuiNotebookEvent_SetOldSelection 3527 -#define wxAuiNotebookEvent_GetOldSelection 3528 -#define wxAuiNotebookEvent_SetDragSource 3529 -#define wxAuiNotebookEvent_GetDragSource 3530 -#define wxAuiManagerEvent_SetManager 3531 -#define wxAuiManagerEvent_GetManager 3532 -#define wxAuiManagerEvent_SetPane 3533 -#define wxAuiManagerEvent_GetPane 3534 -#define wxAuiManagerEvent_SetButton 3535 -#define wxAuiManagerEvent_GetButton 3536 -#define wxAuiManagerEvent_SetDC 3537 -#define wxAuiManagerEvent_GetDC 3538 -#define wxAuiManagerEvent_Veto 3539 -#define wxAuiManagerEvent_GetVeto 3540 -#define wxAuiManagerEvent_SetCanVeto 3541 -#define wxAuiManagerEvent_CanVeto 3542 -#define wxLogNull_new 3543 -#define wxLogNull_destroy 3544 -#define wxTaskBarIcon_new 3545 -#define wxTaskBarIcon_destruct 3546 -#define wxTaskBarIcon_PopupMenu 3547 -#define wxTaskBarIcon_RemoveIcon 3548 -#define wxTaskBarIcon_SetIcon 3549 -#define wxLocale_new_0 3550 -#define wxLocale_new_2 3552 -#define wxLocale_destruct 3553 -#define wxLocale_Init 3555 -#define wxLocale_AddCatalog_1 3556 -#define wxLocale_AddCatalog_3 3557 -#define wxLocale_AddCatalogLookupPathPrefix 3558 -#define wxLocale_GetCanonicalName 3559 -#define wxLocale_GetLanguage 3560 -#define wxLocale_GetLanguageName 3561 -#define wxLocale_GetLocale 3562 -#define wxLocale_GetName 3563 -#define wxLocale_GetString_2 3564 -#define wxLocale_GetString_4 3565 -#define wxLocale_GetHeaderValue 3566 -#define wxLocale_GetSysName 3567 -#define wxLocale_GetSystemEncoding 3568 -#define wxLocale_GetSystemEncodingName 3569 -#define wxLocale_GetSystemLanguage 3570 -#define wxLocale_IsLoaded 3571 -#define wxLocale_IsOk 3572 -#define wxActivateEvent_GetActive 3573 -#define wxPopupWindow_new_2 3575 -#define wxPopupWindow_new_0 3576 -#define wxPopupWindow_destruct 3578 -#define wxPopupWindow_Create 3579 -#define wxPopupWindow_Position 3580 -#define wxPopupTransientWindow_new_0 3581 -#define wxPopupTransientWindow_new_2 3582 -#define wxPopupTransientWindow_destruct 3583 -#define wxPopupTransientWindow_Popup 3584 -#define wxPopupTransientWindow_Dismiss 3585 -#define wxOverlay_new 3586 -#define wxOverlay_destruct 3587 -#define wxOverlay_Reset 3588 -#define wxDCOverlay_new_6 3589 -#define wxDCOverlay_new_2 3590 -#define wxDCOverlay_destruct 3591 -#define wxDCOverlay_Clear 3592 +#define wxToolBar_AddStretchableSpace 984 +#define wxToolBar_InsertStretchableSpace 985 +#define wxToolBar_DeleteTool 986 +#define wxToolBar_DeleteToolByPos 987 +#define wxToolBar_EnableTool 988 +#define wxToolBar_FindById 989 +#define wxToolBar_FindControl 990 +#define wxToolBar_FindToolForPosition 991 +#define wxToolBar_GetToolSize 992 +#define wxToolBar_GetToolBitmapSize 993 +#define wxToolBar_GetMargins 994 +#define wxToolBar_GetToolEnabled 995 +#define wxToolBar_GetToolLongHelp 996 +#define wxToolBar_GetToolPacking 997 +#define wxToolBar_GetToolPos 998 +#define wxToolBar_GetToolSeparation 999 +#define wxToolBar_GetToolShortHelp 1000 +#define wxToolBar_GetToolState 1001 +#define wxToolBar_InsertControl 1002 +#define wxToolBar_InsertSeparator 1003 +#define wxToolBar_InsertTool_5 1004 +#define wxToolBar_InsertTool_2 1005 +#define wxToolBar_InsertTool_4 1006 +#define wxToolBar_Realize 1007 +#define wxToolBar_RemoveTool 1008 +#define wxToolBar_SetMargins 1009 +#define wxToolBar_SetToolBitmapSize 1010 +#define wxToolBar_SetToolLongHelp 1011 +#define wxToolBar_SetToolPacking 1012 +#define wxToolBar_SetToolShortHelp 1013 +#define wxToolBar_SetToolSeparation 1014 +#define wxToolBar_ToggleTool 1015 +#define wxStatusBar_new_0 1017 +#define wxStatusBar_new_2 1018 +#define wxStatusBar_destruct 1020 +#define wxStatusBar_Create 1021 +#define wxStatusBar_GetFieldRect 1022 +#define wxStatusBar_GetFieldsCount 1023 +#define wxStatusBar_GetStatusText 1024 +#define wxStatusBar_PopStatusText 1025 +#define wxStatusBar_PushStatusText 1026 +#define wxStatusBar_SetFieldsCount 1027 +#define wxStatusBar_SetMinHeight 1028 +#define wxStatusBar_SetStatusText 1029 +#define wxStatusBar_SetStatusWidths 1030 +#define wxStatusBar_SetStatusStyles 1031 +#define wxBitmap_new_0 1032 +#define wxBitmap_new_3 1033 +#define wxBitmap_new_4 1034 +#define wxBitmap_new_2_0 1035 +#define wxBitmap_new_2_1 1036 +#define wxBitmap_destruct 1037 +#define wxBitmap_ConvertToImage 1038 +#define wxBitmap_CopyFromIcon 1039 +#define wxBitmap_Create 1040 +#define wxBitmap_GetDepth 1041 +#define wxBitmap_GetHeight 1042 +#define wxBitmap_GetPalette 1043 +#define wxBitmap_GetMask 1044 +#define wxBitmap_GetWidth 1045 +#define wxBitmap_GetSubBitmap 1046 +#define wxBitmap_LoadFile 1047 +#define wxBitmap_Ok 1048 +#define wxBitmap_SaveFile 1049 +#define wxBitmap_SetDepth 1050 +#define wxBitmap_SetHeight 1051 +#define wxBitmap_SetMask 1052 +#define wxBitmap_SetPalette 1053 +#define wxBitmap_SetWidth 1054 +#define wxIcon_new_0 1055 +#define wxIcon_new_2 1056 +#define wxIcon_new_1 1057 +#define wxIcon_CopyFromBitmap 1058 +#define wxIcon_destroy 1059 +#define wxIconBundle_new_0 1060 +#define wxIconBundle_new_2 1061 +#define wxIconBundle_new_1_0 1062 +#define wxIconBundle_new_1_1 1063 +#define wxIconBundle_destruct 1064 +#define wxIconBundle_AddIcon_2 1065 +#define wxIconBundle_AddIcon_1 1066 +#define wxIconBundle_GetIcon_1_1 1067 +#define wxIconBundle_GetIcon_1_0 1068 +#define wxCursor_new_0 1069 +#define wxCursor_new_1_0 1070 +#define wxCursor_new_1_1 1071 +#define wxCursor_new_4 1072 +#define wxCursor_destruct 1073 +#define wxCursor_Ok 1074 +#define wxMask_new_0 1075 +#define wxMask_new_2_1 1076 +#define wxMask_new_2_0 1077 +#define wxMask_new_1 1078 +#define wxMask_destruct 1079 +#define wxMask_Create_2_1 1080 +#define wxMask_Create_2_0 1081 +#define wxMask_Create_1 1082 +#define wxImage_new_0 1083 +#define wxImage_new_3_0 1084 +#define wxImage_new_4 1085 +#define wxImage_new_5 1086 +#define wxImage_new_2 1087 +#define wxImage_new_3_1 1088 +#define wxImage_Blur 1089 +#define wxImage_BlurHorizontal 1090 +#define wxImage_BlurVertical 1091 +#define wxImage_ConvertAlphaToMask 1092 +#define wxImage_ConvertToGreyscale 1093 +#define wxImage_ConvertToMono 1094 +#define wxImage_Copy 1095 +#define wxImage_Create_3 1096 +#define wxImage_Create_4 1097 +#define wxImage_Create_5 1098 +#define wxImage_Destroy 1099 +#define wxImage_FindFirstUnusedColour 1100 +#define wxImage_GetImageExtWildcard 1101 +#define wxImage_GetAlpha_2 1102 +#define wxImage_GetAlpha_0 1103 +#define wxImage_GetBlue 1104 +#define wxImage_GetData 1105 +#define wxImage_GetGreen 1106 +#define wxImage_GetImageCount 1107 +#define wxImage_GetHeight 1108 +#define wxImage_GetMaskBlue 1109 +#define wxImage_GetMaskGreen 1110 +#define wxImage_GetMaskRed 1111 +#define wxImage_GetOrFindMaskColour 1112 +#define wxImage_GetPalette 1113 +#define wxImage_GetRed 1114 +#define wxImage_GetSubImage 1115 +#define wxImage_GetWidth 1116 +#define wxImage_HasAlpha 1117 +#define wxImage_HasMask 1118 +#define wxImage_GetOption 1119 +#define wxImage_GetOptionInt 1120 +#define wxImage_HasOption 1121 +#define wxImage_InitAlpha 1122 +#define wxImage_InitStandardHandlers 1123 +#define wxImage_IsTransparent 1124 +#define wxImage_LoadFile_2 1125 +#define wxImage_LoadFile_3 1126 +#define wxImage_Ok 1127 +#define wxImage_RemoveHandler 1128 +#define wxImage_Mirror 1129 +#define wxImage_Replace 1130 +#define wxImage_Rescale 1131 +#define wxImage_Resize 1132 +#define wxImage_Rotate 1133 +#define wxImage_RotateHue 1134 +#define wxImage_Rotate90 1135 +#define wxImage_SaveFile_1 1136 +#define wxImage_SaveFile_2_0 1137 +#define wxImage_SaveFile_2_1 1138 +#define wxImage_Scale 1139 +#define wxImage_Size 1140 +#define wxImage_SetAlpha_3 1141 +#define wxImage_SetAlpha_2 1142 +#define wxImage_SetData_2 1143 +#define wxImage_SetData_4 1144 +#define wxImage_SetMask 1145 +#define wxImage_SetMaskColour 1146 +#define wxImage_SetMaskFromImage 1147 +#define wxImage_SetOption_2_1 1148 +#define wxImage_SetOption_2_0 1149 +#define wxImage_SetPalette 1150 +#define wxImage_SetRGB_5 1151 +#define wxImage_SetRGB_4 1152 +#define wxImage_destroy 1153 +#define wxBrush_new_0 1154 +#define wxBrush_new_2 1155 +#define wxBrush_new_1 1156 +#define wxBrush_destruct 1158 +#define wxBrush_GetColour 1159 +#define wxBrush_GetStipple 1160 +#define wxBrush_GetStyle 1161 +#define wxBrush_IsHatch 1162 +#define wxBrush_IsOk 1163 +#define wxBrush_SetColour_1 1164 +#define wxBrush_SetColour_3 1165 +#define wxBrush_SetStipple 1166 +#define wxBrush_SetStyle 1167 +#define wxPen_new_0 1168 +#define wxPen_new_2 1169 +#define wxPen_destruct 1170 +#define wxPen_GetCap 1171 +#define wxPen_GetColour 1172 +#define wxPen_GetJoin 1173 +#define wxPen_GetStyle 1174 +#define wxPen_GetWidth 1175 +#define wxPen_IsOk 1176 +#define wxPen_SetCap 1177 +#define wxPen_SetColour_1 1178 +#define wxPen_SetColour_3 1179 +#define wxPen_SetJoin 1180 +#define wxPen_SetStyle 1181 +#define wxPen_SetWidth 1182 +#define wxRegion_new_0 1183 +#define wxRegion_new_4 1184 +#define wxRegion_new_2 1185 +#define wxRegion_new_1_1 1186 +#define wxRegion_new_1_0 1188 +#define wxRegion_destruct 1190 +#define wxRegion_Clear 1191 +#define wxRegion_Contains_2 1192 +#define wxRegion_Contains_1_0 1193 +#define wxRegion_Contains_4 1194 +#define wxRegion_Contains_1_1 1195 +#define wxRegion_ConvertToBitmap 1196 +#define wxRegion_GetBox 1197 +#define wxRegion_Intersect_4 1198 +#define wxRegion_Intersect_1_1 1199 +#define wxRegion_Intersect_1_0 1200 +#define wxRegion_IsEmpty 1201 +#define wxRegion_Subtract_4 1202 +#define wxRegion_Subtract_1_1 1203 +#define wxRegion_Subtract_1_0 1204 +#define wxRegion_Offset_2 1205 +#define wxRegion_Offset_1 1206 +#define wxRegion_Union_4 1207 +#define wxRegion_Union_1_2 1208 +#define wxRegion_Union_1_1 1209 +#define wxRegion_Union_1_0 1210 +#define wxRegion_Union_3 1211 +#define wxRegion_Xor_4 1212 +#define wxRegion_Xor_1_1 1213 +#define wxRegion_Xor_1_0 1214 +#define wxAcceleratorTable_new_0 1215 +#define wxAcceleratorTable_new_2 1216 +#define wxAcceleratorTable_destruct 1217 +#define wxAcceleratorTable_Ok 1218 +#define wxAcceleratorEntry_new_1_0 1219 +#define wxAcceleratorEntry_new_1_1 1220 +#define wxAcceleratorEntry_GetCommand 1221 +#define wxAcceleratorEntry_GetFlags 1222 +#define wxAcceleratorEntry_GetKeyCode 1223 +#define wxAcceleratorEntry_Set 1224 +#define wxAcceleratorEntry_destroy 1225 +#define wxCaret_new_3 1230 +#define wxCaret_new_2 1231 +#define wxCaret_destruct 1233 +#define wxCaret_Create_3 1234 +#define wxCaret_Create_2 1235 +#define wxCaret_GetBlinkTime 1236 +#define wxCaret_GetPosition 1238 +#define wxCaret_GetSize 1240 +#define wxCaret_GetWindow 1241 +#define wxCaret_Hide 1242 +#define wxCaret_IsOk 1243 +#define wxCaret_IsVisible 1244 +#define wxCaret_Move_2 1245 +#define wxCaret_Move_1 1246 +#define wxCaret_SetBlinkTime 1247 +#define wxCaret_SetSize_2 1248 +#define wxCaret_SetSize_1 1249 +#define wxCaret_Show 1250 +#define wxSizer_Add_2_1 1251 +#define wxSizer_Add_2_0 1252 +#define wxSizer_Add_3 1253 +#define wxSizer_Add_2_3 1254 +#define wxSizer_Add_2_2 1255 +#define wxSizer_AddSpacer 1256 +#define wxSizer_AddStretchSpacer 1257 +#define wxSizer_CalcMin 1258 +#define wxSizer_Clear 1259 +#define wxSizer_Detach_1_2 1260 +#define wxSizer_Detach_1_1 1261 +#define wxSizer_Detach_1_0 1262 +#define wxSizer_Fit 1263 +#define wxSizer_FitInside 1264 +#define wxSizer_GetChildren 1265 +#define wxSizer_GetItem_2_1 1266 +#define wxSizer_GetItem_2_0 1267 +#define wxSizer_GetItem_1 1268 +#define wxSizer_GetSize 1269 +#define wxSizer_GetPosition 1270 +#define wxSizer_GetMinSize 1271 +#define wxSizer_Hide_2_0 1272 +#define wxSizer_Hide_2_1 1273 +#define wxSizer_Hide_1 1274 +#define wxSizer_Insert_3_1 1275 +#define wxSizer_Insert_3_0 1276 +#define wxSizer_Insert_4 1277 +#define wxSizer_Insert_3_3 1278 +#define wxSizer_Insert_3_2 1279 +#define wxSizer_Insert_2 1280 +#define wxSizer_InsertSpacer 1281 +#define wxSizer_InsertStretchSpacer 1282 +#define wxSizer_IsShown_1_2 1283 +#define wxSizer_IsShown_1_1 1284 +#define wxSizer_IsShown_1_0 1285 +#define wxSizer_Layout 1286 +#define wxSizer_Prepend_2_1 1287 +#define wxSizer_Prepend_2_0 1288 +#define wxSizer_Prepend_3 1289 +#define wxSizer_Prepend_2_3 1290 +#define wxSizer_Prepend_2_2 1291 +#define wxSizer_Prepend_1 1292 +#define wxSizer_PrependSpacer 1293 +#define wxSizer_PrependStretchSpacer 1294 +#define wxSizer_RecalcSizes 1295 +#define wxSizer_Remove_1_1 1296 +#define wxSizer_Remove_1_0 1297 +#define wxSizer_Replace_3_1 1298 +#define wxSizer_Replace_3_0 1299 +#define wxSizer_Replace_2 1300 +#define wxSizer_SetDimension 1301 +#define wxSizer_SetMinSize_2 1302 +#define wxSizer_SetMinSize_1 1303 +#define wxSizer_SetItemMinSize_3_2 1304 +#define wxSizer_SetItemMinSize_2_2 1305 +#define wxSizer_SetItemMinSize_3_1 1306 +#define wxSizer_SetItemMinSize_2_1 1307 +#define wxSizer_SetItemMinSize_3_0 1308 +#define wxSizer_SetItemMinSize_2_0 1309 +#define wxSizer_SetSizeHints 1310 +#define wxSizer_SetVirtualSizeHints 1311 +#define wxSizer_Show_2_2 1312 +#define wxSizer_Show_2_1 1313 +#define wxSizer_Show_2_0 1314 +#define wxSizer_Show_1 1315 +#define wxSizerFlags_new 1316 +#define wxSizerFlags_Align 1317 +#define wxSizerFlags_Border_2 1318 +#define wxSizerFlags_Border_1 1319 +#define wxSizerFlags_Center 1320 +#define wxSizerFlags_Centre 1321 +#define wxSizerFlags_Expand 1322 +#define wxSizerFlags_Left 1323 +#define wxSizerFlags_Proportion 1324 +#define wxSizerFlags_Right 1325 +#define wxSizerFlags_destroy 1326 +#define wxSizerItem_new_5_1 1327 +#define wxSizerItem_new_2_1 1328 +#define wxSizerItem_new_5_0 1329 +#define wxSizerItem_new_2_0 1330 +#define wxSizerItem_new_6 1331 +#define wxSizerItem_new_3 1332 +#define wxSizerItem_new_0 1333 +#define wxSizerItem_destruct 1334 +#define wxSizerItem_CalcMin 1335 +#define wxSizerItem_DeleteWindows 1336 +#define wxSizerItem_DetachSizer 1337 +#define wxSizerItem_GetBorder 1338 +#define wxSizerItem_GetFlag 1339 +#define wxSizerItem_GetMinSize 1340 +#define wxSizerItem_GetPosition 1341 +#define wxSizerItem_GetProportion 1342 +#define wxSizerItem_GetRatio 1343 +#define wxSizerItem_GetRect 1344 +#define wxSizerItem_GetSize 1345 +#define wxSizerItem_GetSizer 1346 +#define wxSizerItem_GetSpacer 1347 +#define wxSizerItem_GetUserData 1348 +#define wxSizerItem_GetWindow 1349 +#define wxSizerItem_IsSizer 1350 +#define wxSizerItem_IsShown 1351 +#define wxSizerItem_IsSpacer 1352 +#define wxSizerItem_IsWindow 1353 +#define wxSizerItem_SetBorder 1354 +#define wxSizerItem_SetDimension 1355 +#define wxSizerItem_SetFlag 1356 +#define wxSizerItem_SetInitSize 1357 +#define wxSizerItem_SetMinSize_1 1358 +#define wxSizerItem_SetMinSize_2 1359 +#define wxSizerItem_SetProportion 1360 +#define wxSizerItem_SetRatio_2 1361 +#define wxSizerItem_SetRatio_1_1 1362 +#define wxSizerItem_SetRatio_1_0 1363 +#define wxSizerItem_SetSizer 1364 +#define wxSizerItem_SetSpacer_1 1365 +#define wxSizerItem_SetSpacer_2 1366 +#define wxSizerItem_SetWindow 1367 +#define wxSizerItem_Show 1368 +#define wxBoxSizer_new 1369 +#define wxBoxSizer_GetOrientation 1370 +#define wxBoxSizer_destroy 1371 +#define wxStaticBoxSizer_new_2 1372 +#define wxStaticBoxSizer_new_3 1373 +#define wxStaticBoxSizer_GetStaticBox 1374 +#define wxStaticBoxSizer_destroy 1375 +#define wxGridSizer_new_4 1376 +#define wxGridSizer_new_2 1377 +#define wxGridSizer_GetCols 1378 +#define wxGridSizer_GetHGap 1379 +#define wxGridSizer_GetRows 1380 +#define wxGridSizer_GetVGap 1381 +#define wxGridSizer_SetCols 1382 +#define wxGridSizer_SetHGap 1383 +#define wxGridSizer_SetRows 1384 +#define wxGridSizer_SetVGap 1385 +#define wxGridSizer_destroy 1386 +#define wxFlexGridSizer_new_4 1387 +#define wxFlexGridSizer_new_2 1388 +#define wxFlexGridSizer_AddGrowableCol 1389 +#define wxFlexGridSizer_AddGrowableRow 1390 +#define wxFlexGridSizer_GetFlexibleDirection 1391 +#define wxFlexGridSizer_GetNonFlexibleGrowMode 1392 +#define wxFlexGridSizer_RemoveGrowableCol 1393 +#define wxFlexGridSizer_RemoveGrowableRow 1394 +#define wxFlexGridSizer_SetFlexibleDirection 1395 +#define wxFlexGridSizer_SetNonFlexibleGrowMode 1396 +#define wxFlexGridSizer_destroy 1397 +#define wxGridBagSizer_new 1398 +#define wxGridBagSizer_Add_3_2 1399 +#define wxGridBagSizer_Add_3_1 1400 +#define wxGridBagSizer_Add_4 1401 +#define wxGridBagSizer_Add_1_0 1402 +#define wxGridBagSizer_Add_2_1 1403 +#define wxGridBagSizer_Add_2_0 1404 +#define wxGridBagSizer_Add_3_0 1405 +#define wxGridBagSizer_Add_1_1 1406 +#define wxGridBagSizer_CalcMin 1407 +#define wxGridBagSizer_CheckForIntersection_2 1408 +#define wxGridBagSizer_CheckForIntersection_3 1409 +#define wxGridBagSizer_FindItem_1_1 1410 +#define wxGridBagSizer_FindItem_1_0 1411 +#define wxGridBagSizer_FindItemAtPoint 1412 +#define wxGridBagSizer_FindItemAtPosition 1413 +#define wxGridBagSizer_FindItemWithData 1414 +#define wxGridBagSizer_GetCellSize 1415 +#define wxGridBagSizer_GetEmptyCellSize 1416 +#define wxGridBagSizer_GetItemPosition_1_2 1417 +#define wxGridBagSizer_GetItemPosition_1_1 1418 +#define wxGridBagSizer_GetItemPosition_1_0 1419 +#define wxGridBagSizer_GetItemSpan_1_2 1420 +#define wxGridBagSizer_GetItemSpan_1_1 1421 +#define wxGridBagSizer_GetItemSpan_1_0 1422 +#define wxGridBagSizer_SetEmptyCellSize 1423 +#define wxGridBagSizer_SetItemPosition_2_2 1424 +#define wxGridBagSizer_SetItemPosition_2_1 1425 +#define wxGridBagSizer_SetItemPosition_2_0 1426 +#define wxGridBagSizer_SetItemSpan_2_2 1427 +#define wxGridBagSizer_SetItemSpan_2_1 1428 +#define wxGridBagSizer_SetItemSpan_2_0 1429 +#define wxGridBagSizer_destroy 1430 +#define wxStdDialogButtonSizer_new 1431 +#define wxStdDialogButtonSizer_AddButton 1432 +#define wxStdDialogButtonSizer_Realize 1433 +#define wxStdDialogButtonSizer_SetAffirmativeButton 1434 +#define wxStdDialogButtonSizer_SetCancelButton 1435 +#define wxStdDialogButtonSizer_SetNegativeButton 1436 +#define wxStdDialogButtonSizer_destroy 1437 +#define wxFont_new_0 1438 +#define wxFont_new_1 1439 +#define wxFont_new_5 1440 +#define wxFont_destruct 1442 +#define wxFont_IsFixedWidth 1443 +#define wxFont_GetDefaultEncoding 1444 +#define wxFont_GetFaceName 1445 +#define wxFont_GetFamily 1446 +#define wxFont_GetNativeFontInfoDesc 1447 +#define wxFont_GetNativeFontInfoUserDesc 1448 +#define wxFont_GetPointSize 1449 +#define wxFont_GetStyle 1450 +#define wxFont_GetUnderlined 1451 +#define wxFont_GetWeight 1452 +#define wxFont_Ok 1453 +#define wxFont_SetDefaultEncoding 1454 +#define wxFont_SetFaceName 1455 +#define wxFont_SetFamily 1456 +#define wxFont_SetPointSize 1457 +#define wxFont_SetStyle 1458 +#define wxFont_SetUnderlined 1459 +#define wxFont_SetWeight 1460 +#define wxToolTip_Enable 1461 +#define wxToolTip_SetDelay 1462 +#define wxToolTip_new 1463 +#define wxToolTip_SetTip 1464 +#define wxToolTip_GetTip 1465 +#define wxToolTip_GetWindow 1466 +#define wxToolTip_destroy 1467 +#define wxButton_new_3 1469 +#define wxButton_new_0 1470 +#define wxButton_destruct 1471 +#define wxButton_Create 1472 +#define wxButton_GetDefaultSize 1473 +#define wxButton_SetDefault 1474 +#define wxButton_SetLabel 1475 +#define wxBitmapButton_new_4 1477 +#define wxBitmapButton_new_0 1478 +#define wxBitmapButton_Create 1479 +#define wxBitmapButton_GetBitmapDisabled 1480 +#define wxBitmapButton_GetBitmapFocus 1482 +#define wxBitmapButton_GetBitmapLabel 1484 +#define wxBitmapButton_GetBitmapSelected 1486 +#define wxBitmapButton_SetBitmapDisabled 1488 +#define wxBitmapButton_SetBitmapFocus 1489 +#define wxBitmapButton_SetBitmapLabel 1490 +#define wxBitmapButton_SetBitmapSelected 1491 +#define wxBitmapButton_destroy 1492 +#define wxToggleButton_new_0 1493 +#define wxToggleButton_new_4 1494 +#define wxToggleButton_Create 1495 +#define wxToggleButton_GetValue 1496 +#define wxToggleButton_SetValue 1497 +#define wxToggleButton_destroy 1498 +#define wxCalendarCtrl_new_0 1499 +#define wxCalendarCtrl_new_3 1500 +#define wxCalendarCtrl_Create 1501 +#define wxCalendarCtrl_destruct 1502 +#define wxCalendarCtrl_SetDate 1503 +#define wxCalendarCtrl_GetDate 1504 +#define wxCalendarCtrl_EnableYearChange 1505 +#define wxCalendarCtrl_EnableMonthChange 1506 +#define wxCalendarCtrl_EnableHolidayDisplay 1507 +#define wxCalendarCtrl_SetHeaderColours 1508 +#define wxCalendarCtrl_GetHeaderColourFg 1509 +#define wxCalendarCtrl_GetHeaderColourBg 1510 +#define wxCalendarCtrl_SetHighlightColours 1511 +#define wxCalendarCtrl_GetHighlightColourFg 1512 +#define wxCalendarCtrl_GetHighlightColourBg 1513 +#define wxCalendarCtrl_SetHolidayColours 1514 +#define wxCalendarCtrl_GetHolidayColourFg 1515 +#define wxCalendarCtrl_GetHolidayColourBg 1516 +#define wxCalendarCtrl_GetAttr 1517 +#define wxCalendarCtrl_SetAttr 1518 +#define wxCalendarCtrl_SetHoliday 1519 +#define wxCalendarCtrl_ResetAttr 1520 +#define wxCalendarCtrl_HitTest 1521 +#define wxCalendarDateAttr_new_0 1522 +#define wxCalendarDateAttr_new_2_1 1523 +#define wxCalendarDateAttr_new_2_0 1524 +#define wxCalendarDateAttr_SetTextColour 1525 +#define wxCalendarDateAttr_SetBackgroundColour 1526 +#define wxCalendarDateAttr_SetBorderColour 1527 +#define wxCalendarDateAttr_SetFont 1528 +#define wxCalendarDateAttr_SetBorder 1529 +#define wxCalendarDateAttr_SetHoliday 1530 +#define wxCalendarDateAttr_HasTextColour 1531 +#define wxCalendarDateAttr_HasBackgroundColour 1532 +#define wxCalendarDateAttr_HasBorderColour 1533 +#define wxCalendarDateAttr_HasFont 1534 +#define wxCalendarDateAttr_HasBorder 1535 +#define wxCalendarDateAttr_IsHoliday 1536 +#define wxCalendarDateAttr_GetTextColour 1537 +#define wxCalendarDateAttr_GetBackgroundColour 1538 +#define wxCalendarDateAttr_GetBorderColour 1539 +#define wxCalendarDateAttr_GetFont 1540 +#define wxCalendarDateAttr_GetBorder 1541 +#define wxCalendarDateAttr_destroy 1542 +#define wxCheckBox_new_4 1544 +#define wxCheckBox_new_0 1545 +#define wxCheckBox_Create 1546 +#define wxCheckBox_GetValue 1547 +#define wxCheckBox_Get3StateValue 1548 +#define wxCheckBox_Is3rdStateAllowedForUser 1549 +#define wxCheckBox_Is3State 1550 +#define wxCheckBox_IsChecked 1551 +#define wxCheckBox_SetValue 1552 +#define wxCheckBox_Set3StateValue 1553 +#define wxCheckBox_destroy 1554 +#define wxCheckListBox_new_0 1555 +#define wxCheckListBox_new_3 1557 +#define wxCheckListBox_Check 1558 +#define wxCheckListBox_IsChecked 1559 +#define wxCheckListBox_destroy 1560 +#define wxChoice_new_3 1563 +#define wxChoice_new_0 1564 +#define wxChoice_destruct 1566 +#define wxChoice_Create 1568 +#define wxChoice_Delete 1569 +#define wxChoice_GetColumns 1570 +#define wxChoice_SetColumns 1571 +#define wxComboBox_new_0 1572 +#define wxComboBox_new_3 1574 +#define wxComboBox_destruct 1575 +#define wxComboBox_Create 1577 +#define wxComboBox_CanCopy 1578 +#define wxComboBox_CanCut 1579 +#define wxComboBox_CanPaste 1580 +#define wxComboBox_CanRedo 1581 +#define wxComboBox_CanUndo 1582 +#define wxComboBox_Copy 1583 +#define wxComboBox_Cut 1584 +#define wxComboBox_GetInsertionPoint 1585 +#define wxComboBox_GetLastPosition 1586 +#define wxComboBox_GetValue 1587 +#define wxComboBox_Paste 1588 +#define wxComboBox_Redo 1589 +#define wxComboBox_Replace 1590 +#define wxComboBox_Remove 1591 +#define wxComboBox_SetInsertionPoint 1592 +#define wxComboBox_SetInsertionPointEnd 1593 +#define wxComboBox_SetSelection_1 1594 +#define wxComboBox_SetSelection_2 1595 +#define wxComboBox_SetValue 1596 +#define wxComboBox_Undo 1597 +#define wxGauge_new_0 1598 +#define wxGauge_new_4 1599 +#define wxGauge_Create 1600 +#define wxGauge_GetBezelFace 1601 +#define wxGauge_GetRange 1602 +#define wxGauge_GetShadowWidth 1603 +#define wxGauge_GetValue 1604 +#define wxGauge_IsVertical 1605 +#define wxGauge_SetBezelFace 1606 +#define wxGauge_SetRange 1607 +#define wxGauge_SetShadowWidth 1608 +#define wxGauge_SetValue 1609 +#define wxGauge_Pulse 1610 +#define wxGauge_destroy 1611 +#define wxGenericDirCtrl_new_0 1612 +#define wxGenericDirCtrl_new_2 1613 +#define wxGenericDirCtrl_destruct 1614 +#define wxGenericDirCtrl_Create 1615 +#define wxGenericDirCtrl_Init 1616 +#define wxGenericDirCtrl_CollapseTree 1617 +#define wxGenericDirCtrl_ExpandPath 1618 +#define wxGenericDirCtrl_GetDefaultPath 1619 +#define wxGenericDirCtrl_GetPath 1620 +#define wxGenericDirCtrl_GetFilePath 1621 +#define wxGenericDirCtrl_GetFilter 1622 +#define wxGenericDirCtrl_GetFilterIndex 1623 +#define wxGenericDirCtrl_GetRootId 1624 +#define wxGenericDirCtrl_GetTreeCtrl 1625 +#define wxGenericDirCtrl_ReCreateTree 1626 +#define wxGenericDirCtrl_SetDefaultPath 1627 +#define wxGenericDirCtrl_SetFilter 1628 +#define wxGenericDirCtrl_SetFilterIndex 1629 +#define wxGenericDirCtrl_SetPath 1630 +#define wxStaticBox_new_4 1632 +#define wxStaticBox_new_0 1633 +#define wxStaticBox_Create 1634 +#define wxStaticBox_destroy 1635 +#define wxStaticLine_new_2 1637 +#define wxStaticLine_new_0 1638 +#define wxStaticLine_Create 1639 +#define wxStaticLine_IsVertical 1640 +#define wxStaticLine_GetDefaultSize 1641 +#define wxStaticLine_destroy 1642 +#define wxListBox_new_3 1645 +#define wxListBox_new_0 1646 +#define wxListBox_destruct 1648 +#define wxListBox_Create 1650 +#define wxListBox_Deselect 1651 +#define wxListBox_GetSelections 1652 +#define wxListBox_InsertItems 1653 +#define wxListBox_IsSelected 1654 +#define wxListBox_Set 1655 +#define wxListBox_HitTest 1656 +#define wxListBox_SetFirstItem_1_0 1657 +#define wxListBox_SetFirstItem_1_1 1658 +#define wxListCtrl_new_0 1659 +#define wxListCtrl_new_2 1660 +#define wxListCtrl_Arrange 1661 +#define wxListCtrl_AssignImageList 1662 +#define wxListCtrl_ClearAll 1663 +#define wxListCtrl_Create 1664 +#define wxListCtrl_DeleteAllItems 1665 +#define wxListCtrl_DeleteColumn 1666 +#define wxListCtrl_DeleteItem 1667 +#define wxListCtrl_EditLabel 1668 +#define wxListCtrl_EnsureVisible 1669 +#define wxListCtrl_FindItem_3_0 1670 +#define wxListCtrl_FindItem_3_1 1671 +#define wxListCtrl_GetColumn 1672 +#define wxListCtrl_GetColumnCount 1673 +#define wxListCtrl_GetColumnWidth 1674 +#define wxListCtrl_GetCountPerPage 1675 +#define wxListCtrl_GetEditControl 1676 +#define wxListCtrl_GetImageList 1677 +#define wxListCtrl_GetItem 1678 +#define wxListCtrl_GetItemBackgroundColour 1679 +#define wxListCtrl_GetItemCount 1680 +#define wxListCtrl_GetItemData 1681 +#define wxListCtrl_GetItemFont 1682 +#define wxListCtrl_GetItemPosition 1683 +#define wxListCtrl_GetItemRect 1684 +#define wxListCtrl_GetItemSpacing 1685 +#define wxListCtrl_GetItemState 1686 +#define wxListCtrl_GetItemText 1687 +#define wxListCtrl_GetItemTextColour 1688 +#define wxListCtrl_GetNextItem 1689 +#define wxListCtrl_GetSelectedItemCount 1690 +#define wxListCtrl_GetTextColour 1691 +#define wxListCtrl_GetTopItem 1692 +#define wxListCtrl_GetViewRect 1693 +#define wxListCtrl_HitTest 1694 +#define wxListCtrl_InsertColumn_2 1695 +#define wxListCtrl_InsertColumn_3 1696 +#define wxListCtrl_InsertItem_1 1697 +#define wxListCtrl_InsertItem_2_1 1698 +#define wxListCtrl_InsertItem_2_0 1699 +#define wxListCtrl_InsertItem_3 1700 +#define wxListCtrl_RefreshItem 1701 +#define wxListCtrl_RefreshItems 1702 +#define wxListCtrl_ScrollList 1703 +#define wxListCtrl_SetBackgroundColour 1704 +#define wxListCtrl_SetColumn 1705 +#define wxListCtrl_SetColumnWidth 1706 +#define wxListCtrl_SetImageList 1707 +#define wxListCtrl_SetItem_1 1708 +#define wxListCtrl_SetItem_4 1709 +#define wxListCtrl_SetItemBackgroundColour 1710 +#define wxListCtrl_SetItemCount 1711 +#define wxListCtrl_SetItemData 1712 +#define wxListCtrl_SetItemFont 1713 +#define wxListCtrl_SetItemImage 1714 +#define wxListCtrl_SetItemColumnImage 1715 +#define wxListCtrl_SetItemPosition 1716 +#define wxListCtrl_SetItemState 1717 +#define wxListCtrl_SetItemText 1718 +#define wxListCtrl_SetItemTextColour 1719 +#define wxListCtrl_SetSingleStyle 1720 +#define wxListCtrl_SetTextColour 1721 +#define wxListCtrl_SetWindowStyleFlag 1722 +#define wxListCtrl_SortItems 1723 +#define wxListCtrl_destroy 1724 +#define wxListView_ClearColumnImage 1725 +#define wxListView_Focus 1726 +#define wxListView_GetFirstSelected 1727 +#define wxListView_GetFocusedItem 1728 +#define wxListView_GetNextSelected 1729 +#define wxListView_IsSelected 1730 +#define wxListView_Select 1731 +#define wxListView_SetColumnImage 1732 +#define wxListItem_new_0 1733 +#define wxListItem_new_1 1734 +#define wxListItem_destruct 1735 +#define wxListItem_Clear 1736 +#define wxListItem_GetAlign 1737 +#define wxListItem_GetBackgroundColour 1738 +#define wxListItem_GetColumn 1739 +#define wxListItem_GetFont 1740 +#define wxListItem_GetId 1741 +#define wxListItem_GetImage 1742 +#define wxListItem_GetMask 1743 +#define wxListItem_GetState 1744 +#define wxListItem_GetText 1745 +#define wxListItem_GetTextColour 1746 +#define wxListItem_GetWidth 1747 +#define wxListItem_SetAlign 1748 +#define wxListItem_SetBackgroundColour 1749 +#define wxListItem_SetColumn 1750 +#define wxListItem_SetFont 1751 +#define wxListItem_SetId 1752 +#define wxListItem_SetImage 1753 +#define wxListItem_SetMask 1754 +#define wxListItem_SetState 1755 +#define wxListItem_SetStateMask 1756 +#define wxListItem_SetText 1757 +#define wxListItem_SetTextColour 1758 +#define wxListItem_SetWidth 1759 +#define wxListItemAttr_new_0 1760 +#define wxListItemAttr_new_3 1761 +#define wxListItemAttr_GetBackgroundColour 1762 +#define wxListItemAttr_GetFont 1763 +#define wxListItemAttr_GetTextColour 1764 +#define wxListItemAttr_HasBackgroundColour 1765 +#define wxListItemAttr_HasFont 1766 +#define wxListItemAttr_HasTextColour 1767 +#define wxListItemAttr_SetBackgroundColour 1768 +#define wxListItemAttr_SetFont 1769 +#define wxListItemAttr_SetTextColour 1770 +#define wxListItemAttr_destroy 1771 +#define wxImageList_new_0 1772 +#define wxImageList_new_3 1773 +#define wxImageList_Add_1 1774 +#define wxImageList_Add_2_0 1775 +#define wxImageList_Add_2_1 1776 +#define wxImageList_Create 1777 +#define wxImageList_Draw 1779 +#define wxImageList_GetBitmap 1780 +#define wxImageList_GetIcon 1781 +#define wxImageList_GetImageCount 1782 +#define wxImageList_GetSize 1783 +#define wxImageList_Remove 1784 +#define wxImageList_RemoveAll 1785 +#define wxImageList_Replace_2 1786 +#define wxImageList_Replace_3 1787 +#define wxImageList_destroy 1788 +#define wxTextAttr_new_0 1789 +#define wxTextAttr_new_2 1790 +#define wxTextAttr_GetAlignment 1791 +#define wxTextAttr_GetBackgroundColour 1792 +#define wxTextAttr_GetFont 1793 +#define wxTextAttr_GetLeftIndent 1794 +#define wxTextAttr_GetLeftSubIndent 1795 +#define wxTextAttr_GetRightIndent 1796 +#define wxTextAttr_GetTabs 1797 +#define wxTextAttr_GetTextColour 1798 +#define wxTextAttr_HasBackgroundColour 1799 +#define wxTextAttr_HasFont 1800 +#define wxTextAttr_HasTextColour 1801 +#define wxTextAttr_GetFlags 1802 +#define wxTextAttr_IsDefault 1803 +#define wxTextAttr_SetAlignment 1804 +#define wxTextAttr_SetBackgroundColour 1805 +#define wxTextAttr_SetFlags 1806 +#define wxTextAttr_SetFont 1807 +#define wxTextAttr_SetLeftIndent 1808 +#define wxTextAttr_SetRightIndent 1809 +#define wxTextAttr_SetTabs 1810 +#define wxTextAttr_SetTextColour 1811 +#define wxTextAttr_destroy 1812 +#define wxTextCtrl_new_3 1814 +#define wxTextCtrl_new_0 1815 +#define wxTextCtrl_destruct 1817 +#define wxTextCtrl_AppendText 1818 +#define wxTextCtrl_CanCopy 1819 +#define wxTextCtrl_CanCut 1820 +#define wxTextCtrl_CanPaste 1821 +#define wxTextCtrl_CanRedo 1822 +#define wxTextCtrl_CanUndo 1823 +#define wxTextCtrl_Clear 1824 +#define wxTextCtrl_Copy 1825 +#define wxTextCtrl_Create 1826 +#define wxTextCtrl_Cut 1827 +#define wxTextCtrl_DiscardEdits 1828 +#define wxTextCtrl_ChangeValue 1829 +#define wxTextCtrl_EmulateKeyPress 1830 +#define wxTextCtrl_GetDefaultStyle 1831 +#define wxTextCtrl_GetInsertionPoint 1832 +#define wxTextCtrl_GetLastPosition 1833 +#define wxTextCtrl_GetLineLength 1834 +#define wxTextCtrl_GetLineText 1835 +#define wxTextCtrl_GetNumberOfLines 1836 +#define wxTextCtrl_GetRange 1837 +#define wxTextCtrl_GetSelection 1838 +#define wxTextCtrl_GetStringSelection 1839 +#define wxTextCtrl_GetStyle 1840 +#define wxTextCtrl_GetValue 1841 +#define wxTextCtrl_IsEditable 1842 +#define wxTextCtrl_IsModified 1843 +#define wxTextCtrl_IsMultiLine 1844 +#define wxTextCtrl_IsSingleLine 1845 +#define wxTextCtrl_LoadFile 1846 +#define wxTextCtrl_MarkDirty 1847 +#define wxTextCtrl_Paste 1848 +#define wxTextCtrl_PositionToXY 1849 +#define wxTextCtrl_Redo 1850 +#define wxTextCtrl_Remove 1851 +#define wxTextCtrl_Replace 1852 +#define wxTextCtrl_SaveFile 1853 +#define wxTextCtrl_SetDefaultStyle 1854 +#define wxTextCtrl_SetEditable 1855 +#define wxTextCtrl_SetInsertionPoint 1856 +#define wxTextCtrl_SetInsertionPointEnd 1857 +#define wxTextCtrl_SetMaxLength 1859 +#define wxTextCtrl_SetSelection 1860 +#define wxTextCtrl_SetStyle 1861 +#define wxTextCtrl_SetValue 1862 +#define wxTextCtrl_ShowPosition 1863 +#define wxTextCtrl_Undo 1864 +#define wxTextCtrl_WriteText 1865 +#define wxTextCtrl_XYToPosition 1866 +#define wxNotebook_new_0 1869 +#define wxNotebook_new_3 1870 +#define wxNotebook_destruct 1871 +#define wxNotebook_AddPage 1872 +#define wxNotebook_AdvanceSelection 1873 +#define wxNotebook_AssignImageList 1874 +#define wxNotebook_Create 1875 +#define wxNotebook_DeleteAllPages 1876 +#define wxNotebook_DeletePage 1877 +#define wxNotebook_RemovePage 1878 +#define wxNotebook_GetCurrentPage 1879 +#define wxNotebook_GetImageList 1880 +#define wxNotebook_GetPage 1882 +#define wxNotebook_GetPageCount 1883 +#define wxNotebook_GetPageImage 1884 +#define wxNotebook_GetPageText 1885 +#define wxNotebook_GetRowCount 1886 +#define wxNotebook_GetSelection 1887 +#define wxNotebook_GetThemeBackgroundColour 1888 +#define wxNotebook_HitTest 1890 +#define wxNotebook_InsertPage 1892 +#define wxNotebook_SetImageList 1893 +#define wxNotebook_SetPadding 1894 +#define wxNotebook_SetPageSize 1895 +#define wxNotebook_SetPageImage 1896 +#define wxNotebook_SetPageText 1897 +#define wxNotebook_SetSelection 1898 +#define wxNotebook_ChangeSelection 1899 +#define wxChoicebook_new_0 1900 +#define wxChoicebook_new_3 1901 +#define wxChoicebook_AddPage 1902 +#define wxChoicebook_AdvanceSelection 1903 +#define wxChoicebook_AssignImageList 1904 +#define wxChoicebook_Create 1905 +#define wxChoicebook_DeleteAllPages 1906 +#define wxChoicebook_DeletePage 1907 +#define wxChoicebook_RemovePage 1908 +#define wxChoicebook_GetCurrentPage 1909 +#define wxChoicebook_GetImageList 1910 +#define wxChoicebook_GetPage 1912 +#define wxChoicebook_GetPageCount 1913 +#define wxChoicebook_GetPageImage 1914 +#define wxChoicebook_GetPageText 1915 +#define wxChoicebook_GetSelection 1916 +#define wxChoicebook_HitTest 1917 +#define wxChoicebook_InsertPage 1918 +#define wxChoicebook_SetImageList 1919 +#define wxChoicebook_SetPageSize 1920 +#define wxChoicebook_SetPageImage 1921 +#define wxChoicebook_SetPageText 1922 +#define wxChoicebook_SetSelection 1923 +#define wxChoicebook_ChangeSelection 1924 +#define wxChoicebook_destroy 1925 +#define wxToolbook_new_0 1926 +#define wxToolbook_new_3 1927 +#define wxToolbook_AddPage 1928 +#define wxToolbook_AdvanceSelection 1929 +#define wxToolbook_AssignImageList 1930 +#define wxToolbook_Create 1931 +#define wxToolbook_DeleteAllPages 1932 +#define wxToolbook_DeletePage 1933 +#define wxToolbook_RemovePage 1934 +#define wxToolbook_GetCurrentPage 1935 +#define wxToolbook_GetImageList 1936 +#define wxToolbook_GetPage 1938 +#define wxToolbook_GetPageCount 1939 +#define wxToolbook_GetPageImage 1940 +#define wxToolbook_GetPageText 1941 +#define wxToolbook_GetSelection 1942 +#define wxToolbook_HitTest 1944 +#define wxToolbook_InsertPage 1945 +#define wxToolbook_SetImageList 1946 +#define wxToolbook_SetPageSize 1947 +#define wxToolbook_SetPageImage 1948 +#define wxToolbook_SetPageText 1949 +#define wxToolbook_SetSelection 1950 +#define wxToolbook_ChangeSelection 1951 +#define wxToolbook_destroy 1952 +#define wxListbook_new_0 1953 +#define wxListbook_new_3 1954 +#define wxListbook_AddPage 1955 +#define wxListbook_AdvanceSelection 1956 +#define wxListbook_AssignImageList 1957 +#define wxListbook_Create 1958 +#define wxListbook_DeleteAllPages 1959 +#define wxListbook_DeletePage 1960 +#define wxListbook_RemovePage 1961 +#define wxListbook_GetCurrentPage 1962 +#define wxListbook_GetImageList 1963 +#define wxListbook_GetPage 1965 +#define wxListbook_GetPageCount 1966 +#define wxListbook_GetPageImage 1967 +#define wxListbook_GetPageText 1968 +#define wxListbook_GetSelection 1969 +#define wxListbook_HitTest 1971 +#define wxListbook_InsertPage 1972 +#define wxListbook_SetImageList 1973 +#define wxListbook_SetPageSize 1974 +#define wxListbook_SetPageImage 1975 +#define wxListbook_SetPageText 1976 +#define wxListbook_SetSelection 1977 +#define wxListbook_ChangeSelection 1978 +#define wxListbook_destroy 1979 +#define wxTreebook_new_0 1980 +#define wxTreebook_new_3 1981 +#define wxTreebook_AddPage 1982 +#define wxTreebook_AdvanceSelection 1983 +#define wxTreebook_AssignImageList 1984 +#define wxTreebook_Create 1985 +#define wxTreebook_DeleteAllPages 1986 +#define wxTreebook_DeletePage 1987 +#define wxTreebook_RemovePage 1988 +#define wxTreebook_GetCurrentPage 1989 +#define wxTreebook_GetImageList 1990 +#define wxTreebook_GetPage 1992 +#define wxTreebook_GetPageCount 1993 +#define wxTreebook_GetPageImage 1994 +#define wxTreebook_GetPageText 1995 +#define wxTreebook_GetSelection 1996 +#define wxTreebook_ExpandNode 1997 +#define wxTreebook_IsNodeExpanded 1998 +#define wxTreebook_HitTest 2000 +#define wxTreebook_InsertPage 2001 +#define wxTreebook_InsertSubPage 2002 +#define wxTreebook_SetImageList 2003 +#define wxTreebook_SetPageSize 2004 +#define wxTreebook_SetPageImage 2005 +#define wxTreebook_SetPageText 2006 +#define wxTreebook_SetSelection 2007 +#define wxTreebook_ChangeSelection 2008 +#define wxTreebook_destroy 2009 +#define wxTreeCtrl_new_2 2012 +#define wxTreeCtrl_new_0 2013 +#define wxTreeCtrl_destruct 2015 +#define wxTreeCtrl_AddRoot 2016 +#define wxTreeCtrl_AppendItem 2017 +#define wxTreeCtrl_AssignImageList 2018 +#define wxTreeCtrl_AssignStateImageList 2019 +#define wxTreeCtrl_Collapse 2020 +#define wxTreeCtrl_CollapseAndReset 2021 +#define wxTreeCtrl_Create 2022 +#define wxTreeCtrl_Delete 2023 +#define wxTreeCtrl_DeleteAllItems 2024 +#define wxTreeCtrl_DeleteChildren 2025 +#define wxTreeCtrl_EditLabel 2026 +#define wxTreeCtrl_EnsureVisible 2027 +#define wxTreeCtrl_Expand 2028 +#define wxTreeCtrl_GetBoundingRect 2029 +#define wxTreeCtrl_GetChildrenCount 2031 +#define wxTreeCtrl_GetCount 2032 +#define wxTreeCtrl_GetEditControl 2033 +#define wxTreeCtrl_GetFirstChild 2034 +#define wxTreeCtrl_GetNextChild 2035 +#define wxTreeCtrl_GetFirstVisibleItem 2036 +#define wxTreeCtrl_GetImageList 2037 +#define wxTreeCtrl_GetIndent 2038 +#define wxTreeCtrl_GetItemBackgroundColour 2039 +#define wxTreeCtrl_GetItemData 2040 +#define wxTreeCtrl_GetItemFont 2041 +#define wxTreeCtrl_GetItemImage_1 2042 +#define wxTreeCtrl_GetItemImage_2 2043 +#define wxTreeCtrl_GetItemText 2044 +#define wxTreeCtrl_GetItemTextColour 2045 +#define wxTreeCtrl_GetLastChild 2046 +#define wxTreeCtrl_GetNextSibling 2047 +#define wxTreeCtrl_GetNextVisible 2048 +#define wxTreeCtrl_GetItemParent 2049 +#define wxTreeCtrl_GetPrevSibling 2050 +#define wxTreeCtrl_GetPrevVisible 2051 +#define wxTreeCtrl_GetRootItem 2052 +#define wxTreeCtrl_GetSelection 2053 +#define wxTreeCtrl_GetSelections 2054 +#define wxTreeCtrl_GetStateImageList 2055 +#define wxTreeCtrl_HitTest 2056 +#define wxTreeCtrl_InsertItem 2058 +#define wxTreeCtrl_IsBold 2059 +#define wxTreeCtrl_IsExpanded 2060 +#define wxTreeCtrl_IsSelected 2061 +#define wxTreeCtrl_IsVisible 2062 +#define wxTreeCtrl_ItemHasChildren 2063 +#define wxTreeCtrl_IsTreeItemIdOk 2064 +#define wxTreeCtrl_PrependItem 2065 +#define wxTreeCtrl_ScrollTo 2066 +#define wxTreeCtrl_SelectItem_1 2067 +#define wxTreeCtrl_SelectItem_2 2068 +#define wxTreeCtrl_SetIndent 2069 +#define wxTreeCtrl_SetImageList 2070 +#define wxTreeCtrl_SetItemBackgroundColour 2071 +#define wxTreeCtrl_SetItemBold 2072 +#define wxTreeCtrl_SetItemData 2073 +#define wxTreeCtrl_SetItemDropHighlight 2074 +#define wxTreeCtrl_SetItemFont 2075 +#define wxTreeCtrl_SetItemHasChildren 2076 +#define wxTreeCtrl_SetItemImage_2 2077 +#define wxTreeCtrl_SetItemImage_3 2078 +#define wxTreeCtrl_SetItemText 2079 +#define wxTreeCtrl_SetItemTextColour 2080 +#define wxTreeCtrl_SetStateImageList 2081 +#define wxTreeCtrl_SetWindowStyle 2082 +#define wxTreeCtrl_SortChildren 2083 +#define wxTreeCtrl_Toggle 2084 +#define wxTreeCtrl_ToggleItemSelection 2085 +#define wxTreeCtrl_Unselect 2086 +#define wxTreeCtrl_UnselectAll 2087 +#define wxTreeCtrl_UnselectItem 2088 +#define wxScrollBar_new_0 2089 +#define wxScrollBar_new_3 2090 +#define wxScrollBar_destruct 2091 +#define wxScrollBar_Create 2092 +#define wxScrollBar_GetRange 2093 +#define wxScrollBar_GetPageSize 2094 +#define wxScrollBar_GetThumbPosition 2095 +#define wxScrollBar_GetThumbSize 2096 +#define wxScrollBar_SetThumbPosition 2097 +#define wxScrollBar_SetScrollbar 2098 +#define wxSpinButton_new_2 2100 +#define wxSpinButton_new_0 2101 +#define wxSpinButton_Create 2102 +#define wxSpinButton_GetMax 2103 +#define wxSpinButton_GetMin 2104 +#define wxSpinButton_GetValue 2105 +#define wxSpinButton_SetRange 2106 +#define wxSpinButton_SetValue 2107 +#define wxSpinButton_destroy 2108 +#define wxSpinCtrl_new_0 2109 +#define wxSpinCtrl_new_2 2110 +#define wxSpinCtrl_Create 2112 +#define wxSpinCtrl_SetValue_1_1 2115 +#define wxSpinCtrl_SetValue_1_0 2116 +#define wxSpinCtrl_GetValue 2118 +#define wxSpinCtrl_SetRange 2120 +#define wxSpinCtrl_SetSelection 2121 +#define wxSpinCtrl_GetMin 2123 +#define wxSpinCtrl_GetMax 2125 +#define wxSpinCtrl_destroy 2126 +#define wxStaticText_new_0 2127 +#define wxStaticText_new_4 2128 +#define wxStaticText_Create 2129 +#define wxStaticText_GetLabel 2130 +#define wxStaticText_SetLabel 2131 +#define wxStaticText_Wrap 2132 +#define wxStaticText_destroy 2133 +#define wxStaticBitmap_new_0 2134 +#define wxStaticBitmap_new_4 2135 +#define wxStaticBitmap_Create 2136 +#define wxStaticBitmap_GetBitmap 2137 +#define wxStaticBitmap_SetBitmap 2138 +#define wxStaticBitmap_destroy 2139 +#define wxRadioBox_new 2140 +#define wxRadioBox_destruct 2142 +#define wxRadioBox_Create 2143 +#define wxRadioBox_Enable_2 2144 +#define wxRadioBox_Enable_1 2145 +#define wxRadioBox_GetSelection 2146 +#define wxRadioBox_GetString 2147 +#define wxRadioBox_SetSelection 2148 +#define wxRadioBox_Show_2 2149 +#define wxRadioBox_Show_1 2150 +#define wxRadioBox_GetColumnCount 2151 +#define wxRadioBox_GetItemHelpText 2152 +#define wxRadioBox_GetItemToolTip 2153 +#define wxRadioBox_GetItemFromPoint 2155 +#define wxRadioBox_GetRowCount 2156 +#define wxRadioBox_IsItemEnabled 2157 +#define wxRadioBox_IsItemShown 2158 +#define wxRadioBox_SetItemHelpText 2159 +#define wxRadioBox_SetItemToolTip 2160 +#define wxRadioButton_new_0 2161 +#define wxRadioButton_new_4 2162 +#define wxRadioButton_Create 2163 +#define wxRadioButton_GetValue 2164 +#define wxRadioButton_SetValue 2165 +#define wxRadioButton_destroy 2166 +#define wxSlider_new_6 2168 +#define wxSlider_new_0 2169 +#define wxSlider_Create 2170 +#define wxSlider_GetLineSize 2171 +#define wxSlider_GetMax 2172 +#define wxSlider_GetMin 2173 +#define wxSlider_GetPageSize 2174 +#define wxSlider_GetThumbLength 2175 +#define wxSlider_GetValue 2176 +#define wxSlider_SetLineSize 2177 +#define wxSlider_SetPageSize 2178 +#define wxSlider_SetRange 2179 +#define wxSlider_SetThumbLength 2180 +#define wxSlider_SetValue 2181 +#define wxSlider_destroy 2182 +#define wxDialog_new_4 2184 +#define wxDialog_new_0 2185 +#define wxDialog_destruct 2187 +#define wxDialog_Create 2188 +#define wxDialog_CreateButtonSizer 2189 +#define wxDialog_CreateStdDialogButtonSizer 2190 +#define wxDialog_EndModal 2191 +#define wxDialog_GetAffirmativeId 2192 +#define wxDialog_GetReturnCode 2193 +#define wxDialog_IsModal 2194 +#define wxDialog_SetAffirmativeId 2195 +#define wxDialog_SetReturnCode 2196 +#define wxDialog_Show 2197 +#define wxDialog_ShowModal 2198 +#define wxColourDialog_new_0 2199 +#define wxColourDialog_new_2 2200 +#define wxColourDialog_destruct 2201 +#define wxColourDialog_Create 2202 +#define wxColourDialog_GetColourData 2203 +#define wxColourData_new_0 2204 +#define wxColourData_new_1 2205 +#define wxColourData_destruct 2206 +#define wxColourData_GetChooseFull 2207 +#define wxColourData_GetColour 2208 +#define wxColourData_GetCustomColour 2210 +#define wxColourData_SetChooseFull 2211 +#define wxColourData_SetColour 2212 +#define wxColourData_SetCustomColour 2213 +#define wxPalette_new_0 2214 +#define wxPalette_new_4 2215 +#define wxPalette_destruct 2217 +#define wxPalette_Create 2218 +#define wxPalette_GetColoursCount 2219 +#define wxPalette_GetPixel 2220 +#define wxPalette_GetRGB 2221 +#define wxPalette_IsOk 2222 +#define wxDirDialog_new 2226 +#define wxDirDialog_destruct 2227 +#define wxDirDialog_GetPath 2228 +#define wxDirDialog_GetMessage 2229 +#define wxDirDialog_SetMessage 2230 +#define wxDirDialog_SetPath 2231 +#define wxFileDialog_new 2235 +#define wxFileDialog_destruct 2236 +#define wxFileDialog_GetDirectory 2237 +#define wxFileDialog_GetFilename 2238 +#define wxFileDialog_GetFilenames 2239 +#define wxFileDialog_GetFilterIndex 2240 +#define wxFileDialog_GetMessage 2241 +#define wxFileDialog_GetPath 2242 +#define wxFileDialog_GetPaths 2243 +#define wxFileDialog_GetWildcard 2244 +#define wxFileDialog_SetDirectory 2245 +#define wxFileDialog_SetFilename 2246 +#define wxFileDialog_SetFilterIndex 2247 +#define wxFileDialog_SetMessage 2248 +#define wxFileDialog_SetPath 2249 +#define wxFileDialog_SetWildcard 2250 +#define wxPickerBase_SetInternalMargin 2251 +#define wxPickerBase_GetInternalMargin 2252 +#define wxPickerBase_SetTextCtrlProportion 2253 +#define wxPickerBase_SetPickerCtrlProportion 2254 +#define wxPickerBase_GetTextCtrlProportion 2255 +#define wxPickerBase_GetPickerCtrlProportion 2256 +#define wxPickerBase_HasTextCtrl 2257 +#define wxPickerBase_GetTextCtrl 2258 +#define wxPickerBase_IsTextCtrlGrowable 2259 +#define wxPickerBase_SetPickerCtrlGrowable 2260 +#define wxPickerBase_SetTextCtrlGrowable 2261 +#define wxPickerBase_IsPickerCtrlGrowable 2262 +#define wxFilePickerCtrl_new_0 2263 +#define wxFilePickerCtrl_new_3 2264 +#define wxFilePickerCtrl_Create 2265 +#define wxFilePickerCtrl_GetPath 2266 +#define wxFilePickerCtrl_SetPath 2267 +#define wxFilePickerCtrl_destroy 2268 +#define wxDirPickerCtrl_new_0 2269 +#define wxDirPickerCtrl_new_3 2270 +#define wxDirPickerCtrl_Create 2271 +#define wxDirPickerCtrl_GetPath 2272 +#define wxDirPickerCtrl_SetPath 2273 +#define wxDirPickerCtrl_destroy 2274 +#define wxColourPickerCtrl_new_0 2275 +#define wxColourPickerCtrl_new_3 2276 +#define wxColourPickerCtrl_Create 2277 +#define wxColourPickerCtrl_GetColour 2278 +#define wxColourPickerCtrl_SetColour_1_1 2279 +#define wxColourPickerCtrl_SetColour_1_0 2280 +#define wxColourPickerCtrl_destroy 2281 +#define wxDatePickerCtrl_new_0 2282 +#define wxDatePickerCtrl_new_3 2283 +#define wxDatePickerCtrl_GetRange 2284 +#define wxDatePickerCtrl_GetValue 2285 +#define wxDatePickerCtrl_SetRange 2286 +#define wxDatePickerCtrl_SetValue 2287 +#define wxDatePickerCtrl_destroy 2288 +#define wxFontPickerCtrl_new_0 2289 +#define wxFontPickerCtrl_new_3 2290 +#define wxFontPickerCtrl_Create 2291 +#define wxFontPickerCtrl_GetSelectedFont 2292 +#define wxFontPickerCtrl_SetSelectedFont 2293 +#define wxFontPickerCtrl_GetMaxPointSize 2294 +#define wxFontPickerCtrl_SetMaxPointSize 2295 +#define wxFontPickerCtrl_destroy 2296 +#define wxFindReplaceDialog_new_0 2299 +#define wxFindReplaceDialog_new_4 2300 +#define wxFindReplaceDialog_destruct 2301 +#define wxFindReplaceDialog_Create 2302 +#define wxFindReplaceDialog_GetData 2303 +#define wxFindReplaceData_new_0 2304 +#define wxFindReplaceData_new_1 2305 +#define wxFindReplaceData_GetFindString 2306 +#define wxFindReplaceData_GetReplaceString 2307 +#define wxFindReplaceData_GetFlags 2308 +#define wxFindReplaceData_SetFlags 2309 +#define wxFindReplaceData_SetFindString 2310 +#define wxFindReplaceData_SetReplaceString 2311 +#define wxFindReplaceData_destroy 2312 +#define wxMultiChoiceDialog_new_0 2313 +#define wxMultiChoiceDialog_new_5 2315 +#define wxMultiChoiceDialog_GetSelections 2316 +#define wxMultiChoiceDialog_SetSelections 2317 +#define wxMultiChoiceDialog_destroy 2318 +#define wxSingleChoiceDialog_new_0 2319 +#define wxSingleChoiceDialog_new_5 2321 +#define wxSingleChoiceDialog_GetSelection 2322 +#define wxSingleChoiceDialog_GetStringSelection 2323 +#define wxSingleChoiceDialog_SetSelection 2324 +#define wxSingleChoiceDialog_destroy 2325 +#define wxTextEntryDialog_new 2326 +#define wxTextEntryDialog_GetValue 2327 +#define wxTextEntryDialog_SetValue 2328 +#define wxTextEntryDialog_destroy 2329 +#define wxPasswordEntryDialog_new 2330 +#define wxPasswordEntryDialog_destroy 2331 +#define wxFontData_new_0 2332 +#define wxFontData_new_1 2333 +#define wxFontData_destruct 2334 +#define wxFontData_EnableEffects 2335 +#define wxFontData_GetAllowSymbols 2336 +#define wxFontData_GetColour 2337 +#define wxFontData_GetChosenFont 2338 +#define wxFontData_GetEnableEffects 2339 +#define wxFontData_GetInitialFont 2340 +#define wxFontData_GetShowHelp 2341 +#define wxFontData_SetAllowSymbols 2342 +#define wxFontData_SetChosenFont 2343 +#define wxFontData_SetColour 2344 +#define wxFontData_SetInitialFont 2345 +#define wxFontData_SetRange 2346 +#define wxFontData_SetShowHelp 2347 +#define wxFontDialog_new_0 2351 +#define wxFontDialog_new_2 2353 +#define wxFontDialog_Create 2355 +#define wxFontDialog_GetFontData 2356 +#define wxFontDialog_destroy 2358 +#define wxProgressDialog_new 2359 +#define wxProgressDialog_destruct 2360 +#define wxProgressDialog_Resume 2361 +#define wxProgressDialog_Update_2 2362 +#define wxProgressDialog_Update_0 2363 +#define wxMessageDialog_new 2364 +#define wxMessageDialog_destruct 2365 +#define wxPageSetupDialog_new 2366 +#define wxPageSetupDialog_destruct 2367 +#define wxPageSetupDialog_GetPageSetupData 2368 +#define wxPageSetupDialog_ShowModal 2369 +#define wxPageSetupDialogData_new_0 2370 +#define wxPageSetupDialogData_new_1_0 2371 +#define wxPageSetupDialogData_new_1_1 2372 +#define wxPageSetupDialogData_destruct 2373 +#define wxPageSetupDialogData_EnableHelp 2374 +#define wxPageSetupDialogData_EnableMargins 2375 +#define wxPageSetupDialogData_EnableOrientation 2376 +#define wxPageSetupDialogData_EnablePaper 2377 +#define wxPageSetupDialogData_EnablePrinter 2378 +#define wxPageSetupDialogData_GetDefaultMinMargins 2379 +#define wxPageSetupDialogData_GetEnableMargins 2380 +#define wxPageSetupDialogData_GetEnableOrientation 2381 +#define wxPageSetupDialogData_GetEnablePaper 2382 +#define wxPageSetupDialogData_GetEnablePrinter 2383 +#define wxPageSetupDialogData_GetEnableHelp 2384 +#define wxPageSetupDialogData_GetDefaultInfo 2385 +#define wxPageSetupDialogData_GetMarginTopLeft 2386 +#define wxPageSetupDialogData_GetMarginBottomRight 2387 +#define wxPageSetupDialogData_GetMinMarginTopLeft 2388 +#define wxPageSetupDialogData_GetMinMarginBottomRight 2389 +#define wxPageSetupDialogData_GetPaperId 2390 +#define wxPageSetupDialogData_GetPaperSize 2391 +#define wxPageSetupDialogData_GetPrintData 2393 +#define wxPageSetupDialogData_IsOk 2394 +#define wxPageSetupDialogData_SetDefaultInfo 2395 +#define wxPageSetupDialogData_SetDefaultMinMargins 2396 +#define wxPageSetupDialogData_SetMarginTopLeft 2397 +#define wxPageSetupDialogData_SetMarginBottomRight 2398 +#define wxPageSetupDialogData_SetMinMarginTopLeft 2399 +#define wxPageSetupDialogData_SetMinMarginBottomRight 2400 +#define wxPageSetupDialogData_SetPaperId 2401 +#define wxPageSetupDialogData_SetPaperSize_1_1 2402 +#define wxPageSetupDialogData_SetPaperSize_1_0 2403 +#define wxPageSetupDialogData_SetPrintData 2404 +#define wxPrintDialog_new_2_0 2405 +#define wxPrintDialog_new_2_1 2406 +#define wxPrintDialog_destruct 2407 +#define wxPrintDialog_GetPrintDialogData 2408 +#define wxPrintDialog_GetPrintDC 2409 +#define wxPrintDialogData_new_0 2410 +#define wxPrintDialogData_new_1_1 2411 +#define wxPrintDialogData_new_1_0 2412 +#define wxPrintDialogData_destruct 2413 +#define wxPrintDialogData_EnableHelp 2414 +#define wxPrintDialogData_EnablePageNumbers 2415 +#define wxPrintDialogData_EnablePrintToFile 2416 +#define wxPrintDialogData_EnableSelection 2417 +#define wxPrintDialogData_GetAllPages 2418 +#define wxPrintDialogData_GetCollate 2419 +#define wxPrintDialogData_GetFromPage 2420 +#define wxPrintDialogData_GetMaxPage 2421 +#define wxPrintDialogData_GetMinPage 2422 +#define wxPrintDialogData_GetNoCopies 2423 +#define wxPrintDialogData_GetPrintData 2424 +#define wxPrintDialogData_GetPrintToFile 2425 +#define wxPrintDialogData_GetSelection 2426 +#define wxPrintDialogData_GetToPage 2427 +#define wxPrintDialogData_IsOk 2428 +#define wxPrintDialogData_SetCollate 2429 +#define wxPrintDialogData_SetFromPage 2430 +#define wxPrintDialogData_SetMaxPage 2431 +#define wxPrintDialogData_SetMinPage 2432 +#define wxPrintDialogData_SetNoCopies 2433 +#define wxPrintDialogData_SetPrintData 2434 +#define wxPrintDialogData_SetPrintToFile 2435 +#define wxPrintDialogData_SetSelection 2436 +#define wxPrintDialogData_SetToPage 2437 +#define wxPrintData_new_0 2438 +#define wxPrintData_new_1 2439 +#define wxPrintData_destruct 2440 +#define wxPrintData_GetCollate 2441 +#define wxPrintData_GetBin 2442 +#define wxPrintData_GetColour 2443 +#define wxPrintData_GetDuplex 2444 +#define wxPrintData_GetNoCopies 2445 +#define wxPrintData_GetOrientation 2446 +#define wxPrintData_GetPaperId 2447 +#define wxPrintData_GetPrinterName 2448 +#define wxPrintData_GetQuality 2449 +#define wxPrintData_IsOk 2450 +#define wxPrintData_SetBin 2451 +#define wxPrintData_SetCollate 2452 +#define wxPrintData_SetColour 2453 +#define wxPrintData_SetDuplex 2454 +#define wxPrintData_SetNoCopies 2455 +#define wxPrintData_SetOrientation 2456 +#define wxPrintData_SetPaperId 2457 +#define wxPrintData_SetPrinterName 2458 +#define wxPrintData_SetQuality 2459 +#define wxPrintPreview_new_2 2462 +#define wxPrintPreview_new_3 2463 +#define wxPrintPreview_destruct 2465 +#define wxPrintPreview_GetCanvas 2466 +#define wxPrintPreview_GetCurrentPage 2467 +#define wxPrintPreview_GetFrame 2468 +#define wxPrintPreview_GetMaxPage 2469 +#define wxPrintPreview_GetMinPage 2470 +#define wxPrintPreview_GetPrintout 2471 +#define wxPrintPreview_GetPrintoutForPrinting 2472 +#define wxPrintPreview_IsOk 2473 +#define wxPrintPreview_PaintPage 2474 +#define wxPrintPreview_Print 2475 +#define wxPrintPreview_RenderPage 2476 +#define wxPrintPreview_SetCanvas 2477 +#define wxPrintPreview_SetCurrentPage 2478 +#define wxPrintPreview_SetFrame 2479 +#define wxPrintPreview_SetPrintout 2480 +#define wxPrintPreview_SetZoom 2481 +#define wxPreviewFrame_new 2482 +#define wxPreviewFrame_destruct 2483 +#define wxPreviewFrame_CreateControlBar 2484 +#define wxPreviewFrame_CreateCanvas 2485 +#define wxPreviewFrame_Initialize 2486 +#define wxPreviewFrame_OnCloseWindow 2487 +#define wxPreviewControlBar_new 2488 +#define wxPreviewControlBar_destruct 2489 +#define wxPreviewControlBar_CreateButtons 2490 +#define wxPreviewControlBar_GetPrintPreview 2491 +#define wxPreviewControlBar_GetZoomControl 2492 +#define wxPreviewControlBar_SetZoomControl 2493 +#define wxPrinter_new 2495 +#define wxPrinter_CreateAbortWindow 2496 +#define wxPrinter_GetAbort 2497 +#define wxPrinter_GetLastError 2498 +#define wxPrinter_GetPrintDialogData 2499 +#define wxPrinter_Print 2500 +#define wxPrinter_PrintDialog 2501 +#define wxPrinter_ReportError 2502 +#define wxPrinter_Setup 2503 +#define wxPrinter_destroy 2504 +#define wxXmlResource_new_1 2505 +#define wxXmlResource_new_2 2506 +#define wxXmlResource_destruct 2507 +#define wxXmlResource_AttachUnknownControl 2508 +#define wxXmlResource_ClearHandlers 2509 +#define wxXmlResource_CompareVersion 2510 +#define wxXmlResource_Get 2511 +#define wxXmlResource_GetFlags 2512 +#define wxXmlResource_GetVersion 2513 +#define wxXmlResource_GetXRCID 2514 +#define wxXmlResource_InitAllHandlers 2515 +#define wxXmlResource_Load 2516 +#define wxXmlResource_LoadBitmap 2517 +#define wxXmlResource_LoadDialog_2 2518 +#define wxXmlResource_LoadDialog_3 2519 +#define wxXmlResource_LoadFrame_2 2520 +#define wxXmlResource_LoadFrame_3 2521 +#define wxXmlResource_LoadIcon 2522 +#define wxXmlResource_LoadMenu 2523 +#define wxXmlResource_LoadMenuBar_2 2524 +#define wxXmlResource_LoadMenuBar_1 2525 +#define wxXmlResource_LoadPanel_2 2526 +#define wxXmlResource_LoadPanel_3 2527 +#define wxXmlResource_LoadToolBar 2528 +#define wxXmlResource_Set 2529 +#define wxXmlResource_SetFlags 2530 +#define wxXmlResource_Unload 2531 +#define wxXmlResource_xrcctrl 2532 +#define wxHtmlEasyPrinting_new 2533 +#define wxHtmlEasyPrinting_destruct 2534 +#define wxHtmlEasyPrinting_GetPrintData 2535 +#define wxHtmlEasyPrinting_GetPageSetupData 2536 +#define wxHtmlEasyPrinting_PreviewFile 2537 +#define wxHtmlEasyPrinting_PreviewText 2538 +#define wxHtmlEasyPrinting_PrintFile 2539 +#define wxHtmlEasyPrinting_PrintText 2540 +#define wxHtmlEasyPrinting_PageSetup 2541 +#define wxHtmlEasyPrinting_SetFonts 2542 +#define wxHtmlEasyPrinting_SetHeader 2543 +#define wxHtmlEasyPrinting_SetFooter 2544 +#define wxGLCanvas_new_2 2546 +#define wxGLCanvas_new_3_1 2547 +#define wxGLCanvas_new_3_0 2548 +#define wxGLCanvas_GetContext 2549 +#define wxGLCanvas_SetCurrent 2551 +#define wxGLCanvas_SwapBuffers 2552 +#define wxGLCanvas_destroy 2553 +#define wxAuiManager_new 2554 +#define wxAuiManager_destruct 2555 +#define wxAuiManager_AddPane_2_1 2556 +#define wxAuiManager_AddPane_3 2557 +#define wxAuiManager_AddPane_2_0 2558 +#define wxAuiManager_DetachPane 2559 +#define wxAuiManager_GetAllPanes 2560 +#define wxAuiManager_GetArtProvider 2561 +#define wxAuiManager_GetDockSizeConstraint 2562 +#define wxAuiManager_GetFlags 2563 +#define wxAuiManager_GetManagedWindow 2564 +#define wxAuiManager_GetManager 2565 +#define wxAuiManager_GetPane_1_1 2566 +#define wxAuiManager_GetPane_1_0 2567 +#define wxAuiManager_HideHint 2568 +#define wxAuiManager_InsertPane 2569 +#define wxAuiManager_LoadPaneInfo 2570 +#define wxAuiManager_LoadPerspective 2571 +#define wxAuiManager_SavePaneInfo 2572 +#define wxAuiManager_SavePerspective 2573 +#define wxAuiManager_SetArtProvider 2574 +#define wxAuiManager_SetDockSizeConstraint 2575 +#define wxAuiManager_SetFlags 2576 +#define wxAuiManager_SetManagedWindow 2577 +#define wxAuiManager_ShowHint 2578 +#define wxAuiManager_UnInit 2579 +#define wxAuiManager_Update 2580 +#define wxAuiPaneInfo_new_0 2581 +#define wxAuiPaneInfo_new_1 2582 +#define wxAuiPaneInfo_destruct 2583 +#define wxAuiPaneInfo_BestSize_1 2584 +#define wxAuiPaneInfo_BestSize_2 2585 +#define wxAuiPaneInfo_Bottom 2586 +#define wxAuiPaneInfo_BottomDockable 2587 +#define wxAuiPaneInfo_Caption 2588 +#define wxAuiPaneInfo_CaptionVisible 2589 +#define wxAuiPaneInfo_Centre 2590 +#define wxAuiPaneInfo_CentrePane 2591 +#define wxAuiPaneInfo_CloseButton 2592 +#define wxAuiPaneInfo_DefaultPane 2593 +#define wxAuiPaneInfo_DestroyOnClose 2594 +#define wxAuiPaneInfo_Direction 2595 +#define wxAuiPaneInfo_Dock 2596 +#define wxAuiPaneInfo_Dockable 2597 +#define wxAuiPaneInfo_Fixed 2598 +#define wxAuiPaneInfo_Float 2599 +#define wxAuiPaneInfo_Floatable 2600 +#define wxAuiPaneInfo_FloatingPosition_1 2601 +#define wxAuiPaneInfo_FloatingPosition_2 2602 +#define wxAuiPaneInfo_FloatingSize_1 2603 +#define wxAuiPaneInfo_FloatingSize_2 2604 +#define wxAuiPaneInfo_Gripper 2605 +#define wxAuiPaneInfo_GripperTop 2606 +#define wxAuiPaneInfo_HasBorder 2607 +#define wxAuiPaneInfo_HasCaption 2608 +#define wxAuiPaneInfo_HasCloseButton 2609 +#define wxAuiPaneInfo_HasFlag 2610 +#define wxAuiPaneInfo_HasGripper 2611 +#define wxAuiPaneInfo_HasGripperTop 2612 +#define wxAuiPaneInfo_HasMaximizeButton 2613 +#define wxAuiPaneInfo_HasMinimizeButton 2614 +#define wxAuiPaneInfo_HasPinButton 2615 +#define wxAuiPaneInfo_Hide 2616 +#define wxAuiPaneInfo_IsBottomDockable 2617 +#define wxAuiPaneInfo_IsDocked 2618 +#define wxAuiPaneInfo_IsFixed 2619 +#define wxAuiPaneInfo_IsFloatable 2620 +#define wxAuiPaneInfo_IsFloating 2621 +#define wxAuiPaneInfo_IsLeftDockable 2622 +#define wxAuiPaneInfo_IsMovable 2623 +#define wxAuiPaneInfo_IsOk 2624 +#define wxAuiPaneInfo_IsResizable 2625 +#define wxAuiPaneInfo_IsRightDockable 2626 +#define wxAuiPaneInfo_IsShown 2627 +#define wxAuiPaneInfo_IsToolbar 2628 +#define wxAuiPaneInfo_IsTopDockable 2629 +#define wxAuiPaneInfo_Layer 2630 +#define wxAuiPaneInfo_Left 2631 +#define wxAuiPaneInfo_LeftDockable 2632 +#define wxAuiPaneInfo_MaxSize_1 2633 +#define wxAuiPaneInfo_MaxSize_2 2634 +#define wxAuiPaneInfo_MaximizeButton 2635 +#define wxAuiPaneInfo_MinSize_1 2636 +#define wxAuiPaneInfo_MinSize_2 2637 +#define wxAuiPaneInfo_MinimizeButton 2638 +#define wxAuiPaneInfo_Movable 2639 +#define wxAuiPaneInfo_Name 2640 +#define wxAuiPaneInfo_PaneBorder 2641 +#define wxAuiPaneInfo_PinButton 2642 +#define wxAuiPaneInfo_Position 2643 +#define wxAuiPaneInfo_Resizable 2644 +#define wxAuiPaneInfo_Right 2645 +#define wxAuiPaneInfo_RightDockable 2646 +#define wxAuiPaneInfo_Row 2647 +#define wxAuiPaneInfo_SafeSet 2648 +#define wxAuiPaneInfo_SetFlag 2649 +#define wxAuiPaneInfo_Show 2650 +#define wxAuiPaneInfo_ToolbarPane 2651 +#define wxAuiPaneInfo_Top 2652 +#define wxAuiPaneInfo_TopDockable 2653 +#define wxAuiPaneInfo_Window 2654 +#define wxAuiPaneInfo_GetWindow 2655 +#define wxAuiPaneInfo_GetFrame 2656 +#define wxAuiPaneInfo_GetDirection 2657 +#define wxAuiPaneInfo_GetLayer 2658 +#define wxAuiPaneInfo_GetRow 2659 +#define wxAuiPaneInfo_GetPosition 2660 +#define wxAuiPaneInfo_GetFloatingPosition 2661 +#define wxAuiPaneInfo_GetFloatingSize 2662 +#define wxAuiNotebook_new_0 2663 +#define wxAuiNotebook_new_2 2664 +#define wxAuiNotebook_AddPage 2665 +#define wxAuiNotebook_Create 2666 +#define wxAuiNotebook_DeletePage 2667 +#define wxAuiNotebook_GetArtProvider 2668 +#define wxAuiNotebook_GetPage 2669 +#define wxAuiNotebook_GetPageBitmap 2670 +#define wxAuiNotebook_GetPageCount 2671 +#define wxAuiNotebook_GetPageIndex 2672 +#define wxAuiNotebook_GetPageText 2673 +#define wxAuiNotebook_GetSelection 2674 +#define wxAuiNotebook_InsertPage 2675 +#define wxAuiNotebook_RemovePage 2676 +#define wxAuiNotebook_SetArtProvider 2677 +#define wxAuiNotebook_SetFont 2678 +#define wxAuiNotebook_SetPageBitmap 2679 +#define wxAuiNotebook_SetPageText 2680 +#define wxAuiNotebook_SetSelection 2681 +#define wxAuiNotebook_SetTabCtrlHeight 2682 +#define wxAuiNotebook_SetUniformBitmapSize 2683 +#define wxAuiNotebook_destroy 2684 +#define wxAuiTabArt_SetFlags 2685 +#define wxAuiTabArt_SetMeasuringFont 2686 +#define wxAuiTabArt_SetNormalFont 2687 +#define wxAuiTabArt_SetSelectedFont 2688 +#define wxAuiTabArt_SetColour 2689 +#define wxAuiTabArt_SetActiveColour 2690 +#define wxAuiDockArt_GetColour 2691 +#define wxAuiDockArt_GetFont 2692 +#define wxAuiDockArt_GetMetric 2693 +#define wxAuiDockArt_SetColour 2694 +#define wxAuiDockArt_SetFont 2695 +#define wxAuiDockArt_SetMetric 2696 +#define wxAuiSimpleTabArt_new 2697 +#define wxAuiSimpleTabArt_destroy 2698 +#define wxMDIParentFrame_new_0 2699 +#define wxMDIParentFrame_new_4 2700 +#define wxMDIParentFrame_destruct 2701 +#define wxMDIParentFrame_ActivateNext 2702 +#define wxMDIParentFrame_ActivatePrevious 2703 +#define wxMDIParentFrame_ArrangeIcons 2704 +#define wxMDIParentFrame_Cascade 2705 +#define wxMDIParentFrame_Create 2706 +#define wxMDIParentFrame_GetActiveChild 2707 +#define wxMDIParentFrame_GetClientWindow 2708 +#define wxMDIParentFrame_Tile 2709 +#define wxMDIChildFrame_new_0 2710 +#define wxMDIChildFrame_new_4 2711 +#define wxMDIChildFrame_destruct 2712 +#define wxMDIChildFrame_Activate 2713 +#define wxMDIChildFrame_Create 2714 +#define wxMDIChildFrame_Maximize 2715 +#define wxMDIChildFrame_Restore 2716 +#define wxMDIClientWindow_new_0 2717 +#define wxMDIClientWindow_new_2 2718 +#define wxMDIClientWindow_destruct 2719 +#define wxMDIClientWindow_CreateClient 2720 +#define wxLayoutAlgorithm_new 2721 +#define wxLayoutAlgorithm_LayoutFrame 2722 +#define wxLayoutAlgorithm_LayoutMDIFrame 2723 +#define wxLayoutAlgorithm_LayoutWindow 2724 +#define wxLayoutAlgorithm_destroy 2725 +#define wxEvent_GetId 2726 +#define wxEvent_GetSkipped 2727 +#define wxEvent_GetTimestamp 2728 +#define wxEvent_IsCommandEvent 2729 +#define wxEvent_ResumePropagation 2730 +#define wxEvent_ShouldPropagate 2731 +#define wxEvent_Skip 2732 +#define wxEvent_StopPropagation 2733 +#define wxCommandEvent_getClientData 2734 +#define wxCommandEvent_GetExtraLong 2735 +#define wxCommandEvent_GetInt 2736 +#define wxCommandEvent_GetSelection 2737 +#define wxCommandEvent_GetString 2738 +#define wxCommandEvent_IsChecked 2739 +#define wxCommandEvent_IsSelection 2740 +#define wxCommandEvent_SetInt 2741 +#define wxCommandEvent_SetString 2742 +#define wxScrollEvent_GetOrientation 2743 +#define wxScrollEvent_GetPosition 2744 +#define wxScrollWinEvent_GetOrientation 2745 +#define wxScrollWinEvent_GetPosition 2746 +#define wxMouseEvent_AltDown 2747 +#define wxMouseEvent_Button 2748 +#define wxMouseEvent_ButtonDClick 2749 +#define wxMouseEvent_ButtonDown 2750 +#define wxMouseEvent_ButtonUp 2751 +#define wxMouseEvent_CmdDown 2752 +#define wxMouseEvent_ControlDown 2753 +#define wxMouseEvent_Dragging 2754 +#define wxMouseEvent_Entering 2755 +#define wxMouseEvent_GetButton 2756 +#define wxMouseEvent_GetPosition 2759 +#define wxMouseEvent_GetLogicalPosition 2760 +#define wxMouseEvent_GetLinesPerAction 2761 +#define wxMouseEvent_GetWheelRotation 2762 +#define wxMouseEvent_GetWheelDelta 2763 +#define wxMouseEvent_GetX 2764 +#define wxMouseEvent_GetY 2765 +#define wxMouseEvent_IsButton 2766 +#define wxMouseEvent_IsPageScroll 2767 +#define wxMouseEvent_Leaving 2768 +#define wxMouseEvent_LeftDClick 2769 +#define wxMouseEvent_LeftDown 2770 +#define wxMouseEvent_LeftIsDown 2771 +#define wxMouseEvent_LeftUp 2772 +#define wxMouseEvent_MetaDown 2773 +#define wxMouseEvent_MiddleDClick 2774 +#define wxMouseEvent_MiddleDown 2775 +#define wxMouseEvent_MiddleIsDown 2776 +#define wxMouseEvent_MiddleUp 2777 +#define wxMouseEvent_Moving 2778 +#define wxMouseEvent_RightDClick 2779 +#define wxMouseEvent_RightDown 2780 +#define wxMouseEvent_RightIsDown 2781 +#define wxMouseEvent_RightUp 2782 +#define wxMouseEvent_ShiftDown 2783 +#define wxSetCursorEvent_GetCursor 2784 +#define wxSetCursorEvent_GetX 2785 +#define wxSetCursorEvent_GetY 2786 +#define wxSetCursorEvent_HasCursor 2787 +#define wxSetCursorEvent_SetCursor 2788 +#define wxKeyEvent_AltDown 2789 +#define wxKeyEvent_CmdDown 2790 +#define wxKeyEvent_ControlDown 2791 +#define wxKeyEvent_GetKeyCode 2792 +#define wxKeyEvent_GetModifiers 2793 +#define wxKeyEvent_GetPosition 2796 +#define wxKeyEvent_GetRawKeyCode 2797 +#define wxKeyEvent_GetRawKeyFlags 2798 +#define wxKeyEvent_GetUnicodeKey 2799 +#define wxKeyEvent_GetX 2800 +#define wxKeyEvent_GetY 2801 +#define wxKeyEvent_HasModifiers 2802 +#define wxKeyEvent_MetaDown 2803 +#define wxKeyEvent_ShiftDown 2804 +#define wxSizeEvent_GetSize 2805 +#define wxMoveEvent_GetPosition 2806 +#define wxEraseEvent_GetDC 2807 +#define wxFocusEvent_GetWindow 2808 +#define wxChildFocusEvent_GetWindow 2809 +#define wxMenuEvent_GetMenu 2810 +#define wxMenuEvent_GetMenuId 2811 +#define wxMenuEvent_IsPopup 2812 +#define wxCloseEvent_CanVeto 2813 +#define wxCloseEvent_GetLoggingOff 2814 +#define wxCloseEvent_SetCanVeto 2815 +#define wxCloseEvent_SetLoggingOff 2816 +#define wxCloseEvent_Veto 2817 +#define wxShowEvent_SetShow 2818 +#define wxShowEvent_GetShow 2819 +#define wxIconizeEvent_Iconized 2820 +#define wxJoystickEvent_ButtonDown 2821 +#define wxJoystickEvent_ButtonIsDown 2822 +#define wxJoystickEvent_ButtonUp 2823 +#define wxJoystickEvent_GetButtonChange 2824 +#define wxJoystickEvent_GetButtonState 2825 +#define wxJoystickEvent_GetJoystick 2826 +#define wxJoystickEvent_GetPosition 2827 +#define wxJoystickEvent_GetZPosition 2828 +#define wxJoystickEvent_IsButton 2829 +#define wxJoystickEvent_IsMove 2830 +#define wxJoystickEvent_IsZMove 2831 +#define wxUpdateUIEvent_CanUpdate 2832 +#define wxUpdateUIEvent_Check 2833 +#define wxUpdateUIEvent_Enable 2834 +#define wxUpdateUIEvent_Show 2835 +#define wxUpdateUIEvent_GetChecked 2836 +#define wxUpdateUIEvent_GetEnabled 2837 +#define wxUpdateUIEvent_GetShown 2838 +#define wxUpdateUIEvent_GetSetChecked 2839 +#define wxUpdateUIEvent_GetSetEnabled 2840 +#define wxUpdateUIEvent_GetSetShown 2841 +#define wxUpdateUIEvent_GetSetText 2842 +#define wxUpdateUIEvent_GetText 2843 +#define wxUpdateUIEvent_GetMode 2844 +#define wxUpdateUIEvent_GetUpdateInterval 2845 +#define wxUpdateUIEvent_ResetUpdateTime 2846 +#define wxUpdateUIEvent_SetMode 2847 +#define wxUpdateUIEvent_SetText 2848 +#define wxUpdateUIEvent_SetUpdateInterval 2849 +#define wxMouseCaptureChangedEvent_GetCapturedWindow 2850 +#define wxPaletteChangedEvent_SetChangedWindow 2851 +#define wxPaletteChangedEvent_GetChangedWindow 2852 +#define wxQueryNewPaletteEvent_SetPaletteRealized 2853 +#define wxQueryNewPaletteEvent_GetPaletteRealized 2854 +#define wxNavigationKeyEvent_GetDirection 2855 +#define wxNavigationKeyEvent_SetDirection 2856 +#define wxNavigationKeyEvent_IsWindowChange 2857 +#define wxNavigationKeyEvent_SetWindowChange 2858 +#define wxNavigationKeyEvent_IsFromTab 2859 +#define wxNavigationKeyEvent_SetFromTab 2860 +#define wxNavigationKeyEvent_GetCurrentFocus 2861 +#define wxNavigationKeyEvent_SetCurrentFocus 2862 +#define wxHelpEvent_GetOrigin 2863 +#define wxHelpEvent_GetPosition 2864 +#define wxHelpEvent_SetOrigin 2865 +#define wxHelpEvent_SetPosition 2866 +#define wxContextMenuEvent_GetPosition 2867 +#define wxContextMenuEvent_SetPosition 2868 +#define wxIdleEvent_CanSend 2869 +#define wxIdleEvent_GetMode 2870 +#define wxIdleEvent_RequestMore 2871 +#define wxIdleEvent_MoreRequested 2872 +#define wxIdleEvent_SetMode 2873 +#define wxGridEvent_AltDown 2874 +#define wxGridEvent_ControlDown 2875 +#define wxGridEvent_GetCol 2876 +#define wxGridEvent_GetPosition 2877 +#define wxGridEvent_GetRow 2878 +#define wxGridEvent_MetaDown 2879 +#define wxGridEvent_Selecting 2880 +#define wxGridEvent_ShiftDown 2881 +#define wxNotifyEvent_Allow 2882 +#define wxNotifyEvent_IsAllowed 2883 +#define wxNotifyEvent_Veto 2884 +#define wxSashEvent_GetEdge 2885 +#define wxSashEvent_GetDragRect 2886 +#define wxSashEvent_GetDragStatus 2887 +#define wxListEvent_GetCacheFrom 2888 +#define wxListEvent_GetCacheTo 2889 +#define wxListEvent_GetKeyCode 2890 +#define wxListEvent_GetIndex 2891 +#define wxListEvent_GetColumn 2892 +#define wxListEvent_GetPoint 2893 +#define wxListEvent_GetLabel 2894 +#define wxListEvent_GetText 2895 +#define wxListEvent_GetImage 2896 +#define wxListEvent_GetData 2897 +#define wxListEvent_GetMask 2898 +#define wxListEvent_GetItem 2899 +#define wxListEvent_IsEditCancelled 2900 +#define wxDateEvent_GetDate 2901 +#define wxCalendarEvent_GetWeekDay 2902 +#define wxFileDirPickerEvent_GetPath 2903 +#define wxColourPickerEvent_GetColour 2904 +#define wxFontPickerEvent_GetFont 2905 +#define wxStyledTextEvent_GetPosition 2906 +#define wxStyledTextEvent_GetKey 2907 +#define wxStyledTextEvent_GetModifiers 2908 +#define wxStyledTextEvent_GetModificationType 2909 +#define wxStyledTextEvent_GetText 2910 +#define wxStyledTextEvent_GetLength 2911 +#define wxStyledTextEvent_GetLinesAdded 2912 +#define wxStyledTextEvent_GetLine 2913 +#define wxStyledTextEvent_GetFoldLevelNow 2914 +#define wxStyledTextEvent_GetFoldLevelPrev 2915 +#define wxStyledTextEvent_GetMargin 2916 +#define wxStyledTextEvent_GetMessage 2917 +#define wxStyledTextEvent_GetWParam 2918 +#define wxStyledTextEvent_GetLParam 2919 +#define wxStyledTextEvent_GetListType 2920 +#define wxStyledTextEvent_GetX 2921 +#define wxStyledTextEvent_GetY 2922 +#define wxStyledTextEvent_GetDragText 2923 +#define wxStyledTextEvent_GetDragAllowMove 2924 +#define wxStyledTextEvent_GetDragResult 2925 +#define wxStyledTextEvent_GetShift 2926 +#define wxStyledTextEvent_GetControl 2927 +#define wxStyledTextEvent_GetAlt 2928 +#define utils_wxGetKeyState 2929 +#define utils_wxGetMousePosition 2930 +#define utils_wxGetMouseState 2931 +#define utils_wxSetDetectableAutoRepeat 2932 +#define utils_wxBell 2933 +#define utils_wxFindMenuItemId 2934 +#define utils_wxGenericFindWindowAtPoint 2935 +#define utils_wxFindWindowAtPoint 2936 +#define utils_wxBeginBusyCursor 2937 +#define utils_wxEndBusyCursor 2938 +#define utils_wxIsBusy 2939 +#define utils_wxShutdown 2940 +#define utils_wxShell 2941 +#define utils_wxLaunchDefaultBrowser 2942 +#define utils_wxGetEmailAddress 2943 +#define utils_wxGetUserId 2944 +#define utils_wxGetHomeDir 2945 +#define utils_wxNewId 2946 +#define utils_wxRegisterId 2947 +#define utils_wxGetCurrentId 2948 +#define utils_wxGetOsDescription 2949 +#define utils_wxIsPlatformLittleEndian 2950 +#define utils_wxIsPlatform64Bit 2951 +#define gdicmn_wxDisplaySize 2952 +#define gdicmn_wxSetCursor 2953 +#define wxPrintout_new 2954 +#define wxPrintout_destruct 2955 +#define wxPrintout_GetDC 2956 +#define wxPrintout_GetPageSizeMM 2957 +#define wxPrintout_GetPageSizePixels 2958 +#define wxPrintout_GetPaperRectPixels 2959 +#define wxPrintout_GetPPIPrinter 2960 +#define wxPrintout_GetPPIScreen 2961 +#define wxPrintout_GetTitle 2962 +#define wxPrintout_IsPreview 2963 +#define wxPrintout_FitThisSizeToPaper 2964 +#define wxPrintout_FitThisSizeToPage 2965 +#define wxPrintout_FitThisSizeToPageMargins 2966 +#define wxPrintout_MapScreenSizeToPaper 2967 +#define wxPrintout_MapScreenSizeToPage 2968 +#define wxPrintout_MapScreenSizeToPageMargins 2969 +#define wxPrintout_MapScreenSizeToDevice 2970 +#define wxPrintout_GetLogicalPaperRect 2971 +#define wxPrintout_GetLogicalPageRect 2972 +#define wxPrintout_GetLogicalPageMarginsRect 2973 +#define wxPrintout_SetLogicalOrigin 2974 +#define wxPrintout_OffsetLogicalOrigin 2975 +#define wxStyledTextCtrl_new_2 2976 +#define wxStyledTextCtrl_new_0 2977 +#define wxStyledTextCtrl_destruct 2978 +#define wxStyledTextCtrl_Create 2979 +#define wxStyledTextCtrl_AddText 2980 +#define wxStyledTextCtrl_AddStyledText 2981 +#define wxStyledTextCtrl_InsertText 2982 +#define wxStyledTextCtrl_ClearAll 2983 +#define wxStyledTextCtrl_ClearDocumentStyle 2984 +#define wxStyledTextCtrl_GetLength 2985 +#define wxStyledTextCtrl_GetCharAt 2986 +#define wxStyledTextCtrl_GetCurrentPos 2987 +#define wxStyledTextCtrl_GetAnchor 2988 +#define wxStyledTextCtrl_GetStyleAt 2989 +#define wxStyledTextCtrl_Redo 2990 +#define wxStyledTextCtrl_SetUndoCollection 2991 +#define wxStyledTextCtrl_SelectAll 2992 +#define wxStyledTextCtrl_SetSavePoint 2993 +#define wxStyledTextCtrl_GetStyledText 2994 +#define wxStyledTextCtrl_CanRedo 2995 +#define wxStyledTextCtrl_MarkerLineFromHandle 2996 +#define wxStyledTextCtrl_MarkerDeleteHandle 2997 +#define wxStyledTextCtrl_GetUndoCollection 2998 +#define wxStyledTextCtrl_GetViewWhiteSpace 2999 +#define wxStyledTextCtrl_SetViewWhiteSpace 3000 +#define wxStyledTextCtrl_PositionFromPoint 3001 +#define wxStyledTextCtrl_PositionFromPointClose 3002 +#define wxStyledTextCtrl_GotoLine 3003 +#define wxStyledTextCtrl_GotoPos 3004 +#define wxStyledTextCtrl_SetAnchor 3005 +#define wxStyledTextCtrl_GetCurLine 3006 +#define wxStyledTextCtrl_GetEndStyled 3007 +#define wxStyledTextCtrl_ConvertEOLs 3008 +#define wxStyledTextCtrl_GetEOLMode 3009 +#define wxStyledTextCtrl_SetEOLMode 3010 +#define wxStyledTextCtrl_StartStyling 3011 +#define wxStyledTextCtrl_SetStyling 3012 +#define wxStyledTextCtrl_GetBufferedDraw 3013 +#define wxStyledTextCtrl_SetBufferedDraw 3014 +#define wxStyledTextCtrl_SetTabWidth 3015 +#define wxStyledTextCtrl_GetTabWidth 3016 +#define wxStyledTextCtrl_SetCodePage 3017 +#define wxStyledTextCtrl_MarkerDefine 3018 +#define wxStyledTextCtrl_MarkerSetForeground 3019 +#define wxStyledTextCtrl_MarkerSetBackground 3020 +#define wxStyledTextCtrl_MarkerAdd 3021 +#define wxStyledTextCtrl_MarkerDelete 3022 +#define wxStyledTextCtrl_MarkerDeleteAll 3023 +#define wxStyledTextCtrl_MarkerGet 3024 +#define wxStyledTextCtrl_MarkerNext 3025 +#define wxStyledTextCtrl_MarkerPrevious 3026 +#define wxStyledTextCtrl_MarkerDefineBitmap 3027 +#define wxStyledTextCtrl_MarkerAddSet 3028 +#define wxStyledTextCtrl_MarkerSetAlpha 3029 +#define wxStyledTextCtrl_SetMarginType 3030 +#define wxStyledTextCtrl_GetMarginType 3031 +#define wxStyledTextCtrl_SetMarginWidth 3032 +#define wxStyledTextCtrl_GetMarginWidth 3033 +#define wxStyledTextCtrl_SetMarginMask 3034 +#define wxStyledTextCtrl_GetMarginMask 3035 +#define wxStyledTextCtrl_SetMarginSensitive 3036 +#define wxStyledTextCtrl_GetMarginSensitive 3037 +#define wxStyledTextCtrl_StyleClearAll 3038 +#define wxStyledTextCtrl_StyleSetForeground 3039 +#define wxStyledTextCtrl_StyleSetBackground 3040 +#define wxStyledTextCtrl_StyleSetBold 3041 +#define wxStyledTextCtrl_StyleSetItalic 3042 +#define wxStyledTextCtrl_StyleSetSize 3043 +#define wxStyledTextCtrl_StyleSetFaceName 3044 +#define wxStyledTextCtrl_StyleSetEOLFilled 3045 +#define wxStyledTextCtrl_StyleResetDefault 3046 +#define wxStyledTextCtrl_StyleSetUnderline 3047 +#define wxStyledTextCtrl_StyleSetCase 3048 +#define wxStyledTextCtrl_StyleSetHotSpot 3049 +#define wxStyledTextCtrl_SetSelForeground 3050 +#define wxStyledTextCtrl_SetSelBackground 3051 +#define wxStyledTextCtrl_GetSelAlpha 3052 +#define wxStyledTextCtrl_SetSelAlpha 3053 +#define wxStyledTextCtrl_SetCaretForeground 3054 +#define wxStyledTextCtrl_CmdKeyAssign 3055 +#define wxStyledTextCtrl_CmdKeyClear 3056 +#define wxStyledTextCtrl_CmdKeyClearAll 3057 +#define wxStyledTextCtrl_SetStyleBytes 3058 +#define wxStyledTextCtrl_StyleSetVisible 3059 +#define wxStyledTextCtrl_GetCaretPeriod 3060 +#define wxStyledTextCtrl_SetCaretPeriod 3061 +#define wxStyledTextCtrl_SetWordChars 3062 +#define wxStyledTextCtrl_BeginUndoAction 3063 +#define wxStyledTextCtrl_EndUndoAction 3064 +#define wxStyledTextCtrl_IndicatorSetStyle 3065 +#define wxStyledTextCtrl_IndicatorGetStyle 3066 +#define wxStyledTextCtrl_IndicatorSetForeground 3067 +#define wxStyledTextCtrl_IndicatorGetForeground 3068 +#define wxStyledTextCtrl_SetWhitespaceForeground 3069 +#define wxStyledTextCtrl_SetWhitespaceBackground 3070 +#define wxStyledTextCtrl_GetStyleBits 3071 +#define wxStyledTextCtrl_SetLineState 3072 +#define wxStyledTextCtrl_GetLineState 3073 +#define wxStyledTextCtrl_GetMaxLineState 3074 +#define wxStyledTextCtrl_GetCaretLineVisible 3075 +#define wxStyledTextCtrl_SetCaretLineVisible 3076 +#define wxStyledTextCtrl_GetCaretLineBackground 3077 +#define wxStyledTextCtrl_SetCaretLineBackground 3078 +#define wxStyledTextCtrl_AutoCompShow 3079 +#define wxStyledTextCtrl_AutoCompCancel 3080 +#define wxStyledTextCtrl_AutoCompActive 3081 +#define wxStyledTextCtrl_AutoCompPosStart 3082 +#define wxStyledTextCtrl_AutoCompComplete 3083 +#define wxStyledTextCtrl_AutoCompStops 3084 +#define wxStyledTextCtrl_AutoCompSetSeparator 3085 +#define wxStyledTextCtrl_AutoCompGetSeparator 3086 +#define wxStyledTextCtrl_AutoCompSelect 3087 +#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3088 +#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3089 +#define wxStyledTextCtrl_AutoCompSetFillUps 3090 +#define wxStyledTextCtrl_AutoCompSetChooseSingle 3091 +#define wxStyledTextCtrl_AutoCompGetChooseSingle 3092 +#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3093 +#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3094 +#define wxStyledTextCtrl_UserListShow 3095 +#define wxStyledTextCtrl_AutoCompSetAutoHide 3096 +#define wxStyledTextCtrl_AutoCompGetAutoHide 3097 +#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3098 +#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3099 +#define wxStyledTextCtrl_RegisterImage 3100 +#define wxStyledTextCtrl_ClearRegisteredImages 3101 +#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3102 +#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3103 +#define wxStyledTextCtrl_AutoCompSetMaxWidth 3104 +#define wxStyledTextCtrl_AutoCompGetMaxWidth 3105 +#define wxStyledTextCtrl_AutoCompSetMaxHeight 3106 +#define wxStyledTextCtrl_AutoCompGetMaxHeight 3107 +#define wxStyledTextCtrl_SetIndent 3108 +#define wxStyledTextCtrl_GetIndent 3109 +#define wxStyledTextCtrl_SetUseTabs 3110 +#define wxStyledTextCtrl_GetUseTabs 3111 +#define wxStyledTextCtrl_SetLineIndentation 3112 +#define wxStyledTextCtrl_GetLineIndentation 3113 +#define wxStyledTextCtrl_GetLineIndentPosition 3114 +#define wxStyledTextCtrl_GetColumn 3115 +#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3116 +#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3117 +#define wxStyledTextCtrl_SetIndentationGuides 3118 +#define wxStyledTextCtrl_GetIndentationGuides 3119 +#define wxStyledTextCtrl_SetHighlightGuide 3120 +#define wxStyledTextCtrl_GetHighlightGuide 3121 +#define wxStyledTextCtrl_GetLineEndPosition 3122 +#define wxStyledTextCtrl_GetCodePage 3123 +#define wxStyledTextCtrl_GetCaretForeground 3124 +#define wxStyledTextCtrl_GetReadOnly 3125 +#define wxStyledTextCtrl_SetCurrentPos 3126 +#define wxStyledTextCtrl_SetSelectionStart 3127 +#define wxStyledTextCtrl_GetSelectionStart 3128 +#define wxStyledTextCtrl_SetSelectionEnd 3129 +#define wxStyledTextCtrl_GetSelectionEnd 3130 +#define wxStyledTextCtrl_SetPrintMagnification 3131 +#define wxStyledTextCtrl_GetPrintMagnification 3132 +#define wxStyledTextCtrl_SetPrintColourMode 3133 +#define wxStyledTextCtrl_GetPrintColourMode 3134 +#define wxStyledTextCtrl_FindText 3135 +#define wxStyledTextCtrl_FormatRange 3136 +#define wxStyledTextCtrl_GetFirstVisibleLine 3137 +#define wxStyledTextCtrl_GetLine 3138 +#define wxStyledTextCtrl_GetLineCount 3139 +#define wxStyledTextCtrl_SetMarginLeft 3140 +#define wxStyledTextCtrl_GetMarginLeft 3141 +#define wxStyledTextCtrl_SetMarginRight 3142 +#define wxStyledTextCtrl_GetMarginRight 3143 +#define wxStyledTextCtrl_GetModify 3144 +#define wxStyledTextCtrl_SetSelection 3145 +#define wxStyledTextCtrl_GetSelectedText 3146 +#define wxStyledTextCtrl_GetTextRange 3147 +#define wxStyledTextCtrl_HideSelection 3148 +#define wxStyledTextCtrl_LineFromPosition 3149 +#define wxStyledTextCtrl_PositionFromLine 3150 +#define wxStyledTextCtrl_LineScroll 3151 +#define wxStyledTextCtrl_EnsureCaretVisible 3152 +#define wxStyledTextCtrl_ReplaceSelection 3153 +#define wxStyledTextCtrl_SetReadOnly 3154 +#define wxStyledTextCtrl_CanPaste 3155 +#define wxStyledTextCtrl_CanUndo 3156 +#define wxStyledTextCtrl_EmptyUndoBuffer 3157 +#define wxStyledTextCtrl_Undo 3158 +#define wxStyledTextCtrl_Cut 3159 +#define wxStyledTextCtrl_Copy 3160 +#define wxStyledTextCtrl_Paste 3161 +#define wxStyledTextCtrl_Clear 3162 +#define wxStyledTextCtrl_SetText 3163 +#define wxStyledTextCtrl_GetText 3164 +#define wxStyledTextCtrl_GetTextLength 3165 +#define wxStyledTextCtrl_GetOvertype 3166 +#define wxStyledTextCtrl_SetCaretWidth 3167 +#define wxStyledTextCtrl_GetCaretWidth 3168 +#define wxStyledTextCtrl_SetTargetStart 3169 +#define wxStyledTextCtrl_GetTargetStart 3170 +#define wxStyledTextCtrl_SetTargetEnd 3171 +#define wxStyledTextCtrl_GetTargetEnd 3172 +#define wxStyledTextCtrl_ReplaceTarget 3173 +#define wxStyledTextCtrl_SearchInTarget 3174 +#define wxStyledTextCtrl_SetSearchFlags 3175 +#define wxStyledTextCtrl_GetSearchFlags 3176 +#define wxStyledTextCtrl_CallTipShow 3177 +#define wxStyledTextCtrl_CallTipCancel 3178 +#define wxStyledTextCtrl_CallTipActive 3179 +#define wxStyledTextCtrl_CallTipPosAtStart 3180 +#define wxStyledTextCtrl_CallTipSetHighlight 3181 +#define wxStyledTextCtrl_CallTipSetBackground 3182 +#define wxStyledTextCtrl_CallTipSetForeground 3183 +#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3184 +#define wxStyledTextCtrl_CallTipUseStyle 3185 +#define wxStyledTextCtrl_VisibleFromDocLine 3186 +#define wxStyledTextCtrl_DocLineFromVisible 3187 +#define wxStyledTextCtrl_WrapCount 3188 +#define wxStyledTextCtrl_SetFoldLevel 3189 +#define wxStyledTextCtrl_GetFoldLevel 3190 +#define wxStyledTextCtrl_GetLastChild 3191 +#define wxStyledTextCtrl_GetFoldParent 3192 +#define wxStyledTextCtrl_ShowLines 3193 +#define wxStyledTextCtrl_HideLines 3194 +#define wxStyledTextCtrl_GetLineVisible 3195 +#define wxStyledTextCtrl_SetFoldExpanded 3196 +#define wxStyledTextCtrl_GetFoldExpanded 3197 +#define wxStyledTextCtrl_ToggleFold 3198 +#define wxStyledTextCtrl_EnsureVisible 3199 +#define wxStyledTextCtrl_SetFoldFlags 3200 +#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3201 +#define wxStyledTextCtrl_SetTabIndents 3202 +#define wxStyledTextCtrl_GetTabIndents 3203 +#define wxStyledTextCtrl_SetBackSpaceUnIndents 3204 +#define wxStyledTextCtrl_GetBackSpaceUnIndents 3205 +#define wxStyledTextCtrl_SetMouseDwellTime 3206 +#define wxStyledTextCtrl_GetMouseDwellTime 3207 +#define wxStyledTextCtrl_WordStartPosition 3208 +#define wxStyledTextCtrl_WordEndPosition 3209 +#define wxStyledTextCtrl_SetWrapMode 3210 +#define wxStyledTextCtrl_GetWrapMode 3211 +#define wxStyledTextCtrl_SetWrapVisualFlags 3212 +#define wxStyledTextCtrl_GetWrapVisualFlags 3213 +#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3214 +#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3215 +#define wxStyledTextCtrl_SetWrapStartIndent 3216 +#define wxStyledTextCtrl_GetWrapStartIndent 3217 +#define wxStyledTextCtrl_SetLayoutCache 3218 +#define wxStyledTextCtrl_GetLayoutCache 3219 +#define wxStyledTextCtrl_SetScrollWidth 3220 +#define wxStyledTextCtrl_GetScrollWidth 3221 +#define wxStyledTextCtrl_TextWidth 3222 +#define wxStyledTextCtrl_GetEndAtLastLine 3223 +#define wxStyledTextCtrl_TextHeight 3224 +#define wxStyledTextCtrl_SetUseVerticalScrollBar 3225 +#define wxStyledTextCtrl_GetUseVerticalScrollBar 3226 +#define wxStyledTextCtrl_AppendText 3227 +#define wxStyledTextCtrl_GetTwoPhaseDraw 3228 +#define wxStyledTextCtrl_SetTwoPhaseDraw 3229 +#define wxStyledTextCtrl_TargetFromSelection 3230 +#define wxStyledTextCtrl_LinesJoin 3231 +#define wxStyledTextCtrl_LinesSplit 3232 +#define wxStyledTextCtrl_SetFoldMarginColour 3233 +#define wxStyledTextCtrl_SetFoldMarginHiColour 3234 +#define wxStyledTextCtrl_LineDown 3235 +#define wxStyledTextCtrl_LineDownExtend 3236 +#define wxStyledTextCtrl_LineUp 3237 +#define wxStyledTextCtrl_LineUpExtend 3238 +#define wxStyledTextCtrl_CharLeft 3239 +#define wxStyledTextCtrl_CharLeftExtend 3240 +#define wxStyledTextCtrl_CharRight 3241 +#define wxStyledTextCtrl_CharRightExtend 3242 +#define wxStyledTextCtrl_WordLeft 3243 +#define wxStyledTextCtrl_WordLeftExtend 3244 +#define wxStyledTextCtrl_WordRight 3245 +#define wxStyledTextCtrl_WordRightExtend 3246 +#define wxStyledTextCtrl_Home 3247 +#define wxStyledTextCtrl_HomeExtend 3248 +#define wxStyledTextCtrl_LineEnd 3249 +#define wxStyledTextCtrl_LineEndExtend 3250 +#define wxStyledTextCtrl_DocumentStart 3251 +#define wxStyledTextCtrl_DocumentStartExtend 3252 +#define wxStyledTextCtrl_DocumentEnd 3253 +#define wxStyledTextCtrl_DocumentEndExtend 3254 +#define wxStyledTextCtrl_PageUp 3255 +#define wxStyledTextCtrl_PageUpExtend 3256 +#define wxStyledTextCtrl_PageDown 3257 +#define wxStyledTextCtrl_PageDownExtend 3258 +#define wxStyledTextCtrl_EditToggleOvertype 3259 +#define wxStyledTextCtrl_Cancel 3260 +#define wxStyledTextCtrl_DeleteBack 3261 +#define wxStyledTextCtrl_Tab 3262 +#define wxStyledTextCtrl_BackTab 3263 +#define wxStyledTextCtrl_NewLine 3264 +#define wxStyledTextCtrl_FormFeed 3265 +#define wxStyledTextCtrl_VCHome 3266 +#define wxStyledTextCtrl_VCHomeExtend 3267 +#define wxStyledTextCtrl_ZoomIn 3268 +#define wxStyledTextCtrl_ZoomOut 3269 +#define wxStyledTextCtrl_DelWordLeft 3270 +#define wxStyledTextCtrl_DelWordRight 3271 +#define wxStyledTextCtrl_LineCut 3272 +#define wxStyledTextCtrl_LineDelete 3273 +#define wxStyledTextCtrl_LineTranspose 3274 +#define wxStyledTextCtrl_LineDuplicate 3275 +#define wxStyledTextCtrl_LowerCase 3276 +#define wxStyledTextCtrl_UpperCase 3277 +#define wxStyledTextCtrl_LineScrollDown 3278 +#define wxStyledTextCtrl_LineScrollUp 3279 +#define wxStyledTextCtrl_DeleteBackNotLine 3280 +#define wxStyledTextCtrl_HomeDisplay 3281 +#define wxStyledTextCtrl_HomeDisplayExtend 3282 +#define wxStyledTextCtrl_LineEndDisplay 3283 +#define wxStyledTextCtrl_LineEndDisplayExtend 3284 +#define wxStyledTextCtrl_HomeWrapExtend 3285 +#define wxStyledTextCtrl_LineEndWrap 3286 +#define wxStyledTextCtrl_LineEndWrapExtend 3287 +#define wxStyledTextCtrl_VCHomeWrap 3288 +#define wxStyledTextCtrl_VCHomeWrapExtend 3289 +#define wxStyledTextCtrl_LineCopy 3290 +#define wxStyledTextCtrl_MoveCaretInsideView 3291 +#define wxStyledTextCtrl_LineLength 3292 +#define wxStyledTextCtrl_BraceHighlight 3293 +#define wxStyledTextCtrl_BraceBadLight 3294 +#define wxStyledTextCtrl_BraceMatch 3295 +#define wxStyledTextCtrl_GetViewEOL 3296 +#define wxStyledTextCtrl_SetViewEOL 3297 +#define wxStyledTextCtrl_SetModEventMask 3298 +#define wxStyledTextCtrl_GetEdgeColumn 3299 +#define wxStyledTextCtrl_SetEdgeColumn 3300 +#define wxStyledTextCtrl_SetEdgeMode 3301 +#define wxStyledTextCtrl_GetEdgeMode 3302 +#define wxStyledTextCtrl_GetEdgeColour 3303 +#define wxStyledTextCtrl_SetEdgeColour 3304 +#define wxStyledTextCtrl_SearchAnchor 3305 +#define wxStyledTextCtrl_SearchNext 3306 +#define wxStyledTextCtrl_SearchPrev 3307 +#define wxStyledTextCtrl_LinesOnScreen 3308 +#define wxStyledTextCtrl_UsePopUp 3309 +#define wxStyledTextCtrl_SelectionIsRectangle 3310 +#define wxStyledTextCtrl_SetZoom 3311 +#define wxStyledTextCtrl_GetZoom 3312 +#define wxStyledTextCtrl_GetModEventMask 3313 +#define wxStyledTextCtrl_SetSTCFocus 3314 +#define wxStyledTextCtrl_GetSTCFocus 3315 +#define wxStyledTextCtrl_SetStatus 3316 +#define wxStyledTextCtrl_GetStatus 3317 +#define wxStyledTextCtrl_SetMouseDownCaptures 3318 +#define wxStyledTextCtrl_GetMouseDownCaptures 3319 +#define wxStyledTextCtrl_SetSTCCursor 3320 +#define wxStyledTextCtrl_GetSTCCursor 3321 +#define wxStyledTextCtrl_SetControlCharSymbol 3322 +#define wxStyledTextCtrl_GetControlCharSymbol 3323 +#define wxStyledTextCtrl_WordPartLeft 3324 +#define wxStyledTextCtrl_WordPartLeftExtend 3325 +#define wxStyledTextCtrl_WordPartRight 3326 +#define wxStyledTextCtrl_WordPartRightExtend 3327 +#define wxStyledTextCtrl_SetVisiblePolicy 3328 +#define wxStyledTextCtrl_DelLineLeft 3329 +#define wxStyledTextCtrl_DelLineRight 3330 +#define wxStyledTextCtrl_GetXOffset 3331 +#define wxStyledTextCtrl_ChooseCaretX 3332 +#define wxStyledTextCtrl_SetXCaretPolicy 3333 +#define wxStyledTextCtrl_SetYCaretPolicy 3334 +#define wxStyledTextCtrl_GetPrintWrapMode 3335 +#define wxStyledTextCtrl_SetHotspotActiveForeground 3336 +#define wxStyledTextCtrl_SetHotspotActiveBackground 3337 +#define wxStyledTextCtrl_SetHotspotActiveUnderline 3338 +#define wxStyledTextCtrl_SetHotspotSingleLine 3339 +#define wxStyledTextCtrl_ParaDownExtend 3340 +#define wxStyledTextCtrl_ParaUp 3341 +#define wxStyledTextCtrl_ParaUpExtend 3342 +#define wxStyledTextCtrl_PositionBefore 3343 +#define wxStyledTextCtrl_PositionAfter 3344 +#define wxStyledTextCtrl_CopyRange 3345 +#define wxStyledTextCtrl_CopyText 3346 +#define wxStyledTextCtrl_SetSelectionMode 3347 +#define wxStyledTextCtrl_GetSelectionMode 3348 +#define wxStyledTextCtrl_LineDownRectExtend 3349 +#define wxStyledTextCtrl_LineUpRectExtend 3350 +#define wxStyledTextCtrl_CharLeftRectExtend 3351 +#define wxStyledTextCtrl_CharRightRectExtend 3352 +#define wxStyledTextCtrl_HomeRectExtend 3353 +#define wxStyledTextCtrl_VCHomeRectExtend 3354 +#define wxStyledTextCtrl_LineEndRectExtend 3355 +#define wxStyledTextCtrl_PageUpRectExtend 3356 +#define wxStyledTextCtrl_PageDownRectExtend 3357 +#define wxStyledTextCtrl_StutteredPageUp 3358 +#define wxStyledTextCtrl_StutteredPageUpExtend 3359 +#define wxStyledTextCtrl_StutteredPageDown 3360 +#define wxStyledTextCtrl_StutteredPageDownExtend 3361 +#define wxStyledTextCtrl_WordLeftEnd 3362 +#define wxStyledTextCtrl_WordLeftEndExtend 3363 +#define wxStyledTextCtrl_WordRightEnd 3364 +#define wxStyledTextCtrl_WordRightEndExtend 3365 +#define wxStyledTextCtrl_SetWhitespaceChars 3366 +#define wxStyledTextCtrl_SetCharsDefault 3367 +#define wxStyledTextCtrl_AutoCompGetCurrent 3368 +#define wxStyledTextCtrl_Allocate 3369 +#define wxStyledTextCtrl_FindColumn 3370 +#define wxStyledTextCtrl_GetCaretSticky 3371 +#define wxStyledTextCtrl_SetCaretSticky 3372 +#define wxStyledTextCtrl_ToggleCaretSticky 3373 +#define wxStyledTextCtrl_SetPasteConvertEndings 3374 +#define wxStyledTextCtrl_GetPasteConvertEndings 3375 +#define wxStyledTextCtrl_SelectionDuplicate 3376 +#define wxStyledTextCtrl_SetCaretLineBackAlpha 3377 +#define wxStyledTextCtrl_GetCaretLineBackAlpha 3378 +#define wxStyledTextCtrl_StartRecord 3379 +#define wxStyledTextCtrl_StopRecord 3380 +#define wxStyledTextCtrl_SetLexer 3381 +#define wxStyledTextCtrl_GetLexer 3382 +#define wxStyledTextCtrl_Colourise 3383 +#define wxStyledTextCtrl_SetProperty 3384 +#define wxStyledTextCtrl_SetKeyWords 3385 +#define wxStyledTextCtrl_SetLexerLanguage 3386 +#define wxStyledTextCtrl_GetProperty 3387 +#define wxStyledTextCtrl_GetStyleBitsNeeded 3388 +#define wxStyledTextCtrl_GetCurrentLine 3389 +#define wxStyledTextCtrl_StyleSetSpec 3390 +#define wxStyledTextCtrl_StyleSetFont 3391 +#define wxStyledTextCtrl_StyleSetFontAttr 3392 +#define wxStyledTextCtrl_StyleSetCharacterSet 3393 +#define wxStyledTextCtrl_StyleSetFontEncoding 3394 +#define wxStyledTextCtrl_CmdKeyExecute 3395 +#define wxStyledTextCtrl_SetMargins 3396 +#define wxStyledTextCtrl_GetSelection 3397 +#define wxStyledTextCtrl_PointFromPosition 3398 +#define wxStyledTextCtrl_ScrollToLine 3399 +#define wxStyledTextCtrl_ScrollToColumn 3400 +#define wxStyledTextCtrl_SetVScrollBar 3401 +#define wxStyledTextCtrl_SetHScrollBar 3402 +#define wxStyledTextCtrl_GetLastKeydownProcessed 3403 +#define wxStyledTextCtrl_SetLastKeydownProcessed 3404 +#define wxStyledTextCtrl_SaveFile 3405 +#define wxStyledTextCtrl_LoadFile 3406 +#define wxStyledTextCtrl_DoDragOver 3407 +#define wxStyledTextCtrl_DoDropText 3408 +#define wxStyledTextCtrl_GetUseAntiAliasing 3409 +#define wxStyledTextCtrl_AddTextRaw 3410 +#define wxStyledTextCtrl_InsertTextRaw 3411 +#define wxStyledTextCtrl_GetCurLineRaw 3412 +#define wxStyledTextCtrl_GetLineRaw 3413 +#define wxStyledTextCtrl_GetSelectedTextRaw 3414 +#define wxStyledTextCtrl_GetTextRangeRaw 3415 +#define wxStyledTextCtrl_SetTextRaw 3416 +#define wxStyledTextCtrl_GetTextRaw 3417 +#define wxStyledTextCtrl_AppendTextRaw 3418 +#define wxArtProvider_GetBitmap 3419 +#define wxArtProvider_GetIcon 3420 +#define wxTreeEvent_GetKeyCode 3421 +#define wxTreeEvent_GetItem 3422 +#define wxTreeEvent_GetKeyEvent 3423 +#define wxTreeEvent_GetLabel 3424 +#define wxTreeEvent_GetOldItem 3425 +#define wxTreeEvent_GetPoint 3426 +#define wxTreeEvent_IsEditCancelled 3427 +#define wxTreeEvent_SetToolTip 3428 +#define wxNotebookEvent_GetOldSelection 3429 +#define wxNotebookEvent_GetSelection 3430 +#define wxNotebookEvent_SetOldSelection 3431 +#define wxNotebookEvent_SetSelection 3432 +#define wxFileDataObject_new 3433 +#define wxFileDataObject_AddFile 3434 +#define wxFileDataObject_GetFilenames 3435 +#define wxFileDataObject_destroy 3436 +#define wxTextDataObject_new 3437 +#define wxTextDataObject_GetTextLength 3438 +#define wxTextDataObject_GetText 3439 +#define wxTextDataObject_SetText 3440 +#define wxTextDataObject_destroy 3441 +#define wxBitmapDataObject_new_1_1 3442 +#define wxBitmapDataObject_new_1_0 3443 +#define wxBitmapDataObject_GetBitmap 3444 +#define wxBitmapDataObject_SetBitmap 3445 +#define wxBitmapDataObject_destroy 3446 +#define wxClipboard_new 3448 +#define wxClipboard_destruct 3449 +#define wxClipboard_AddData 3450 +#define wxClipboard_Clear 3451 +#define wxClipboard_Close 3452 +#define wxClipboard_Flush 3453 +#define wxClipboard_GetData 3454 +#define wxClipboard_IsOpened 3455 +#define wxClipboard_Open 3456 +#define wxClipboard_SetData 3457 +#define wxClipboard_UsePrimarySelection 3459 +#define wxClipboard_IsSupported 3460 +#define wxClipboard_Get 3461 +#define wxSpinEvent_GetPosition 3462 +#define wxSpinEvent_SetPosition 3463 +#define wxSplitterWindow_new_0 3464 +#define wxSplitterWindow_new_2 3465 +#define wxSplitterWindow_destruct 3466 +#define wxSplitterWindow_Create 3467 +#define wxSplitterWindow_GetMinimumPaneSize 3468 +#define wxSplitterWindow_GetSashGravity 3469 +#define wxSplitterWindow_GetSashPosition 3470 +#define wxSplitterWindow_GetSplitMode 3471 +#define wxSplitterWindow_GetWindow1 3472 +#define wxSplitterWindow_GetWindow2 3473 +#define wxSplitterWindow_Initialize 3474 +#define wxSplitterWindow_IsSplit 3475 +#define wxSplitterWindow_ReplaceWindow 3476 +#define wxSplitterWindow_SetSashGravity 3477 +#define wxSplitterWindow_SetSashPosition 3478 +#define wxSplitterWindow_SetSashSize 3479 +#define wxSplitterWindow_SetMinimumPaneSize 3480 +#define wxSplitterWindow_SetSplitMode 3481 +#define wxSplitterWindow_SplitHorizontally 3482 +#define wxSplitterWindow_SplitVertically 3483 +#define wxSplitterWindow_Unsplit 3484 +#define wxSplitterWindow_UpdateSize 3485 +#define wxSplitterEvent_GetSashPosition 3486 +#define wxSplitterEvent_GetX 3487 +#define wxSplitterEvent_GetY 3488 +#define wxSplitterEvent_GetWindowBeingRemoved 3489 +#define wxSplitterEvent_SetSashPosition 3490 +#define wxHtmlWindow_new_0 3491 +#define wxHtmlWindow_new_2 3492 +#define wxHtmlWindow_AppendToPage 3493 +#define wxHtmlWindow_GetOpenedAnchor 3494 +#define wxHtmlWindow_GetOpenedPage 3495 +#define wxHtmlWindow_GetOpenedPageTitle 3496 +#define wxHtmlWindow_GetRelatedFrame 3497 +#define wxHtmlWindow_HistoryBack 3498 +#define wxHtmlWindow_HistoryCanBack 3499 +#define wxHtmlWindow_HistoryCanForward 3500 +#define wxHtmlWindow_HistoryClear 3501 +#define wxHtmlWindow_HistoryForward 3502 +#define wxHtmlWindow_LoadFile 3503 +#define wxHtmlWindow_LoadPage 3504 +#define wxHtmlWindow_SelectAll 3505 +#define wxHtmlWindow_SelectionToText 3506 +#define wxHtmlWindow_SelectLine 3507 +#define wxHtmlWindow_SelectWord 3508 +#define wxHtmlWindow_SetBorders 3509 +#define wxHtmlWindow_SetFonts 3510 +#define wxHtmlWindow_SetPage 3511 +#define wxHtmlWindow_SetRelatedFrame 3512 +#define wxHtmlWindow_SetRelatedStatusBar 3513 +#define wxHtmlWindow_ToText 3514 +#define wxHtmlWindow_destroy 3515 +#define wxHtmlLinkEvent_GetLinkInfo 3516 +#define wxSystemSettings_GetColour 3517 +#define wxSystemSettings_GetFont 3518 +#define wxSystemSettings_GetMetric 3519 +#define wxSystemSettings_GetScreenType 3520 +#define wxSystemOptions_GetOption 3521 +#define wxSystemOptions_GetOptionInt 3522 +#define wxSystemOptions_HasOption 3523 +#define wxSystemOptions_IsFalse 3524 +#define wxSystemOptions_SetOption_2_1 3525 +#define wxSystemOptions_SetOption_2_0 3526 +#define wxAuiNotebookEvent_SetSelection 3527 +#define wxAuiNotebookEvent_GetSelection 3528 +#define wxAuiNotebookEvent_SetOldSelection 3529 +#define wxAuiNotebookEvent_GetOldSelection 3530 +#define wxAuiNotebookEvent_SetDragSource 3531 +#define wxAuiNotebookEvent_GetDragSource 3532 +#define wxAuiManagerEvent_SetManager 3533 +#define wxAuiManagerEvent_GetManager 3534 +#define wxAuiManagerEvent_SetPane 3535 +#define wxAuiManagerEvent_GetPane 3536 +#define wxAuiManagerEvent_SetButton 3537 +#define wxAuiManagerEvent_GetButton 3538 +#define wxAuiManagerEvent_SetDC 3539 +#define wxAuiManagerEvent_GetDC 3540 +#define wxAuiManagerEvent_Veto 3541 +#define wxAuiManagerEvent_GetVeto 3542 +#define wxAuiManagerEvent_SetCanVeto 3543 +#define wxAuiManagerEvent_CanVeto 3544 +#define wxLogNull_new 3545 +#define wxLogNull_destroy 3546 +#define wxTaskBarIcon_new 3547 +#define wxTaskBarIcon_destruct 3548 +#define wxTaskBarIcon_PopupMenu 3549 +#define wxTaskBarIcon_RemoveIcon 3550 +#define wxTaskBarIcon_SetIcon 3551 +#define wxLocale_new_0 3552 +#define wxLocale_new_2 3554 +#define wxLocale_destruct 3555 +#define wxLocale_Init 3557 +#define wxLocale_AddCatalog_1 3558 +#define wxLocale_AddCatalog_3 3559 +#define wxLocale_AddCatalogLookupPathPrefix 3560 +#define wxLocale_GetCanonicalName 3561 +#define wxLocale_GetLanguage 3562 +#define wxLocale_GetLanguageName 3563 +#define wxLocale_GetLocale 3564 +#define wxLocale_GetName 3565 +#define wxLocale_GetString_2 3566 +#define wxLocale_GetString_4 3567 +#define wxLocale_GetHeaderValue 3568 +#define wxLocale_GetSysName 3569 +#define wxLocale_GetSystemEncoding 3570 +#define wxLocale_GetSystemEncodingName 3571 +#define wxLocale_GetSystemLanguage 3572 +#define wxLocale_IsLoaded 3573 +#define wxLocale_IsOk 3574 +#define wxActivateEvent_GetActive 3575 +#define wxPopupWindow_new_2 3577 +#define wxPopupWindow_new_0 3578 +#define wxPopupWindow_destruct 3580 +#define wxPopupWindow_Create 3581 +#define wxPopupWindow_Position 3582 +#define wxPopupTransientWindow_new_0 3583 +#define wxPopupTransientWindow_new_2 3584 +#define wxPopupTransientWindow_destruct 3585 +#define wxPopupTransientWindow_Popup 3586 +#define wxPopupTransientWindow_Dismiss 3587 +#define wxOverlay_new 3588 +#define wxOverlay_destruct 3589 +#define wxOverlay_Reset 3590 +#define wxDCOverlay_new_6 3591 +#define wxDCOverlay_new_2 3592 +#define wxDCOverlay_destruct 3593 +#define wxDCOverlay_Clear 3594 diff --git a/lib/wx/src/gen/wxToolBar.erl b/lib/wx/src/gen/wxToolBar.erl index 5c079fec1e..bee20b97f4 100644 --- a/lib/wx/src/gen/wxToolBar.erl +++ b/lib/wx/src/gen/wxToolBar.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -31,14 +31,15 @@ -module(wxToolBar). -include("wxe.hrl"). -export([addCheckTool/4,addCheckTool/5,addControl/2,addRadioTool/4,addRadioTool/5, - addSeparator/1,addTool/2,addTool/3,addTool/4,addTool/5,addTool/6,addTool/7, - deleteTool/2,deleteToolByPos/2,enableTool/3,findById/2,findControl/2, - findToolForPosition/3,getMargins/1,getToolBitmapSize/1,getToolEnabled/2, - getToolLongHelp/2,getToolPacking/1,getToolPos/2,getToolSeparation/1, - getToolShortHelp/2,getToolSize/1,getToolState/2,insertControl/3,insertSeparator/2, - insertTool/3,insertTool/4,insertTool/5,insertTool/6,realize/1,removeTool/2, - setMargins/3,setToolBitmapSize/2,setToolLongHelp/3,setToolPacking/2, - setToolSeparation/2,setToolShortHelp/3,toggleTool/3]). + addSeparator/1,addStretchableSpace/1,addTool/2,addTool/3,addTool/4, + addTool/5,addTool/6,addTool/7,deleteTool/2,deleteToolByPos/2,enableTool/3, + findById/2,findControl/2,findToolForPosition/3,getMargins/1,getToolBitmapSize/1, + getToolEnabled/2,getToolLongHelp/2,getToolPacking/1,getToolPos/2, + getToolSeparation/1,getToolShortHelp/2,getToolSize/1,getToolState/2, + insertControl/3,insertSeparator/2,insertStretchableSpace/2,insertTool/3, + insertTool/4,insertTool/5,insertTool/6,realize/1,removeTool/2,setMargins/3, + setToolBitmapSize/2,setToolLongHelp/3,setToolPacking/2,setToolSeparation/2, + setToolShortHelp/3,toggleTool/3]). %% inherited exports -export([cacheBestSize/2,captureMouse/1,center/1,center/2,centerOnParent/1, @@ -328,6 +329,23 @@ addRadioTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Label,#wx_ref{type=BitmapT,r wxe_util:call(?wxToolBar_AddRadioTool, <>). +%% @doc See external documentation. +-spec addStretchableSpace(This) -> wx:wx_object() when + This::wxToolBar(). +addStretchableSpace(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxToolBar), + wxe_util:call(?wxToolBar_AddStretchableSpace, + <>). + +%% @doc See external documentation. +-spec insertStretchableSpace(This, Pos) -> wx:wx_object() when + This::wxToolBar(), Pos::integer(). +insertStretchableSpace(#wx_ref{type=ThisT,ref=ThisRef},Pos) + when is_integer(Pos) -> + ?CLASS(ThisT,wxToolBar), + wxe_util:call(?wxToolBar_InsertStretchableSpace, + <>). + %% @doc See external documentation. -spec deleteTool(This, Toolid) -> boolean() when This::wxToolBar(), Toolid::integer(). diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl index 6c7602acd3..375adde47d 100644 --- a/lib/wx/src/gen/wxe_debug.hrl +++ b/lib/wx/src/gen/wxe_debug.hrl @@ -863,2513 +863,2515 @@ wxdebug_table() -> {981, {wxToolBar, addTool_6, 6}}, {982, {wxToolBar, addCheckTool, 4}}, {983, {wxToolBar, addRadioTool, 4}}, - {984, {wxToolBar, deleteTool, 1}}, - {985, {wxToolBar, deleteToolByPos, 1}}, - {986, {wxToolBar, enableTool, 2}}, - {987, {wxToolBar, findById, 1}}, - {988, {wxToolBar, findControl, 1}}, - {989, {wxToolBar, findToolForPosition, 2}}, - {990, {wxToolBar, getToolSize, 0}}, - {991, {wxToolBar, getToolBitmapSize, 0}}, - {992, {wxToolBar, getMargins, 0}}, - {993, {wxToolBar, getToolEnabled, 1}}, - {994, {wxToolBar, getToolLongHelp, 1}}, - {995, {wxToolBar, getToolPacking, 0}}, - {996, {wxToolBar, getToolPos, 1}}, - {997, {wxToolBar, getToolSeparation, 0}}, - {998, {wxToolBar, getToolShortHelp, 1}}, - {999, {wxToolBar, getToolState, 1}}, - {1000, {wxToolBar, insertControl, 2}}, - {1001, {wxToolBar, insertSeparator, 1}}, - {1002, {wxToolBar, insertTool_5, 5}}, - {1003, {wxToolBar, insertTool_2, 2}}, - {1004, {wxToolBar, insertTool_4, 4}}, - {1005, {wxToolBar, realize, 0}}, - {1006, {wxToolBar, removeTool, 1}}, - {1007, {wxToolBar, setMargins, 2}}, - {1008, {wxToolBar, setToolBitmapSize, 1}}, - {1009, {wxToolBar, setToolLongHelp, 2}}, - {1010, {wxToolBar, setToolPacking, 1}}, - {1011, {wxToolBar, setToolShortHelp, 2}}, - {1012, {wxToolBar, setToolSeparation, 1}}, - {1013, {wxToolBar, toggleTool, 2}}, - {1015, {wxStatusBar, new_0, 0}}, - {1016, {wxStatusBar, new_2, 2}}, - {1018, {wxStatusBar, destruct, 0}}, - {1019, {wxStatusBar, create, 2}}, - {1020, {wxStatusBar, getFieldRect, 2}}, - {1021, {wxStatusBar, getFieldsCount, 0}}, - {1022, {wxStatusBar, getStatusText, 1}}, - {1023, {wxStatusBar, popStatusText, 1}}, - {1024, {wxStatusBar, pushStatusText, 2}}, - {1025, {wxStatusBar, setFieldsCount, 2}}, - {1026, {wxStatusBar, setMinHeight, 1}}, - {1027, {wxStatusBar, setStatusText, 2}}, - {1028, {wxStatusBar, setStatusWidths, 2}}, - {1029, {wxStatusBar, setStatusStyles, 2}}, - {1030, {wxBitmap, new_0, 0}}, - {1031, {wxBitmap, new_3, 3}}, - {1032, {wxBitmap, new_4, 4}}, - {1033, {wxBitmap, new_2_0, 2}}, - {1034, {wxBitmap, new_2_1, 2}}, - {1035, {wxBitmap, destruct, 0}}, - {1036, {wxBitmap, convertToImage, 0}}, - {1037, {wxBitmap, copyFromIcon, 1}}, - {1038, {wxBitmap, create, 3}}, - {1039, {wxBitmap, getDepth, 0}}, - {1040, {wxBitmap, getHeight, 0}}, - {1041, {wxBitmap, getPalette, 0}}, - {1042, {wxBitmap, getMask, 0}}, - {1043, {wxBitmap, getWidth, 0}}, - {1044, {wxBitmap, getSubBitmap, 1}}, - {1045, {wxBitmap, loadFile, 2}}, - {1046, {wxBitmap, ok, 0}}, - {1047, {wxBitmap, saveFile, 3}}, - {1048, {wxBitmap, setDepth, 1}}, - {1049, {wxBitmap, setHeight, 1}}, - {1050, {wxBitmap, setMask, 1}}, - {1051, {wxBitmap, setPalette, 1}}, - {1052, {wxBitmap, setWidth, 1}}, - {1053, {wxIcon, new_0, 0}}, - {1054, {wxIcon, new_2, 2}}, - {1055, {wxIcon, new_1, 1}}, - {1056, {wxIcon, copyFromBitmap, 1}}, - {1057, {wxIcon, 'Destroy', undefined}}, - {1058, {wxIconBundle, new_0, 0}}, - {1059, {wxIconBundle, new_2, 2}}, - {1060, {wxIconBundle, new_1_0, 1}}, - {1061, {wxIconBundle, new_1_1, 1}}, - {1062, {wxIconBundle, destruct, 0}}, - {1063, {wxIconBundle, addIcon_2, 2}}, - {1064, {wxIconBundle, addIcon_1, 1}}, - {1065, {wxIconBundle, getIcon_1_1, 1}}, - {1066, {wxIconBundle, getIcon_1_0, 1}}, - {1067, {wxCursor, new_0, 0}}, - {1068, {wxCursor, new_1_0, 1}}, - {1069, {wxCursor, new_1_1, 1}}, - {1070, {wxCursor, new_4, 4}}, - {1071, {wxCursor, destruct, 0}}, - {1072, {wxCursor, ok, 0}}, - {1073, {wxMask, new_0, 0}}, - {1074, {wxMask, new_2_1, 2}}, - {1075, {wxMask, new_2_0, 2}}, - {1076, {wxMask, new_1, 1}}, - {1077, {wxMask, destruct, 0}}, - {1078, {wxMask, create_2_1, 2}}, - {1079, {wxMask, create_2_0, 2}}, - {1080, {wxMask, create_1, 1}}, - {1081, {wxImage, new_0, 0}}, - {1082, {wxImage, new_3_0, 3}}, - {1083, {wxImage, new_4, 4}}, - {1084, {wxImage, new_5, 5}}, - {1085, {wxImage, new_2, 2}}, - {1086, {wxImage, new_3_1, 3}}, - {1087, {wxImage, blur, 1}}, - {1088, {wxImage, blurHorizontal, 1}}, - {1089, {wxImage, blurVertical, 1}}, - {1090, {wxImage, convertAlphaToMask, 1}}, - {1091, {wxImage, convertToGreyscale, 1}}, - {1092, {wxImage, convertToMono, 3}}, - {1093, {wxImage, copy, 0}}, - {1094, {wxImage, create_3, 3}}, - {1095, {wxImage, create_4, 4}}, - {1096, {wxImage, create_5, 5}}, - {1097, {wxImage, 'Destroy', 0}}, - {1098, {wxImage, findFirstUnusedColour, 4}}, - {1099, {wxImage, getImageExtWildcard, 0}}, - {1100, {wxImage, getAlpha_2, 2}}, - {1101, {wxImage, getAlpha_0, 0}}, - {1102, {wxImage, getBlue, 2}}, - {1103, {wxImage, getData, 0}}, - {1104, {wxImage, getGreen, 2}}, - {1105, {wxImage, getImageCount, 2}}, - {1106, {wxImage, getHeight, 0}}, - {1107, {wxImage, getMaskBlue, 0}}, - {1108, {wxImage, getMaskGreen, 0}}, - {1109, {wxImage, getMaskRed, 0}}, - {1110, {wxImage, getOrFindMaskColour, 3}}, - {1111, {wxImage, getPalette, 0}}, - {1112, {wxImage, getRed, 2}}, - {1113, {wxImage, getSubImage, 1}}, - {1114, {wxImage, getWidth, 0}}, - {1115, {wxImage, hasAlpha, 0}}, - {1116, {wxImage, hasMask, 0}}, - {1117, {wxImage, getOption, 1}}, - {1118, {wxImage, getOptionInt, 1}}, - {1119, {wxImage, hasOption, 1}}, - {1120, {wxImage, initAlpha, 0}}, - {1121, {wxImage, initStandardHandlers, 0}}, - {1122, {wxImage, isTransparent, 3}}, - {1123, {wxImage, loadFile_2, 2}}, - {1124, {wxImage, loadFile_3, 3}}, - {1125, {wxImage, ok, 0}}, - {1126, {wxImage, removeHandler, 1}}, - {1127, {wxImage, mirror, 1}}, - {1128, {wxImage, replace, 6}}, - {1129, {wxImage, rescale, 3}}, - {1130, {wxImage, resize, 3}}, - {1131, {wxImage, rotate, 3}}, - {1132, {wxImage, rotateHue, 1}}, - {1133, {wxImage, rotate90, 1}}, - {1134, {wxImage, saveFile_1, 1}}, - {1135, {wxImage, saveFile_2_0, 2}}, - {1136, {wxImage, saveFile_2_1, 2}}, - {1137, {wxImage, scale, 3}}, - {1138, {wxImage, size, 3}}, - {1139, {wxImage, setAlpha_3, 3}}, - {1140, {wxImage, setAlpha_2, 2}}, - {1141, {wxImage, setData_2, 2}}, - {1142, {wxImage, setData_4, 4}}, - {1143, {wxImage, setMask, 1}}, - {1144, {wxImage, setMaskColour, 3}}, - {1145, {wxImage, setMaskFromImage, 4}}, - {1146, {wxImage, setOption_2_1, 2}}, - {1147, {wxImage, setOption_2_0, 2}}, - {1148, {wxImage, setPalette, 1}}, - {1149, {wxImage, setRGB_5, 5}}, - {1150, {wxImage, setRGB_4, 4}}, - {1151, {wxImage, 'Destroy', undefined}}, - {1152, {wxBrush, new_0, 0}}, - {1153, {wxBrush, new_2, 2}}, - {1154, {wxBrush, new_1, 1}}, - {1156, {wxBrush, destruct, 0}}, - {1157, {wxBrush, getColour, 0}}, - {1158, {wxBrush, getStipple, 0}}, - {1159, {wxBrush, getStyle, 0}}, - {1160, {wxBrush, isHatch, 0}}, - {1161, {wxBrush, isOk, 0}}, - {1162, {wxBrush, setColour_1, 1}}, - {1163, {wxBrush, setColour_3, 3}}, - {1164, {wxBrush, setStipple, 1}}, - {1165, {wxBrush, setStyle, 1}}, - {1166, {wxPen, new_0, 0}}, - {1167, {wxPen, new_2, 2}}, - {1168, {wxPen, destruct, 0}}, - {1169, {wxPen, getCap, 0}}, - {1170, {wxPen, getColour, 0}}, - {1171, {wxPen, getJoin, 0}}, - {1172, {wxPen, getStyle, 0}}, - {1173, {wxPen, getWidth, 0}}, - {1174, {wxPen, isOk, 0}}, - {1175, {wxPen, setCap, 1}}, - {1176, {wxPen, setColour_1, 1}}, - {1177, {wxPen, setColour_3, 3}}, - {1178, {wxPen, setJoin, 1}}, - {1179, {wxPen, setStyle, 1}}, - {1180, {wxPen, setWidth, 1}}, - {1181, {wxRegion, new_0, 0}}, - {1182, {wxRegion, new_4, 4}}, - {1183, {wxRegion, new_2, 2}}, - {1184, {wxRegion, new_1_1, 1}}, - {1186, {wxRegion, new_1_0, 1}}, - {1188, {wxRegion, destruct, 0}}, - {1189, {wxRegion, clear, 0}}, - {1190, {wxRegion, contains_2, 2}}, - {1191, {wxRegion, contains_1_0, 1}}, - {1192, {wxRegion, contains_4, 4}}, - {1193, {wxRegion, contains_1_1, 1}}, - {1194, {wxRegion, convertToBitmap, 0}}, - {1195, {wxRegion, getBox, 0}}, - {1196, {wxRegion, intersect_4, 4}}, - {1197, {wxRegion, intersect_1_1, 1}}, - {1198, {wxRegion, intersect_1_0, 1}}, - {1199, {wxRegion, isEmpty, 0}}, - {1200, {wxRegion, subtract_4, 4}}, - {1201, {wxRegion, subtract_1_1, 1}}, - {1202, {wxRegion, subtract_1_0, 1}}, - {1203, {wxRegion, offset_2, 2}}, - {1204, {wxRegion, offset_1, 1}}, - {1205, {wxRegion, union_4, 4}}, - {1206, {wxRegion, union_1_2, 1}}, - {1207, {wxRegion, union_1_1, 1}}, - {1208, {wxRegion, union_1_0, 1}}, - {1209, {wxRegion, union_3, 3}}, - {1210, {wxRegion, xor_4, 4}}, - {1211, {wxRegion, xor_1_1, 1}}, - {1212, {wxRegion, xor_1_0, 1}}, - {1213, {wxAcceleratorTable, new_0, 0}}, - {1214, {wxAcceleratorTable, new_2, 2}}, - {1215, {wxAcceleratorTable, destruct, 0}}, - {1216, {wxAcceleratorTable, ok, 0}}, - {1217, {wxAcceleratorEntry, new_1_0, 1}}, - {1218, {wxAcceleratorEntry, new_1_1, 1}}, - {1219, {wxAcceleratorEntry, getCommand, 0}}, - {1220, {wxAcceleratorEntry, getFlags, 0}}, - {1221, {wxAcceleratorEntry, getKeyCode, 0}}, - {1222, {wxAcceleratorEntry, set, 4}}, - {1223, {wxAcceleratorEntry, 'Destroy', undefined}}, - {1228, {wxCaret, new_3, 3}}, - {1229, {wxCaret, new_2, 2}}, - {1231, {wxCaret, destruct, 0}}, - {1232, {wxCaret, create_3, 3}}, - {1233, {wxCaret, create_2, 2}}, - {1234, {wxCaret, getBlinkTime, 0}}, - {1236, {wxCaret, getPosition, 0}}, - {1238, {wxCaret, getSize, 0}}, - {1239, {wxCaret, getWindow, 0}}, - {1240, {wxCaret, hide, 0}}, - {1241, {wxCaret, isOk, 0}}, - {1242, {wxCaret, isVisible, 0}}, - {1243, {wxCaret, move_2, 2}}, - {1244, {wxCaret, move_1, 1}}, - {1245, {wxCaret, setBlinkTime, 1}}, - {1246, {wxCaret, setSize_2, 2}}, - {1247, {wxCaret, setSize_1, 1}}, - {1248, {wxCaret, show, 1}}, - {1249, {wxSizer, add_2_1, 2}}, - {1250, {wxSizer, add_2_0, 2}}, - {1251, {wxSizer, add_3, 3}}, - {1252, {wxSizer, add_2_3, 2}}, - {1253, {wxSizer, add_2_2, 2}}, - {1254, {wxSizer, addSpacer, 1}}, - {1255, {wxSizer, addStretchSpacer, 1}}, - {1256, {wxSizer, calcMin, 0}}, - {1257, {wxSizer, clear, 1}}, - {1258, {wxSizer, detach_1_2, 1}}, - {1259, {wxSizer, detach_1_1, 1}}, - {1260, {wxSizer, detach_1_0, 1}}, - {1261, {wxSizer, fit, 1}}, - {1262, {wxSizer, fitInside, 1}}, - {1263, {wxSizer, getChildren, 0}}, - {1264, {wxSizer, getItem_2_1, 2}}, - {1265, {wxSizer, getItem_2_0, 2}}, - {1266, {wxSizer, getItem_1, 1}}, - {1267, {wxSizer, getSize, 0}}, - {1268, {wxSizer, getPosition, 0}}, - {1269, {wxSizer, getMinSize, 0}}, - {1270, {wxSizer, hide_2_0, 2}}, - {1271, {wxSizer, hide_2_1, 2}}, - {1272, {wxSizer, hide_1, 1}}, - {1273, {wxSizer, insert_3_1, 3}}, - {1274, {wxSizer, insert_3_0, 3}}, - {1275, {wxSizer, insert_4, 4}}, - {1276, {wxSizer, insert_3_3, 3}}, - {1277, {wxSizer, insert_3_2, 3}}, - {1278, {wxSizer, insert_2, 2}}, - {1279, {wxSizer, insertSpacer, 2}}, - {1280, {wxSizer, insertStretchSpacer, 2}}, - {1281, {wxSizer, isShown_1_2, 1}}, - {1282, {wxSizer, isShown_1_1, 1}}, - {1283, {wxSizer, isShown_1_0, 1}}, - {1284, {wxSizer, layout, 0}}, - {1285, {wxSizer, prepend_2_1, 2}}, - {1286, {wxSizer, prepend_2_0, 2}}, - {1287, {wxSizer, prepend_3, 3}}, - {1288, {wxSizer, prepend_2_3, 2}}, - {1289, {wxSizer, prepend_2_2, 2}}, - {1290, {wxSizer, prepend_1, 1}}, - {1291, {wxSizer, prependSpacer, 1}}, - {1292, {wxSizer, prependStretchSpacer, 1}}, - {1293, {wxSizer, recalcSizes, 0}}, - {1294, {wxSizer, remove_1_1, 1}}, - {1295, {wxSizer, remove_1_0, 1}}, - {1296, {wxSizer, replace_3_1, 3}}, - {1297, {wxSizer, replace_3_0, 3}}, - {1298, {wxSizer, replace_2, 2}}, - {1299, {wxSizer, setDimension, 4}}, - {1300, {wxSizer, setMinSize_2, 2}}, - {1301, {wxSizer, setMinSize_1, 1}}, - {1302, {wxSizer, setItemMinSize_3_2, 3}}, - {1303, {wxSizer, setItemMinSize_2_2, 2}}, - {1304, {wxSizer, setItemMinSize_3_1, 3}}, - {1305, {wxSizer, setItemMinSize_2_1, 2}}, - {1306, {wxSizer, setItemMinSize_3_0, 3}}, - {1307, {wxSizer, setItemMinSize_2_0, 2}}, - {1308, {wxSizer, setSizeHints, 1}}, - {1309, {wxSizer, setVirtualSizeHints, 1}}, - {1310, {wxSizer, show_2_2, 2}}, - {1311, {wxSizer, show_2_1, 2}}, - {1312, {wxSizer, show_2_0, 2}}, - {1313, {wxSizer, show_1, 1}}, - {1314, {wxSizerFlags, new, 1}}, - {1315, {wxSizerFlags, align, 1}}, - {1316, {wxSizerFlags, border_2, 2}}, - {1317, {wxSizerFlags, border_1, 1}}, - {1318, {wxSizerFlags, center, 0}}, - {1319, {wxSizerFlags, centre, 0}}, - {1320, {wxSizerFlags, expand, 0}}, - {1321, {wxSizerFlags, left, 0}}, - {1322, {wxSizerFlags, proportion, 1}}, - {1323, {wxSizerFlags, right, 0}}, - {1324, {wxSizerFlags, 'Destroy', undefined}}, - {1325, {wxSizerItem, new_5_1, 5}}, - {1326, {wxSizerItem, new_2_1, 2}}, - {1327, {wxSizerItem, new_5_0, 5}}, - {1328, {wxSizerItem, new_2_0, 2}}, - {1329, {wxSizerItem, new_6, 6}}, - {1330, {wxSizerItem, new_3, 3}}, - {1331, {wxSizerItem, new_0, 0}}, - {1332, {wxSizerItem, destruct, 0}}, - {1333, {wxSizerItem, calcMin, 0}}, - {1334, {wxSizerItem, deleteWindows, 0}}, - {1335, {wxSizerItem, detachSizer, 0}}, - {1336, {wxSizerItem, getBorder, 0}}, - {1337, {wxSizerItem, getFlag, 0}}, - {1338, {wxSizerItem, getMinSize, 0}}, - {1339, {wxSizerItem, getPosition, 0}}, - {1340, {wxSizerItem, getProportion, 0}}, - {1341, {wxSizerItem, getRatio, 0}}, - {1342, {wxSizerItem, getRect, 0}}, - {1343, {wxSizerItem, getSize, 0}}, - {1344, {wxSizerItem, getSizer, 0}}, - {1345, {wxSizerItem, getSpacer, 0}}, - {1346, {wxSizerItem, getUserData, 0}}, - {1347, {wxSizerItem, getWindow, 0}}, - {1348, {wxSizerItem, isSizer, 0}}, - {1349, {wxSizerItem, isShown, 0}}, - {1350, {wxSizerItem, isSpacer, 0}}, - {1351, {wxSizerItem, isWindow, 0}}, - {1352, {wxSizerItem, setBorder, 1}}, - {1353, {wxSizerItem, setDimension, 2}}, - {1354, {wxSizerItem, setFlag, 1}}, - {1355, {wxSizerItem, setInitSize, 2}}, - {1356, {wxSizerItem, setMinSize_1, 1}}, - {1357, {wxSizerItem, setMinSize_2, 2}}, - {1358, {wxSizerItem, setProportion, 1}}, - {1359, {wxSizerItem, setRatio_2, 2}}, - {1360, {wxSizerItem, setRatio_1_1, 1}}, - {1361, {wxSizerItem, setRatio_1_0, 1}}, - {1362, {wxSizerItem, setSizer, 1}}, - {1363, {wxSizerItem, setSpacer_1, 1}}, - {1364, {wxSizerItem, setSpacer_2, 2}}, - {1365, {wxSizerItem, setWindow, 1}}, - {1366, {wxSizerItem, show, 1}}, - {1367, {wxBoxSizer, new, 1}}, - {1368, {wxBoxSizer, getOrientation, 0}}, - {1369, {wxBoxSizer, 'Destroy', undefined}}, - {1370, {wxStaticBoxSizer, new_2, 2}}, - {1371, {wxStaticBoxSizer, new_3, 3}}, - {1372, {wxStaticBoxSizer, getStaticBox, 0}}, - {1373, {wxStaticBoxSizer, 'Destroy', undefined}}, - {1374, {wxGridSizer, new_4, 4}}, - {1375, {wxGridSizer, new_2, 2}}, - {1376, {wxGridSizer, getCols, 0}}, - {1377, {wxGridSizer, getHGap, 0}}, - {1378, {wxGridSizer, getRows, 0}}, - {1379, {wxGridSizer, getVGap, 0}}, - {1380, {wxGridSizer, setCols, 1}}, - {1381, {wxGridSizer, setHGap, 1}}, - {1382, {wxGridSizer, setRows, 1}}, - {1383, {wxGridSizer, setVGap, 1}}, - {1384, {wxGridSizer, 'Destroy', undefined}}, - {1385, {wxFlexGridSizer, new_4, 4}}, - {1386, {wxFlexGridSizer, new_2, 2}}, - {1387, {wxFlexGridSizer, addGrowableCol, 2}}, - {1388, {wxFlexGridSizer, addGrowableRow, 2}}, - {1389, {wxFlexGridSizer, getFlexibleDirection, 0}}, - {1390, {wxFlexGridSizer, getNonFlexibleGrowMode, 0}}, - {1391, {wxFlexGridSizer, removeGrowableCol, 1}}, - {1392, {wxFlexGridSizer, removeGrowableRow, 1}}, - {1393, {wxFlexGridSizer, setFlexibleDirection, 1}}, - {1394, {wxFlexGridSizer, setNonFlexibleGrowMode, 1}}, - {1395, {wxFlexGridSizer, 'Destroy', undefined}}, - {1396, {wxGridBagSizer, new, 1}}, - {1397, {wxGridBagSizer, add_3_2, 3}}, - {1398, {wxGridBagSizer, add_3_1, 3}}, - {1399, {wxGridBagSizer, add_4, 4}}, - {1400, {wxGridBagSizer, add_1_0, 1}}, - {1401, {wxGridBagSizer, add_2_1, 2}}, - {1402, {wxGridBagSizer, add_2_0, 2}}, - {1403, {wxGridBagSizer, add_3_0, 3}}, - {1404, {wxGridBagSizer, add_1_1, 1}}, - {1405, {wxGridBagSizer, calcMin, 0}}, - {1406, {wxGridBagSizer, checkForIntersection_2, 2}}, - {1407, {wxGridBagSizer, checkForIntersection_3, 3}}, - {1408, {wxGridBagSizer, findItem_1_1, 1}}, - {1409, {wxGridBagSizer, findItem_1_0, 1}}, - {1410, {wxGridBagSizer, findItemAtPoint, 1}}, - {1411, {wxGridBagSizer, findItemAtPosition, 1}}, - {1412, {wxGridBagSizer, findItemWithData, 1}}, - {1413, {wxGridBagSizer, getCellSize, 2}}, - {1414, {wxGridBagSizer, getEmptyCellSize, 0}}, - {1415, {wxGridBagSizer, getItemPosition_1_2, 1}}, - {1416, {wxGridBagSizer, getItemPosition_1_1, 1}}, - {1417, {wxGridBagSizer, getItemPosition_1_0, 1}}, - {1418, {wxGridBagSizer, getItemSpan_1_2, 1}}, - {1419, {wxGridBagSizer, getItemSpan_1_1, 1}}, - {1420, {wxGridBagSizer, getItemSpan_1_0, 1}}, - {1421, {wxGridBagSizer, setEmptyCellSize, 1}}, - {1422, {wxGridBagSizer, setItemPosition_2_2, 2}}, - {1423, {wxGridBagSizer, setItemPosition_2_1, 2}}, - {1424, {wxGridBagSizer, setItemPosition_2_0, 2}}, - {1425, {wxGridBagSizer, setItemSpan_2_2, 2}}, - {1426, {wxGridBagSizer, setItemSpan_2_1, 2}}, - {1427, {wxGridBagSizer, setItemSpan_2_0, 2}}, - {1428, {wxGridBagSizer, 'Destroy', undefined}}, - {1429, {wxStdDialogButtonSizer, new, 0}}, - {1430, {wxStdDialogButtonSizer, addButton, 1}}, - {1431, {wxStdDialogButtonSizer, realize, 0}}, - {1432, {wxStdDialogButtonSizer, setAffirmativeButton, 1}}, - {1433, {wxStdDialogButtonSizer, setCancelButton, 1}}, - {1434, {wxStdDialogButtonSizer, setNegativeButton, 1}}, - {1435, {wxStdDialogButtonSizer, 'Destroy', undefined}}, - {1436, {wxFont, new_0, 0}}, - {1437, {wxFont, new_1, 1}}, - {1438, {wxFont, new_5, 5}}, - {1440, {wxFont, destruct, 0}}, - {1441, {wxFont, isFixedWidth, 0}}, - {1442, {wxFont, getDefaultEncoding, 0}}, - {1443, {wxFont, getFaceName, 0}}, - {1444, {wxFont, getFamily, 0}}, - {1445, {wxFont, getNativeFontInfoDesc, 0}}, - {1446, {wxFont, getNativeFontInfoUserDesc, 0}}, - {1447, {wxFont, getPointSize, 0}}, - {1448, {wxFont, getStyle, 0}}, - {1449, {wxFont, getUnderlined, 0}}, - {1450, {wxFont, getWeight, 0}}, - {1451, {wxFont, ok, 0}}, - {1452, {wxFont, setDefaultEncoding, 1}}, - {1453, {wxFont, setFaceName, 1}}, - {1454, {wxFont, setFamily, 1}}, - {1455, {wxFont, setPointSize, 1}}, - {1456, {wxFont, setStyle, 1}}, - {1457, {wxFont, setUnderlined, 1}}, - {1458, {wxFont, setWeight, 1}}, - {1459, {wxToolTip, enable, 1}}, - {1460, {wxToolTip, setDelay, 1}}, - {1461, {wxToolTip, new, 1}}, - {1462, {wxToolTip, setTip, 1}}, - {1463, {wxToolTip, getTip, 0}}, - {1464, {wxToolTip, getWindow, 0}}, - {1465, {wxToolTip, 'Destroy', undefined}}, - {1467, {wxButton, new_3, 3}}, - {1468, {wxButton, new_0, 0}}, - {1469, {wxButton, destruct, 0}}, - {1470, {wxButton, create, 3}}, - {1471, {wxButton, getDefaultSize, 0}}, - {1472, {wxButton, setDefault, 0}}, - {1473, {wxButton, setLabel, 1}}, - {1475, {wxBitmapButton, new_4, 4}}, - {1476, {wxBitmapButton, new_0, 0}}, - {1477, {wxBitmapButton, create, 4}}, - {1478, {wxBitmapButton, getBitmapDisabled, 0}}, - {1480, {wxBitmapButton, getBitmapFocus, 0}}, - {1482, {wxBitmapButton, getBitmapLabel, 0}}, - {1484, {wxBitmapButton, getBitmapSelected, 0}}, - {1486, {wxBitmapButton, setBitmapDisabled, 1}}, - {1487, {wxBitmapButton, setBitmapFocus, 1}}, - {1488, {wxBitmapButton, setBitmapLabel, 1}}, - {1489, {wxBitmapButton, setBitmapSelected, 1}}, - {1490, {wxBitmapButton, 'Destroy', undefined}}, - {1491, {wxToggleButton, new_0, 0}}, - {1492, {wxToggleButton, new_4, 4}}, - {1493, {wxToggleButton, create, 4}}, - {1494, {wxToggleButton, getValue, 0}}, - {1495, {wxToggleButton, setValue, 1}}, - {1496, {wxToggleButton, 'Destroy', undefined}}, - {1497, {wxCalendarCtrl, new_0, 0}}, - {1498, {wxCalendarCtrl, new_3, 3}}, - {1499, {wxCalendarCtrl, create, 3}}, - {1500, {wxCalendarCtrl, destruct, 0}}, - {1501, {wxCalendarCtrl, setDate, 1}}, - {1502, {wxCalendarCtrl, getDate, 0}}, - {1503, {wxCalendarCtrl, enableYearChange, 1}}, - {1504, {wxCalendarCtrl, enableMonthChange, 1}}, - {1505, {wxCalendarCtrl, enableHolidayDisplay, 1}}, - {1506, {wxCalendarCtrl, setHeaderColours, 2}}, - {1507, {wxCalendarCtrl, getHeaderColourFg, 0}}, - {1508, {wxCalendarCtrl, getHeaderColourBg, 0}}, - {1509, {wxCalendarCtrl, setHighlightColours, 2}}, - {1510, {wxCalendarCtrl, getHighlightColourFg, 0}}, - {1511, {wxCalendarCtrl, getHighlightColourBg, 0}}, - {1512, {wxCalendarCtrl, setHolidayColours, 2}}, - {1513, {wxCalendarCtrl, getHolidayColourFg, 0}}, - {1514, {wxCalendarCtrl, getHolidayColourBg, 0}}, - {1515, {wxCalendarCtrl, getAttr, 1}}, - {1516, {wxCalendarCtrl, setAttr, 2}}, - {1517, {wxCalendarCtrl, setHoliday, 1}}, - {1518, {wxCalendarCtrl, resetAttr, 1}}, - {1519, {wxCalendarCtrl, hitTest, 2}}, - {1520, {wxCalendarDateAttr, new_0, 0}}, - {1521, {wxCalendarDateAttr, new_2_1, 2}}, - {1522, {wxCalendarDateAttr, new_2_0, 2}}, - {1523, {wxCalendarDateAttr, setTextColour, 1}}, - {1524, {wxCalendarDateAttr, setBackgroundColour, 1}}, - {1525, {wxCalendarDateAttr, setBorderColour, 1}}, - {1526, {wxCalendarDateAttr, setFont, 1}}, - {1527, {wxCalendarDateAttr, setBorder, 1}}, - {1528, {wxCalendarDateAttr, setHoliday, 1}}, - {1529, {wxCalendarDateAttr, hasTextColour, 0}}, - {1530, {wxCalendarDateAttr, hasBackgroundColour, 0}}, - {1531, {wxCalendarDateAttr, hasBorderColour, 0}}, - {1532, {wxCalendarDateAttr, hasFont, 0}}, - {1533, {wxCalendarDateAttr, hasBorder, 0}}, - {1534, {wxCalendarDateAttr, isHoliday, 0}}, - {1535, {wxCalendarDateAttr, getTextColour, 0}}, - {1536, {wxCalendarDateAttr, getBackgroundColour, 0}}, - {1537, {wxCalendarDateAttr, getBorderColour, 0}}, - {1538, {wxCalendarDateAttr, getFont, 0}}, - {1539, {wxCalendarDateAttr, getBorder, 0}}, - {1540, {wxCalendarDateAttr, 'Destroy', undefined}}, - {1542, {wxCheckBox, new_4, 4}}, - {1543, {wxCheckBox, new_0, 0}}, - {1544, {wxCheckBox, create, 4}}, - {1545, {wxCheckBox, getValue, 0}}, - {1546, {wxCheckBox, get3StateValue, 0}}, - {1547, {wxCheckBox, is3rdStateAllowedForUser, 0}}, - {1548, {wxCheckBox, is3State, 0}}, - {1549, {wxCheckBox, isChecked, 0}}, - {1550, {wxCheckBox, setValue, 1}}, - {1551, {wxCheckBox, set3StateValue, 1}}, - {1552, {wxCheckBox, 'Destroy', undefined}}, - {1553, {wxCheckListBox, new_0, 0}}, - {1555, {wxCheckListBox, new_3, 3}}, - {1556, {wxCheckListBox, check, 2}}, - {1557, {wxCheckListBox, isChecked, 1}}, - {1558, {wxCheckListBox, 'Destroy', undefined}}, - {1561, {wxChoice, new_3, 3}}, - {1562, {wxChoice, new_0, 0}}, - {1564, {wxChoice, destruct, 0}}, - {1566, {wxChoice, create, 6}}, - {1567, {wxChoice, delete, 1}}, - {1568, {wxChoice, getColumns, 0}}, - {1569, {wxChoice, setColumns, 1}}, - {1570, {wxComboBox, new_0, 0}}, - {1572, {wxComboBox, new_3, 3}}, - {1573, {wxComboBox, destruct, 0}}, - {1575, {wxComboBox, create, 7}}, - {1576, {wxComboBox, canCopy, 0}}, - {1577, {wxComboBox, canCut, 0}}, - {1578, {wxComboBox, canPaste, 0}}, - {1579, {wxComboBox, canRedo, 0}}, - {1580, {wxComboBox, canUndo, 0}}, - {1581, {wxComboBox, copy, 0}}, - {1582, {wxComboBox, cut, 0}}, - {1583, {wxComboBox, getInsertionPoint, 0}}, - {1584, {wxComboBox, getLastPosition, 0}}, - {1585, {wxComboBox, getValue, 0}}, - {1586, {wxComboBox, paste, 0}}, - {1587, {wxComboBox, redo, 0}}, - {1588, {wxComboBox, replace, 3}}, - {1589, {wxComboBox, remove, 2}}, - {1590, {wxComboBox, setInsertionPoint, 1}}, - {1591, {wxComboBox, setInsertionPointEnd, 0}}, - {1592, {wxComboBox, setSelection_1, 1}}, - {1593, {wxComboBox, setSelection_2, 2}}, - {1594, {wxComboBox, setValue, 1}}, - {1595, {wxComboBox, undo, 0}}, - {1596, {wxGauge, new_0, 0}}, - {1597, {wxGauge, new_4, 4}}, - {1598, {wxGauge, create, 4}}, - {1599, {wxGauge, getBezelFace, 0}}, - {1600, {wxGauge, getRange, 0}}, - {1601, {wxGauge, getShadowWidth, 0}}, - {1602, {wxGauge, getValue, 0}}, - {1603, {wxGauge, isVertical, 0}}, - {1604, {wxGauge, setBezelFace, 1}}, - {1605, {wxGauge, setRange, 1}}, - {1606, {wxGauge, setShadowWidth, 1}}, - {1607, {wxGauge, setValue, 1}}, - {1608, {wxGauge, pulse, 0}}, - {1609, {wxGauge, 'Destroy', undefined}}, - {1610, {wxGenericDirCtrl, new_0, 0}}, - {1611, {wxGenericDirCtrl, new_2, 2}}, - {1612, {wxGenericDirCtrl, destruct, 0}}, - {1613, {wxGenericDirCtrl, create, 2}}, - {1614, {wxGenericDirCtrl, init, 0}}, - {1615, {wxGenericDirCtrl, collapseTree, 0}}, - {1616, {wxGenericDirCtrl, expandPath, 1}}, - {1617, {wxGenericDirCtrl, getDefaultPath, 0}}, - {1618, {wxGenericDirCtrl, getPath, 0}}, - {1619, {wxGenericDirCtrl, getFilePath, 0}}, - {1620, {wxGenericDirCtrl, getFilter, 0}}, - {1621, {wxGenericDirCtrl, getFilterIndex, 0}}, - {1622, {wxGenericDirCtrl, getRootId, 0}}, - {1623, {wxGenericDirCtrl, getTreeCtrl, 0}}, - {1624, {wxGenericDirCtrl, reCreateTree, 0}}, - {1625, {wxGenericDirCtrl, setDefaultPath, 1}}, - {1626, {wxGenericDirCtrl, setFilter, 1}}, - {1627, {wxGenericDirCtrl, setFilterIndex, 1}}, - {1628, {wxGenericDirCtrl, setPath, 1}}, - {1630, {wxStaticBox, new_4, 4}}, - {1631, {wxStaticBox, new_0, 0}}, - {1632, {wxStaticBox, create, 4}}, - {1633, {wxStaticBox, 'Destroy', undefined}}, - {1635, {wxStaticLine, new_2, 2}}, - {1636, {wxStaticLine, new_0, 0}}, - {1637, {wxStaticLine, create, 2}}, - {1638, {wxStaticLine, isVertical, 0}}, - {1639, {wxStaticLine, getDefaultSize, 0}}, - {1640, {wxStaticLine, 'Destroy', undefined}}, - {1643, {wxListBox, new_3, 3}}, - {1644, {wxListBox, new_0, 0}}, - {1646, {wxListBox, destruct, 0}}, - {1648, {wxListBox, create, 6}}, - {1649, {wxListBox, deselect, 1}}, - {1650, {wxListBox, getSelections, 1}}, - {1651, {wxListBox, insertItems, 2}}, - {1652, {wxListBox, isSelected, 1}}, - {1653, {wxListBox, set, 1}}, - {1654, {wxListBox, hitTest, 1}}, - {1655, {wxListBox, setFirstItem_1_0, 1}}, - {1656, {wxListBox, setFirstItem_1_1, 1}}, - {1657, {wxListCtrl, new_0, 0}}, - {1658, {wxListCtrl, new_2, 2}}, - {1659, {wxListCtrl, arrange, 1}}, - {1660, {wxListCtrl, assignImageList, 2}}, - {1661, {wxListCtrl, clearAll, 0}}, - {1662, {wxListCtrl, create, 2}}, - {1663, {wxListCtrl, deleteAllItems, 0}}, - {1664, {wxListCtrl, deleteColumn, 1}}, - {1665, {wxListCtrl, deleteItem, 1}}, - {1666, {wxListCtrl, editLabel, 1}}, - {1667, {wxListCtrl, ensureVisible, 1}}, - {1668, {wxListCtrl, findItem_3_0, 3}}, - {1669, {wxListCtrl, findItem_3_1, 3}}, - {1670, {wxListCtrl, getColumn, 2}}, - {1671, {wxListCtrl, getColumnCount, 0}}, - {1672, {wxListCtrl, getColumnWidth, 1}}, - {1673, {wxListCtrl, getCountPerPage, 0}}, - {1674, {wxListCtrl, getEditControl, 0}}, - {1675, {wxListCtrl, getImageList, 1}}, - {1676, {wxListCtrl, getItem, 1}}, - {1677, {wxListCtrl, getItemBackgroundColour, 1}}, - {1678, {wxListCtrl, getItemCount, 0}}, - {1679, {wxListCtrl, getItemData, 1}}, - {1680, {wxListCtrl, getItemFont, 1}}, - {1681, {wxListCtrl, getItemPosition, 2}}, - {1682, {wxListCtrl, getItemRect, 3}}, - {1683, {wxListCtrl, getItemSpacing, 0}}, - {1684, {wxListCtrl, getItemState, 2}}, - {1685, {wxListCtrl, getItemText, 1}}, - {1686, {wxListCtrl, getItemTextColour, 1}}, - {1687, {wxListCtrl, getNextItem, 2}}, - {1688, {wxListCtrl, getSelectedItemCount, 0}}, - {1689, {wxListCtrl, getTextColour, 0}}, - {1690, {wxListCtrl, getTopItem, 0}}, - {1691, {wxListCtrl, getViewRect, 0}}, - {1692, {wxListCtrl, hitTest, 2}}, - {1693, {wxListCtrl, insertColumn_2, 2}}, - {1694, {wxListCtrl, insertColumn_3, 3}}, - {1695, {wxListCtrl, insertItem_1, 1}}, - {1696, {wxListCtrl, insertItem_2_1, 2}}, - {1697, {wxListCtrl, insertItem_2_0, 2}}, - {1698, {wxListCtrl, insertItem_3, 3}}, - {1699, {wxListCtrl, refreshItem, 1}}, - {1700, {wxListCtrl, refreshItems, 2}}, - {1701, {wxListCtrl, scrollList, 2}}, - {1702, {wxListCtrl, setBackgroundColour, 1}}, - {1703, {wxListCtrl, setColumn, 2}}, - {1704, {wxListCtrl, setColumnWidth, 2}}, - {1705, {wxListCtrl, setImageList, 2}}, - {1706, {wxListCtrl, setItem_1, 1}}, - {1707, {wxListCtrl, setItem_4, 4}}, - {1708, {wxListCtrl, setItemBackgroundColour, 2}}, - {1709, {wxListCtrl, setItemCount, 1}}, - {1710, {wxListCtrl, setItemData, 2}}, - {1711, {wxListCtrl, setItemFont, 2}}, - {1712, {wxListCtrl, setItemImage, 3}}, - {1713, {wxListCtrl, setItemColumnImage, 3}}, - {1714, {wxListCtrl, setItemPosition, 2}}, - {1715, {wxListCtrl, setItemState, 3}}, - {1716, {wxListCtrl, setItemText, 2}}, - {1717, {wxListCtrl, setItemTextColour, 2}}, - {1718, {wxListCtrl, setSingleStyle, 2}}, - {1719, {wxListCtrl, setTextColour, 1}}, - {1720, {wxListCtrl, setWindowStyleFlag, 1}}, - {1721, {wxListCtrl, sortItems, 2}}, - {1722, {wxListCtrl, 'Destroy', undefined}}, - {1723, {wxListView, clearColumnImage, 1}}, - {1724, {wxListView, focus, 1}}, - {1725, {wxListView, getFirstSelected, 0}}, - {1726, {wxListView, getFocusedItem, 0}}, - {1727, {wxListView, getNextSelected, 1}}, - {1728, {wxListView, isSelected, 1}}, - {1729, {wxListView, select, 2}}, - {1730, {wxListView, setColumnImage, 2}}, - {1731, {wxListItem, new_0, 0}}, - {1732, {wxListItem, new_1, 1}}, - {1733, {wxListItem, destruct, 0}}, - {1734, {wxListItem, clear, 0}}, - {1735, {wxListItem, getAlign, 0}}, - {1736, {wxListItem, getBackgroundColour, 0}}, - {1737, {wxListItem, getColumn, 0}}, - {1738, {wxListItem, getFont, 0}}, - {1739, {wxListItem, getId, 0}}, - {1740, {wxListItem, getImage, 0}}, - {1741, {wxListItem, getMask, 0}}, - {1742, {wxListItem, getState, 0}}, - {1743, {wxListItem, getText, 0}}, - {1744, {wxListItem, getTextColour, 0}}, - {1745, {wxListItem, getWidth, 0}}, - {1746, {wxListItem, setAlign, 1}}, - {1747, {wxListItem, setBackgroundColour, 1}}, - {1748, {wxListItem, setColumn, 1}}, - {1749, {wxListItem, setFont, 1}}, - {1750, {wxListItem, setId, 1}}, - {1751, {wxListItem, setImage, 1}}, - {1752, {wxListItem, setMask, 1}}, - {1753, {wxListItem, setState, 1}}, - {1754, {wxListItem, setStateMask, 1}}, - {1755, {wxListItem, setText, 1}}, - {1756, {wxListItem, setTextColour, 1}}, - {1757, {wxListItem, setWidth, 1}}, - {1758, {wxListItemAttr, new_0, 0}}, - {1759, {wxListItemAttr, new_3, 3}}, - {1760, {wxListItemAttr, getBackgroundColour, 0}}, - {1761, {wxListItemAttr, getFont, 0}}, - {1762, {wxListItemAttr, getTextColour, 0}}, - {1763, {wxListItemAttr, hasBackgroundColour, 0}}, - {1764, {wxListItemAttr, hasFont, 0}}, - {1765, {wxListItemAttr, hasTextColour, 0}}, - {1766, {wxListItemAttr, setBackgroundColour, 1}}, - {1767, {wxListItemAttr, setFont, 1}}, - {1768, {wxListItemAttr, setTextColour, 1}}, - {1769, {wxListItemAttr, 'Destroy', undefined}}, - {1770, {wxImageList, new_0, 0}}, - {1771, {wxImageList, new_3, 3}}, - {1772, {wxImageList, add_1, 1}}, - {1773, {wxImageList, add_2_0, 2}}, - {1774, {wxImageList, add_2_1, 2}}, - {1775, {wxImageList, create, 3}}, - {1777, {wxImageList, draw, 5}}, - {1778, {wxImageList, getBitmap, 1}}, - {1779, {wxImageList, getIcon, 1}}, - {1780, {wxImageList, getImageCount, 0}}, - {1781, {wxImageList, getSize, 3}}, - {1782, {wxImageList, remove, 1}}, - {1783, {wxImageList, removeAll, 0}}, - {1784, {wxImageList, replace_2, 2}}, - {1785, {wxImageList, replace_3, 3}}, - {1786, {wxImageList, 'Destroy', undefined}}, - {1787, {wxTextAttr, new_0, 0}}, - {1788, {wxTextAttr, new_2, 2}}, - {1789, {wxTextAttr, getAlignment, 0}}, - {1790, {wxTextAttr, getBackgroundColour, 0}}, - {1791, {wxTextAttr, getFont, 0}}, - {1792, {wxTextAttr, getLeftIndent, 0}}, - {1793, {wxTextAttr, getLeftSubIndent, 0}}, - {1794, {wxTextAttr, getRightIndent, 0}}, - {1795, {wxTextAttr, getTabs, 0}}, - {1796, {wxTextAttr, getTextColour, 0}}, - {1797, {wxTextAttr, hasBackgroundColour, 0}}, - {1798, {wxTextAttr, hasFont, 0}}, - {1799, {wxTextAttr, hasTextColour, 0}}, - {1800, {wxTextAttr, getFlags, 0}}, - {1801, {wxTextAttr, isDefault, 0}}, - {1802, {wxTextAttr, setAlignment, 1}}, - {1803, {wxTextAttr, setBackgroundColour, 1}}, - {1804, {wxTextAttr, setFlags, 1}}, - {1805, {wxTextAttr, setFont, 2}}, - {1806, {wxTextAttr, setLeftIndent, 2}}, - {1807, {wxTextAttr, setRightIndent, 1}}, - {1808, {wxTextAttr, setTabs, 1}}, - {1809, {wxTextAttr, setTextColour, 1}}, - {1810, {wxTextAttr, 'Destroy', undefined}}, - {1812, {wxTextCtrl, new_3, 3}}, - {1813, {wxTextCtrl, new_0, 0}}, - {1815, {wxTextCtrl, destruct, 0}}, - {1816, {wxTextCtrl, appendText, 1}}, - {1817, {wxTextCtrl, canCopy, 0}}, - {1818, {wxTextCtrl, canCut, 0}}, - {1819, {wxTextCtrl, canPaste, 0}}, - {1820, {wxTextCtrl, canRedo, 0}}, - {1821, {wxTextCtrl, canUndo, 0}}, - {1822, {wxTextCtrl, clear, 0}}, - {1823, {wxTextCtrl, copy, 0}}, - {1824, {wxTextCtrl, create, 3}}, - {1825, {wxTextCtrl, cut, 0}}, - {1826, {wxTextCtrl, discardEdits, 0}}, - {1827, {wxTextCtrl, changeValue, 1}}, - {1828, {wxTextCtrl, emulateKeyPress, 1}}, - {1829, {wxTextCtrl, getDefaultStyle, 0}}, - {1830, {wxTextCtrl, getInsertionPoint, 0}}, - {1831, {wxTextCtrl, getLastPosition, 0}}, - {1832, {wxTextCtrl, getLineLength, 1}}, - {1833, {wxTextCtrl, getLineText, 1}}, - {1834, {wxTextCtrl, getNumberOfLines, 0}}, - {1835, {wxTextCtrl, getRange, 2}}, - {1836, {wxTextCtrl, getSelection, 2}}, - {1837, {wxTextCtrl, getStringSelection, 0}}, - {1838, {wxTextCtrl, getStyle, 2}}, - {1839, {wxTextCtrl, getValue, 0}}, - {1840, {wxTextCtrl, isEditable, 0}}, - {1841, {wxTextCtrl, isModified, 0}}, - {1842, {wxTextCtrl, isMultiLine, 0}}, - {1843, {wxTextCtrl, isSingleLine, 0}}, - {1844, {wxTextCtrl, loadFile, 2}}, - {1845, {wxTextCtrl, markDirty, 0}}, - {1846, {wxTextCtrl, paste, 0}}, - {1847, {wxTextCtrl, positionToXY, 3}}, - {1848, {wxTextCtrl, redo, 0}}, - {1849, {wxTextCtrl, remove, 2}}, - {1850, {wxTextCtrl, replace, 3}}, - {1851, {wxTextCtrl, saveFile, 1}}, - {1852, {wxTextCtrl, setDefaultStyle, 1}}, - {1853, {wxTextCtrl, setEditable, 1}}, - {1854, {wxTextCtrl, setInsertionPoint, 1}}, - {1855, {wxTextCtrl, setInsertionPointEnd, 0}}, - {1857, {wxTextCtrl, setMaxLength, 1}}, - {1858, {wxTextCtrl, setSelection, 2}}, - {1859, {wxTextCtrl, setStyle, 3}}, - {1860, {wxTextCtrl, setValue, 1}}, - {1861, {wxTextCtrl, showPosition, 1}}, - {1862, {wxTextCtrl, undo, 0}}, - {1863, {wxTextCtrl, writeText, 1}}, - {1864, {wxTextCtrl, xYToPosition, 2}}, - {1867, {wxNotebook, new_0, 0}}, - {1868, {wxNotebook, new_3, 3}}, - {1869, {wxNotebook, destruct, 0}}, - {1870, {wxNotebook, addPage, 3}}, - {1871, {wxNotebook, advanceSelection, 1}}, - {1872, {wxNotebook, assignImageList, 1}}, - {1873, {wxNotebook, create, 3}}, - {1874, {wxNotebook, deleteAllPages, 0}}, - {1875, {wxNotebook, deletePage, 1}}, - {1876, {wxNotebook, removePage, 1}}, - {1877, {wxNotebook, getCurrentPage, 0}}, - {1878, {wxNotebook, getImageList, 0}}, - {1880, {wxNotebook, getPage, 1}}, - {1881, {wxNotebook, getPageCount, 0}}, - {1882, {wxNotebook, getPageImage, 1}}, - {1883, {wxNotebook, getPageText, 1}}, - {1884, {wxNotebook, getRowCount, 0}}, - {1885, {wxNotebook, getSelection, 0}}, - {1886, {wxNotebook, getThemeBackgroundColour, 0}}, - {1888, {wxNotebook, hitTest, 2}}, - {1890, {wxNotebook, insertPage, 4}}, - {1891, {wxNotebook, setImageList, 1}}, - {1892, {wxNotebook, setPadding, 1}}, - {1893, {wxNotebook, setPageSize, 1}}, - {1894, {wxNotebook, setPageImage, 2}}, - {1895, {wxNotebook, setPageText, 2}}, - {1896, {wxNotebook, setSelection, 1}}, - {1897, {wxNotebook, changeSelection, 1}}, - {1898, {wxChoicebook, new_0, 0}}, - {1899, {wxChoicebook, new_3, 3}}, - {1900, {wxChoicebook, addPage, 3}}, - {1901, {wxChoicebook, advanceSelection, 1}}, - {1902, {wxChoicebook, assignImageList, 1}}, - {1903, {wxChoicebook, create, 3}}, - {1904, {wxChoicebook, deleteAllPages, 0}}, - {1905, {wxChoicebook, deletePage, 1}}, - {1906, {wxChoicebook, removePage, 1}}, - {1907, {wxChoicebook, getCurrentPage, 0}}, - {1908, {wxChoicebook, getImageList, 0}}, - {1910, {wxChoicebook, getPage, 1}}, - {1911, {wxChoicebook, getPageCount, 0}}, - {1912, {wxChoicebook, getPageImage, 1}}, - {1913, {wxChoicebook, getPageText, 1}}, - {1914, {wxChoicebook, getSelection, 0}}, - {1915, {wxChoicebook, hitTest, 2}}, - {1916, {wxChoicebook, insertPage, 4}}, - {1917, {wxChoicebook, setImageList, 1}}, - {1918, {wxChoicebook, setPageSize, 1}}, - {1919, {wxChoicebook, setPageImage, 2}}, - {1920, {wxChoicebook, setPageText, 2}}, - {1921, {wxChoicebook, setSelection, 1}}, - {1922, {wxChoicebook, changeSelection, 1}}, - {1923, {wxChoicebook, 'Destroy', undefined}}, - {1924, {wxToolbook, new_0, 0}}, - {1925, {wxToolbook, new_3, 3}}, - {1926, {wxToolbook, addPage, 3}}, - {1927, {wxToolbook, advanceSelection, 1}}, - {1928, {wxToolbook, assignImageList, 1}}, - {1929, {wxToolbook, create, 3}}, - {1930, {wxToolbook, deleteAllPages, 0}}, - {1931, {wxToolbook, deletePage, 1}}, - {1932, {wxToolbook, removePage, 1}}, - {1933, {wxToolbook, getCurrentPage, 0}}, - {1934, {wxToolbook, getImageList, 0}}, - {1936, {wxToolbook, getPage, 1}}, - {1937, {wxToolbook, getPageCount, 0}}, - {1938, {wxToolbook, getPageImage, 1}}, - {1939, {wxToolbook, getPageText, 1}}, - {1940, {wxToolbook, getSelection, 0}}, - {1942, {wxToolbook, hitTest, 2}}, - {1943, {wxToolbook, insertPage, 4}}, - {1944, {wxToolbook, setImageList, 1}}, - {1945, {wxToolbook, setPageSize, 1}}, - {1946, {wxToolbook, setPageImage, 2}}, - {1947, {wxToolbook, setPageText, 2}}, - {1948, {wxToolbook, setSelection, 1}}, - {1949, {wxToolbook, changeSelection, 1}}, - {1950, {wxToolbook, 'Destroy', undefined}}, - {1951, {wxListbook, new_0, 0}}, - {1952, {wxListbook, new_3, 3}}, - {1953, {wxListbook, addPage, 3}}, - {1954, {wxListbook, advanceSelection, 1}}, - {1955, {wxListbook, assignImageList, 1}}, - {1956, {wxListbook, create, 3}}, - {1957, {wxListbook, deleteAllPages, 0}}, - {1958, {wxListbook, deletePage, 1}}, - {1959, {wxListbook, removePage, 1}}, - {1960, {wxListbook, getCurrentPage, 0}}, - {1961, {wxListbook, getImageList, 0}}, - {1963, {wxListbook, getPage, 1}}, - {1964, {wxListbook, getPageCount, 0}}, - {1965, {wxListbook, getPageImage, 1}}, - {1966, {wxListbook, getPageText, 1}}, - {1967, {wxListbook, getSelection, 0}}, - {1969, {wxListbook, hitTest, 2}}, - {1970, {wxListbook, insertPage, 4}}, - {1971, {wxListbook, setImageList, 1}}, - {1972, {wxListbook, setPageSize, 1}}, - {1973, {wxListbook, setPageImage, 2}}, - {1974, {wxListbook, setPageText, 2}}, - {1975, {wxListbook, setSelection, 1}}, - {1976, {wxListbook, changeSelection, 1}}, - {1977, {wxListbook, 'Destroy', undefined}}, - {1978, {wxTreebook, new_0, 0}}, - {1979, {wxTreebook, new_3, 3}}, - {1980, {wxTreebook, addPage, 3}}, - {1981, {wxTreebook, advanceSelection, 1}}, - {1982, {wxTreebook, assignImageList, 1}}, - {1983, {wxTreebook, create, 3}}, - {1984, {wxTreebook, deleteAllPages, 0}}, - {1985, {wxTreebook, deletePage, 1}}, - {1986, {wxTreebook, removePage, 1}}, - {1987, {wxTreebook, getCurrentPage, 0}}, - {1988, {wxTreebook, getImageList, 0}}, - {1990, {wxTreebook, getPage, 1}}, - {1991, {wxTreebook, getPageCount, 0}}, - {1992, {wxTreebook, getPageImage, 1}}, - {1993, {wxTreebook, getPageText, 1}}, - {1994, {wxTreebook, getSelection, 0}}, - {1995, {wxTreebook, expandNode, 2}}, - {1996, {wxTreebook, isNodeExpanded, 1}}, - {1998, {wxTreebook, hitTest, 2}}, - {1999, {wxTreebook, insertPage, 4}}, - {2000, {wxTreebook, insertSubPage, 4}}, - {2001, {wxTreebook, setImageList, 1}}, - {2002, {wxTreebook, setPageSize, 1}}, - {2003, {wxTreebook, setPageImage, 2}}, - {2004, {wxTreebook, setPageText, 2}}, - {2005, {wxTreebook, setSelection, 1}}, - {2006, {wxTreebook, changeSelection, 1}}, - {2007, {wxTreebook, 'Destroy', undefined}}, - {2010, {wxTreeCtrl, new_2, 2}}, - {2011, {wxTreeCtrl, new_0, 0}}, - {2013, {wxTreeCtrl, destruct, 0}}, - {2014, {wxTreeCtrl, addRoot, 2}}, - {2015, {wxTreeCtrl, appendItem, 3}}, - {2016, {wxTreeCtrl, assignImageList, 1}}, - {2017, {wxTreeCtrl, assignStateImageList, 1}}, - {2018, {wxTreeCtrl, collapse, 1}}, - {2019, {wxTreeCtrl, collapseAndReset, 1}}, - {2020, {wxTreeCtrl, create, 2}}, - {2021, {wxTreeCtrl, delete, 1}}, - {2022, {wxTreeCtrl, deleteAllItems, 0}}, - {2023, {wxTreeCtrl, deleteChildren, 1}}, - {2024, {wxTreeCtrl, editLabel, 1}}, - {2025, {wxTreeCtrl, ensureVisible, 1}}, - {2026, {wxTreeCtrl, expand, 1}}, - {2027, {wxTreeCtrl, getBoundingRect, 3}}, - {2029, {wxTreeCtrl, getChildrenCount, 2}}, - {2030, {wxTreeCtrl, getCount, 0}}, - {2031, {wxTreeCtrl, getEditControl, 0}}, - {2032, {wxTreeCtrl, getFirstChild, 2}}, - {2033, {wxTreeCtrl, getNextChild, 2}}, - {2034, {wxTreeCtrl, getFirstVisibleItem, 0}}, - {2035, {wxTreeCtrl, getImageList, 0}}, - {2036, {wxTreeCtrl, getIndent, 0}}, - {2037, {wxTreeCtrl, getItemBackgroundColour, 1}}, - {2038, {wxTreeCtrl, getItemData, 1}}, - {2039, {wxTreeCtrl, getItemFont, 1}}, - {2040, {wxTreeCtrl, getItemImage_1, 1}}, - {2041, {wxTreeCtrl, getItemImage_2, 2}}, - {2042, {wxTreeCtrl, getItemText, 1}}, - {2043, {wxTreeCtrl, getItemTextColour, 1}}, - {2044, {wxTreeCtrl, getLastChild, 1}}, - {2045, {wxTreeCtrl, getNextSibling, 1}}, - {2046, {wxTreeCtrl, getNextVisible, 1}}, - {2047, {wxTreeCtrl, getItemParent, 1}}, - {2048, {wxTreeCtrl, getPrevSibling, 1}}, - {2049, {wxTreeCtrl, getPrevVisible, 1}}, - {2050, {wxTreeCtrl, getRootItem, 0}}, - {2051, {wxTreeCtrl, getSelection, 0}}, - {2052, {wxTreeCtrl, getSelections, 1}}, - {2053, {wxTreeCtrl, getStateImageList, 0}}, - {2054, {wxTreeCtrl, hitTest, 2}}, - {2056, {wxTreeCtrl, insertItem, 4}}, - {2057, {wxTreeCtrl, isBold, 1}}, - {2058, {wxTreeCtrl, isExpanded, 1}}, - {2059, {wxTreeCtrl, isSelected, 1}}, - {2060, {wxTreeCtrl, isVisible, 1}}, - {2061, {wxTreeCtrl, itemHasChildren, 1}}, - {2062, {wxTreeCtrl, isTreeItemIdOk, 1}}, - {2063, {wxTreeCtrl, prependItem, 3}}, - {2064, {wxTreeCtrl, scrollTo, 1}}, - {2065, {wxTreeCtrl, selectItem_1, 1}}, - {2066, {wxTreeCtrl, selectItem_2, 2}}, - {2067, {wxTreeCtrl, setIndent, 1}}, - {2068, {wxTreeCtrl, setImageList, 1}}, - {2069, {wxTreeCtrl, setItemBackgroundColour, 2}}, - {2070, {wxTreeCtrl, setItemBold, 2}}, - {2071, {wxTreeCtrl, setItemData, 2}}, - {2072, {wxTreeCtrl, setItemDropHighlight, 2}}, - {2073, {wxTreeCtrl, setItemFont, 2}}, - {2074, {wxTreeCtrl, setItemHasChildren, 2}}, - {2075, {wxTreeCtrl, setItemImage_2, 2}}, - {2076, {wxTreeCtrl, setItemImage_3, 3}}, - {2077, {wxTreeCtrl, setItemText, 2}}, - {2078, {wxTreeCtrl, setItemTextColour, 2}}, - {2079, {wxTreeCtrl, setStateImageList, 1}}, - {2080, {wxTreeCtrl, setWindowStyle, 1}}, - {2081, {wxTreeCtrl, sortChildren, 1}}, - {2082, {wxTreeCtrl, toggle, 1}}, - {2083, {wxTreeCtrl, toggleItemSelection, 1}}, - {2084, {wxTreeCtrl, unselect, 0}}, - {2085, {wxTreeCtrl, unselectAll, 0}}, - {2086, {wxTreeCtrl, unselectItem, 1}}, - {2087, {wxScrollBar, new_0, 0}}, - {2088, {wxScrollBar, new_3, 3}}, - {2089, {wxScrollBar, destruct, 0}}, - {2090, {wxScrollBar, create, 3}}, - {2091, {wxScrollBar, getRange, 0}}, - {2092, {wxScrollBar, getPageSize, 0}}, - {2093, {wxScrollBar, getThumbPosition, 0}}, - {2094, {wxScrollBar, getThumbSize, 0}}, - {2095, {wxScrollBar, setThumbPosition, 1}}, - {2096, {wxScrollBar, setScrollbar, 5}}, - {2098, {wxSpinButton, new_2, 2}}, - {2099, {wxSpinButton, new_0, 0}}, - {2100, {wxSpinButton, create, 2}}, - {2101, {wxSpinButton, getMax, 0}}, - {2102, {wxSpinButton, getMin, 0}}, - {2103, {wxSpinButton, getValue, 0}}, - {2104, {wxSpinButton, setRange, 2}}, - {2105, {wxSpinButton, setValue, 1}}, - {2106, {wxSpinButton, 'Destroy', undefined}}, - {2107, {wxSpinCtrl, new_0, 0}}, - {2108, {wxSpinCtrl, new_2, 2}}, - {2110, {wxSpinCtrl, create, 2}}, - {2113, {wxSpinCtrl, setValue_1_1, 1}}, - {2114, {wxSpinCtrl, setValue_1_0, 1}}, - {2116, {wxSpinCtrl, getValue, 0}}, - {2118, {wxSpinCtrl, setRange, 2}}, - {2119, {wxSpinCtrl, setSelection, 2}}, - {2121, {wxSpinCtrl, getMin, 0}}, - {2123, {wxSpinCtrl, getMax, 0}}, - {2124, {wxSpinCtrl, 'Destroy', undefined}}, - {2125, {wxStaticText, new_0, 0}}, - {2126, {wxStaticText, new_4, 4}}, - {2127, {wxStaticText, create, 4}}, - {2128, {wxStaticText, getLabel, 0}}, - {2129, {wxStaticText, setLabel, 1}}, - {2130, {wxStaticText, wrap, 1}}, - {2131, {wxStaticText, 'Destroy', undefined}}, - {2132, {wxStaticBitmap, new_0, 0}}, - {2133, {wxStaticBitmap, new_4, 4}}, - {2134, {wxStaticBitmap, create, 4}}, - {2135, {wxStaticBitmap, getBitmap, 0}}, - {2136, {wxStaticBitmap, setBitmap, 1}}, - {2137, {wxStaticBitmap, 'Destroy', undefined}}, - {2138, {wxRadioBox, new, 7}}, - {2140, {wxRadioBox, destruct, 0}}, - {2141, {wxRadioBox, create, 7}}, - {2142, {wxRadioBox, enable_2, 2}}, - {2143, {wxRadioBox, enable_1, 1}}, - {2144, {wxRadioBox, getSelection, 0}}, - {2145, {wxRadioBox, getString, 1}}, - {2146, {wxRadioBox, setSelection, 1}}, - {2147, {wxRadioBox, show_2, 2}}, - {2148, {wxRadioBox, show_1, 1}}, - {2149, {wxRadioBox, getColumnCount, 0}}, - {2150, {wxRadioBox, getItemHelpText, 1}}, - {2151, {wxRadioBox, getItemToolTip, 1}}, - {2153, {wxRadioBox, getItemFromPoint, 1}}, - {2154, {wxRadioBox, getRowCount, 0}}, - {2155, {wxRadioBox, isItemEnabled, 1}}, - {2156, {wxRadioBox, isItemShown, 1}}, - {2157, {wxRadioBox, setItemHelpText, 2}}, - {2158, {wxRadioBox, setItemToolTip, 2}}, - {2159, {wxRadioButton, new_0, 0}}, - {2160, {wxRadioButton, new_4, 4}}, - {2161, {wxRadioButton, create, 4}}, - {2162, {wxRadioButton, getValue, 0}}, - {2163, {wxRadioButton, setValue, 1}}, - {2164, {wxRadioButton, 'Destroy', undefined}}, - {2166, {wxSlider, new_6, 6}}, - {2167, {wxSlider, new_0, 0}}, - {2168, {wxSlider, create, 6}}, - {2169, {wxSlider, getLineSize, 0}}, - {2170, {wxSlider, getMax, 0}}, - {2171, {wxSlider, getMin, 0}}, - {2172, {wxSlider, getPageSize, 0}}, - {2173, {wxSlider, getThumbLength, 0}}, - {2174, {wxSlider, getValue, 0}}, - {2175, {wxSlider, setLineSize, 1}}, - {2176, {wxSlider, setPageSize, 1}}, - {2177, {wxSlider, setRange, 2}}, - {2178, {wxSlider, setThumbLength, 1}}, - {2179, {wxSlider, setValue, 1}}, - {2180, {wxSlider, 'Destroy', undefined}}, - {2182, {wxDialog, new_4, 4}}, - {2183, {wxDialog, new_0, 0}}, - {2185, {wxDialog, destruct, 0}}, - {2186, {wxDialog, create, 4}}, - {2187, {wxDialog, createButtonSizer, 1}}, - {2188, {wxDialog, createStdDialogButtonSizer, 1}}, - {2189, {wxDialog, endModal, 1}}, - {2190, {wxDialog, getAffirmativeId, 0}}, - {2191, {wxDialog, getReturnCode, 0}}, - {2192, {wxDialog, isModal, 0}}, - {2193, {wxDialog, setAffirmativeId, 1}}, - {2194, {wxDialog, setReturnCode, 1}}, - {2195, {wxDialog, show, 1}}, - {2196, {wxDialog, showModal, 0}}, - {2197, {wxColourDialog, new_0, 0}}, - {2198, {wxColourDialog, new_2, 2}}, - {2199, {wxColourDialog, destruct, 0}}, - {2200, {wxColourDialog, create, 2}}, - {2201, {wxColourDialog, getColourData, 0}}, - {2202, {wxColourData, new_0, 0}}, - {2203, {wxColourData, new_1, 1}}, - {2204, {wxColourData, destruct, 0}}, - {2205, {wxColourData, getChooseFull, 0}}, - {2206, {wxColourData, getColour, 0}}, - {2208, {wxColourData, getCustomColour, 1}}, - {2209, {wxColourData, setChooseFull, 1}}, - {2210, {wxColourData, setColour, 1}}, - {2211, {wxColourData, setCustomColour, 2}}, - {2212, {wxPalette, new_0, 0}}, - {2213, {wxPalette, new_4, 4}}, - {2215, {wxPalette, destruct, 0}}, - {2216, {wxPalette, create, 4}}, - {2217, {wxPalette, getColoursCount, 0}}, - {2218, {wxPalette, getPixel, 3}}, - {2219, {wxPalette, getRGB, 4}}, - {2220, {wxPalette, isOk, 0}}, - {2224, {wxDirDialog, new, 2}}, - {2225, {wxDirDialog, destruct, 0}}, - {2226, {wxDirDialog, getPath, 0}}, - {2227, {wxDirDialog, getMessage, 0}}, - {2228, {wxDirDialog, setMessage, 1}}, - {2229, {wxDirDialog, setPath, 1}}, - {2233, {wxFileDialog, new, 2}}, - {2234, {wxFileDialog, destruct, 0}}, - {2235, {wxFileDialog, getDirectory, 0}}, - {2236, {wxFileDialog, getFilename, 0}}, - {2237, {wxFileDialog, getFilenames, 1}}, - {2238, {wxFileDialog, getFilterIndex, 0}}, - {2239, {wxFileDialog, getMessage, 0}}, - {2240, {wxFileDialog, getPath, 0}}, - {2241, {wxFileDialog, getPaths, 1}}, - {2242, {wxFileDialog, getWildcard, 0}}, - {2243, {wxFileDialog, setDirectory, 1}}, - {2244, {wxFileDialog, setFilename, 1}}, - {2245, {wxFileDialog, setFilterIndex, 1}}, - {2246, {wxFileDialog, setMessage, 1}}, - {2247, {wxFileDialog, setPath, 1}}, - {2248, {wxFileDialog, setWildcard, 1}}, - {2249, {wxPickerBase, setInternalMargin, 1}}, - {2250, {wxPickerBase, getInternalMargin, 0}}, - {2251, {wxPickerBase, setTextCtrlProportion, 1}}, - {2252, {wxPickerBase, setPickerCtrlProportion, 1}}, - {2253, {wxPickerBase, getTextCtrlProportion, 0}}, - {2254, {wxPickerBase, getPickerCtrlProportion, 0}}, - {2255, {wxPickerBase, hasTextCtrl, 0}}, - {2256, {wxPickerBase, getTextCtrl, 0}}, - {2257, {wxPickerBase, isTextCtrlGrowable, 0}}, - {2258, {wxPickerBase, setPickerCtrlGrowable, 1}}, - {2259, {wxPickerBase, setTextCtrlGrowable, 1}}, - {2260, {wxPickerBase, isPickerCtrlGrowable, 0}}, - {2261, {wxFilePickerCtrl, new_0, 0}}, - {2262, {wxFilePickerCtrl, new_3, 3}}, - {2263, {wxFilePickerCtrl, create, 3}}, - {2264, {wxFilePickerCtrl, getPath, 0}}, - {2265, {wxFilePickerCtrl, setPath, 1}}, - {2266, {wxFilePickerCtrl, 'Destroy', undefined}}, - {2267, {wxDirPickerCtrl, new_0, 0}}, - {2268, {wxDirPickerCtrl, new_3, 3}}, - {2269, {wxDirPickerCtrl, create, 3}}, - {2270, {wxDirPickerCtrl, getPath, 0}}, - {2271, {wxDirPickerCtrl, setPath, 1}}, - {2272, {wxDirPickerCtrl, 'Destroy', undefined}}, - {2273, {wxColourPickerCtrl, new_0, 0}}, - {2274, {wxColourPickerCtrl, new_3, 3}}, - {2275, {wxColourPickerCtrl, create, 3}}, - {2276, {wxColourPickerCtrl, getColour, 0}}, - {2277, {wxColourPickerCtrl, setColour_1_1, 1}}, - {2278, {wxColourPickerCtrl, setColour_1_0, 1}}, - {2279, {wxColourPickerCtrl, 'Destroy', undefined}}, - {2280, {wxDatePickerCtrl, new_0, 0}}, - {2281, {wxDatePickerCtrl, new_3, 3}}, - {2282, {wxDatePickerCtrl, getRange, 2}}, - {2283, {wxDatePickerCtrl, getValue, 0}}, - {2284, {wxDatePickerCtrl, setRange, 2}}, - {2285, {wxDatePickerCtrl, setValue, 1}}, - {2286, {wxDatePickerCtrl, 'Destroy', undefined}}, - {2287, {wxFontPickerCtrl, new_0, 0}}, - {2288, {wxFontPickerCtrl, new_3, 3}}, - {2289, {wxFontPickerCtrl, create, 3}}, - {2290, {wxFontPickerCtrl, getSelectedFont, 0}}, - {2291, {wxFontPickerCtrl, setSelectedFont, 1}}, - {2292, {wxFontPickerCtrl, getMaxPointSize, 0}}, - {2293, {wxFontPickerCtrl, setMaxPointSize, 1}}, - {2294, {wxFontPickerCtrl, 'Destroy', undefined}}, - {2297, {wxFindReplaceDialog, new_0, 0}}, - {2298, {wxFindReplaceDialog, new_4, 4}}, - {2299, {wxFindReplaceDialog, destruct, 0}}, - {2300, {wxFindReplaceDialog, create, 4}}, - {2301, {wxFindReplaceDialog, getData, 0}}, - {2302, {wxFindReplaceData, new_0, 0}}, - {2303, {wxFindReplaceData, new_1, 1}}, - {2304, {wxFindReplaceData, getFindString, 0}}, - {2305, {wxFindReplaceData, getReplaceString, 0}}, - {2306, {wxFindReplaceData, getFlags, 0}}, - {2307, {wxFindReplaceData, setFlags, 1}}, - {2308, {wxFindReplaceData, setFindString, 1}}, - {2309, {wxFindReplaceData, setReplaceString, 1}}, - {2310, {wxFindReplaceData, 'Destroy', undefined}}, - {2311, {wxMultiChoiceDialog, new_0, 0}}, - {2313, {wxMultiChoiceDialog, new_5, 5}}, - {2314, {wxMultiChoiceDialog, getSelections, 0}}, - {2315, {wxMultiChoiceDialog, setSelections, 1}}, - {2316, {wxMultiChoiceDialog, 'Destroy', undefined}}, - {2317, {wxSingleChoiceDialog, new_0, 0}}, - {2319, {wxSingleChoiceDialog, new_5, 5}}, - {2320, {wxSingleChoiceDialog, getSelection, 0}}, - {2321, {wxSingleChoiceDialog, getStringSelection, 0}}, - {2322, {wxSingleChoiceDialog, setSelection, 1}}, - {2323, {wxSingleChoiceDialog, 'Destroy', undefined}}, - {2324, {wxTextEntryDialog, new, 3}}, - {2325, {wxTextEntryDialog, getValue, 0}}, - {2326, {wxTextEntryDialog, setValue, 1}}, - {2327, {wxTextEntryDialog, 'Destroy', undefined}}, - {2328, {wxPasswordEntryDialog, new, 3}}, - {2329, {wxPasswordEntryDialog, 'Destroy', undefined}}, - {2330, {wxFontData, new_0, 0}}, - {2331, {wxFontData, new_1, 1}}, - {2332, {wxFontData, destruct, 0}}, - {2333, {wxFontData, enableEffects, 1}}, - {2334, {wxFontData, getAllowSymbols, 0}}, - {2335, {wxFontData, getColour, 0}}, - {2336, {wxFontData, getChosenFont, 0}}, - {2337, {wxFontData, getEnableEffects, 0}}, - {2338, {wxFontData, getInitialFont, 0}}, - {2339, {wxFontData, getShowHelp, 0}}, - {2340, {wxFontData, setAllowSymbols, 1}}, - {2341, {wxFontData, setChosenFont, 1}}, - {2342, {wxFontData, setColour, 1}}, - {2343, {wxFontData, setInitialFont, 1}}, - {2344, {wxFontData, setRange, 2}}, - {2345, {wxFontData, setShowHelp, 1}}, - {2349, {wxFontDialog, new_0, 0}}, - {2351, {wxFontDialog, new_2, 2}}, - {2353, {wxFontDialog, create, 2}}, - {2354, {wxFontDialog, getFontData, 0}}, - {2356, {wxFontDialog, 'Destroy', undefined}}, - {2357, {wxProgressDialog, new, 3}}, - {2358, {wxProgressDialog, destruct, 0}}, - {2359, {wxProgressDialog, resume, 0}}, - {2360, {wxProgressDialog, update_2, 2}}, - {2361, {wxProgressDialog, update_0, 0}}, - {2362, {wxMessageDialog, new, 3}}, - {2363, {wxMessageDialog, destruct, 0}}, - {2364, {wxPageSetupDialog, new, 2}}, - {2365, {wxPageSetupDialog, destruct, 0}}, - {2366, {wxPageSetupDialog, getPageSetupData, 0}}, - {2367, {wxPageSetupDialog, showModal, 0}}, - {2368, {wxPageSetupDialogData, new_0, 0}}, - {2369, {wxPageSetupDialogData, new_1_0, 1}}, - {2370, {wxPageSetupDialogData, new_1_1, 1}}, - {2371, {wxPageSetupDialogData, destruct, 0}}, - {2372, {wxPageSetupDialogData, enableHelp, 1}}, - {2373, {wxPageSetupDialogData, enableMargins, 1}}, - {2374, {wxPageSetupDialogData, enableOrientation, 1}}, - {2375, {wxPageSetupDialogData, enablePaper, 1}}, - {2376, {wxPageSetupDialogData, enablePrinter, 1}}, - {2377, {wxPageSetupDialogData, getDefaultMinMargins, 0}}, - {2378, {wxPageSetupDialogData, getEnableMargins, 0}}, - {2379, {wxPageSetupDialogData, getEnableOrientation, 0}}, - {2380, {wxPageSetupDialogData, getEnablePaper, 0}}, - {2381, {wxPageSetupDialogData, getEnablePrinter, 0}}, - {2382, {wxPageSetupDialogData, getEnableHelp, 0}}, - {2383, {wxPageSetupDialogData, getDefaultInfo, 0}}, - {2384, {wxPageSetupDialogData, getMarginTopLeft, 0}}, - {2385, {wxPageSetupDialogData, getMarginBottomRight, 0}}, - {2386, {wxPageSetupDialogData, getMinMarginTopLeft, 0}}, - {2387, {wxPageSetupDialogData, getMinMarginBottomRight, 0}}, - {2388, {wxPageSetupDialogData, getPaperId, 0}}, - {2389, {wxPageSetupDialogData, getPaperSize, 0}}, - {2391, {wxPageSetupDialogData, getPrintData, 0}}, - {2392, {wxPageSetupDialogData, isOk, 0}}, - {2393, {wxPageSetupDialogData, setDefaultInfo, 1}}, - {2394, {wxPageSetupDialogData, setDefaultMinMargins, 1}}, - {2395, {wxPageSetupDialogData, setMarginTopLeft, 1}}, - {2396, {wxPageSetupDialogData, setMarginBottomRight, 1}}, - {2397, {wxPageSetupDialogData, setMinMarginTopLeft, 1}}, - {2398, {wxPageSetupDialogData, setMinMarginBottomRight, 1}}, - {2399, {wxPageSetupDialogData, setPaperId, 1}}, - {2400, {wxPageSetupDialogData, setPaperSize_1_1, 1}}, - {2401, {wxPageSetupDialogData, setPaperSize_1_0, 1}}, - {2402, {wxPageSetupDialogData, setPrintData, 1}}, - {2403, {wxPrintDialog, new_2_0, 2}}, - {2404, {wxPrintDialog, new_2_1, 2}}, - {2405, {wxPrintDialog, destruct, 0}}, - {2406, {wxPrintDialog, getPrintDialogData, 0}}, - {2407, {wxPrintDialog, getPrintDC, 0}}, - {2408, {wxPrintDialogData, new_0, 0}}, - {2409, {wxPrintDialogData, new_1_1, 1}}, - {2410, {wxPrintDialogData, new_1_0, 1}}, - {2411, {wxPrintDialogData, destruct, 0}}, - {2412, {wxPrintDialogData, enableHelp, 1}}, - {2413, {wxPrintDialogData, enablePageNumbers, 1}}, - {2414, {wxPrintDialogData, enablePrintToFile, 1}}, - {2415, {wxPrintDialogData, enableSelection, 1}}, - {2416, {wxPrintDialogData, getAllPages, 0}}, - {2417, {wxPrintDialogData, getCollate, 0}}, - {2418, {wxPrintDialogData, getFromPage, 0}}, - {2419, {wxPrintDialogData, getMaxPage, 0}}, - {2420, {wxPrintDialogData, getMinPage, 0}}, - {2421, {wxPrintDialogData, getNoCopies, 0}}, - {2422, {wxPrintDialogData, getPrintData, 0}}, - {2423, {wxPrintDialogData, getPrintToFile, 0}}, - {2424, {wxPrintDialogData, getSelection, 0}}, - {2425, {wxPrintDialogData, getToPage, 0}}, - {2426, {wxPrintDialogData, isOk, 0}}, - {2427, {wxPrintDialogData, setCollate, 1}}, - {2428, {wxPrintDialogData, setFromPage, 1}}, - {2429, {wxPrintDialogData, setMaxPage, 1}}, - {2430, {wxPrintDialogData, setMinPage, 1}}, - {2431, {wxPrintDialogData, setNoCopies, 1}}, - {2432, {wxPrintDialogData, setPrintData, 1}}, - {2433, {wxPrintDialogData, setPrintToFile, 1}}, - {2434, {wxPrintDialogData, setSelection, 1}}, - {2435, {wxPrintDialogData, setToPage, 1}}, - {2436, {wxPrintData, new_0, 0}}, - {2437, {wxPrintData, new_1, 1}}, - {2438, {wxPrintData, destruct, 0}}, - {2439, {wxPrintData, getCollate, 0}}, - {2440, {wxPrintData, getBin, 0}}, - {2441, {wxPrintData, getColour, 0}}, - {2442, {wxPrintData, getDuplex, 0}}, - {2443, {wxPrintData, getNoCopies, 0}}, - {2444, {wxPrintData, getOrientation, 0}}, - {2445, {wxPrintData, getPaperId, 0}}, - {2446, {wxPrintData, getPrinterName, 0}}, - {2447, {wxPrintData, getQuality, 0}}, - {2448, {wxPrintData, isOk, 0}}, - {2449, {wxPrintData, setBin, 1}}, - {2450, {wxPrintData, setCollate, 1}}, - {2451, {wxPrintData, setColour, 1}}, - {2452, {wxPrintData, setDuplex, 1}}, - {2453, {wxPrintData, setNoCopies, 1}}, - {2454, {wxPrintData, setOrientation, 1}}, - {2455, {wxPrintData, setPaperId, 1}}, - {2456, {wxPrintData, setPrinterName, 1}}, - {2457, {wxPrintData, setQuality, 1}}, - {2460, {wxPrintPreview, new_2, 2}}, - {2461, {wxPrintPreview, new_3, 3}}, - {2463, {wxPrintPreview, destruct, 0}}, - {2464, {wxPrintPreview, getCanvas, 0}}, - {2465, {wxPrintPreview, getCurrentPage, 0}}, - {2466, {wxPrintPreview, getFrame, 0}}, - {2467, {wxPrintPreview, getMaxPage, 0}}, - {2468, {wxPrintPreview, getMinPage, 0}}, - {2469, {wxPrintPreview, getPrintout, 0}}, - {2470, {wxPrintPreview, getPrintoutForPrinting, 0}}, - {2471, {wxPrintPreview, isOk, 0}}, - {2472, {wxPrintPreview, paintPage, 2}}, - {2473, {wxPrintPreview, print, 1}}, - {2474, {wxPrintPreview, renderPage, 1}}, - {2475, {wxPrintPreview, setCanvas, 1}}, - {2476, {wxPrintPreview, setCurrentPage, 1}}, - {2477, {wxPrintPreview, setFrame, 1}}, - {2478, {wxPrintPreview, setPrintout, 1}}, - {2479, {wxPrintPreview, setZoom, 1}}, - {2480, {wxPreviewFrame, new, 3}}, - {2481, {wxPreviewFrame, destruct, 0}}, - {2482, {wxPreviewFrame, createControlBar, 0}}, - {2483, {wxPreviewFrame, createCanvas, 0}}, - {2484, {wxPreviewFrame, initialize, 0}}, - {2485, {wxPreviewFrame, onCloseWindow, 1}}, - {2486, {wxPreviewControlBar, new, 4}}, - {2487, {wxPreviewControlBar, destruct, 0}}, - {2488, {wxPreviewControlBar, createButtons, 0}}, - {2489, {wxPreviewControlBar, getPrintPreview, 0}}, - {2490, {wxPreviewControlBar, getZoomControl, 0}}, - {2491, {wxPreviewControlBar, setZoomControl, 1}}, - {2493, {wxPrinter, new, 1}}, - {2494, {wxPrinter, createAbortWindow, 2}}, - {2495, {wxPrinter, getAbort, 0}}, - {2496, {wxPrinter, getLastError, 0}}, - {2497, {wxPrinter, getPrintDialogData, 0}}, - {2498, {wxPrinter, print, 3}}, - {2499, {wxPrinter, printDialog, 1}}, - {2500, {wxPrinter, reportError, 3}}, - {2501, {wxPrinter, setup, 1}}, - {2502, {wxPrinter, 'Destroy', undefined}}, - {2503, {wxXmlResource, new_1, 1}}, - {2504, {wxXmlResource, new_2, 2}}, - {2505, {wxXmlResource, destruct, 0}}, - {2506, {wxXmlResource, attachUnknownControl, 3}}, - {2507, {wxXmlResource, clearHandlers, 0}}, - {2508, {wxXmlResource, compareVersion, 4}}, - {2509, {wxXmlResource, get, 0}}, - {2510, {wxXmlResource, getFlags, 0}}, - {2511, {wxXmlResource, getVersion, 0}}, - {2512, {wxXmlResource, getXRCID, 2}}, - {2513, {wxXmlResource, initAllHandlers, 0}}, - {2514, {wxXmlResource, load, 1}}, - {2515, {wxXmlResource, loadBitmap, 1}}, - {2516, {wxXmlResource, loadDialog_2, 2}}, - {2517, {wxXmlResource, loadDialog_3, 3}}, - {2518, {wxXmlResource, loadFrame_2, 2}}, - {2519, {wxXmlResource, loadFrame_3, 3}}, - {2520, {wxXmlResource, loadIcon, 1}}, - {2521, {wxXmlResource, loadMenu, 1}}, - {2522, {wxXmlResource, loadMenuBar_2, 2}}, - {2523, {wxXmlResource, loadMenuBar_1, 1}}, - {2524, {wxXmlResource, loadPanel_2, 2}}, - {2525, {wxXmlResource, loadPanel_3, 3}}, - {2526, {wxXmlResource, loadToolBar, 2}}, - {2527, {wxXmlResource, set, 1}}, - {2528, {wxXmlResource, setFlags, 1}}, - {2529, {wxXmlResource, unload, 1}}, - {2530, {wxXmlResource, xrcctrl, 3}}, - {2531, {wxHtmlEasyPrinting, new, 1}}, - {2532, {wxHtmlEasyPrinting, destruct, 0}}, - {2533, {wxHtmlEasyPrinting, getPrintData, 0}}, - {2534, {wxHtmlEasyPrinting, getPageSetupData, 0}}, - {2535, {wxHtmlEasyPrinting, previewFile, 1}}, - {2536, {wxHtmlEasyPrinting, previewText, 2}}, - {2537, {wxHtmlEasyPrinting, printFile, 1}}, - {2538, {wxHtmlEasyPrinting, printText, 2}}, - {2539, {wxHtmlEasyPrinting, pageSetup, 0}}, - {2540, {wxHtmlEasyPrinting, setFonts, 3}}, - {2541, {wxHtmlEasyPrinting, setHeader, 2}}, - {2542, {wxHtmlEasyPrinting, setFooter, 2}}, - {2544, {wxGLCanvas, new_2, 2}}, - {2545, {wxGLCanvas, new_3_1, 3}}, - {2546, {wxGLCanvas, new_3_0, 3}}, - {2547, {wxGLCanvas, getContext, 0}}, - {2549, {wxGLCanvas, setCurrent, 0}}, - {2550, {wxGLCanvas, swapBuffers, 0}}, - {2551, {wxGLCanvas, 'Destroy', undefined}}, - {2552, {wxAuiManager, new, 1}}, - {2553, {wxAuiManager, destruct, 0}}, - {2554, {wxAuiManager, addPane_2_1, 2}}, - {2555, {wxAuiManager, addPane_3, 3}}, - {2556, {wxAuiManager, addPane_2_0, 2}}, - {2557, {wxAuiManager, detachPane, 1}}, - {2558, {wxAuiManager, getAllPanes, 0}}, - {2559, {wxAuiManager, getArtProvider, 0}}, - {2560, {wxAuiManager, getDockSizeConstraint, 2}}, - {2561, {wxAuiManager, getFlags, 0}}, - {2562, {wxAuiManager, getManagedWindow, 0}}, - {2563, {wxAuiManager, getManager, 1}}, - {2564, {wxAuiManager, getPane_1_1, 1}}, - {2565, {wxAuiManager, getPane_1_0, 1}}, - {2566, {wxAuiManager, hideHint, 0}}, - {2567, {wxAuiManager, insertPane, 3}}, - {2568, {wxAuiManager, loadPaneInfo, 2}}, - {2569, {wxAuiManager, loadPerspective, 2}}, - {2570, {wxAuiManager, savePaneInfo, 1}}, - {2571, {wxAuiManager, savePerspective, 0}}, - {2572, {wxAuiManager, setArtProvider, 1}}, - {2573, {wxAuiManager, setDockSizeConstraint, 2}}, - {2574, {wxAuiManager, setFlags, 1}}, - {2575, {wxAuiManager, setManagedWindow, 1}}, - {2576, {wxAuiManager, showHint, 1}}, - {2577, {wxAuiManager, unInit, 0}}, - {2578, {wxAuiManager, update, 0}}, - {2579, {wxAuiPaneInfo, new_0, 0}}, - {2580, {wxAuiPaneInfo, new_1, 1}}, - {2581, {wxAuiPaneInfo, destruct, 0}}, - {2582, {wxAuiPaneInfo, bestSize_1, 1}}, - {2583, {wxAuiPaneInfo, bestSize_2, 2}}, - {2584, {wxAuiPaneInfo, bottom, 0}}, - {2585, {wxAuiPaneInfo, bottomDockable, 1}}, - {2586, {wxAuiPaneInfo, caption, 1}}, - {2587, {wxAuiPaneInfo, captionVisible, 1}}, - {2588, {wxAuiPaneInfo, centre, 0}}, - {2589, {wxAuiPaneInfo, centrePane, 0}}, - {2590, {wxAuiPaneInfo, closeButton, 1}}, - {2591, {wxAuiPaneInfo, defaultPane, 0}}, - {2592, {wxAuiPaneInfo, destroyOnClose, 1}}, - {2593, {wxAuiPaneInfo, direction, 1}}, - {2594, {wxAuiPaneInfo, dock, 0}}, - {2595, {wxAuiPaneInfo, dockable, 1}}, - {2596, {wxAuiPaneInfo, fixed, 0}}, - {2597, {wxAuiPaneInfo, float, 0}}, - {2598, {wxAuiPaneInfo, floatable, 1}}, - {2599, {wxAuiPaneInfo, floatingPosition_1, 1}}, - {2600, {wxAuiPaneInfo, floatingPosition_2, 2}}, - {2601, {wxAuiPaneInfo, floatingSize_1, 1}}, - {2602, {wxAuiPaneInfo, floatingSize_2, 2}}, - {2603, {wxAuiPaneInfo, gripper, 1}}, - {2604, {wxAuiPaneInfo, gripperTop, 1}}, - {2605, {wxAuiPaneInfo, hasBorder, 0}}, - {2606, {wxAuiPaneInfo, hasCaption, 0}}, - {2607, {wxAuiPaneInfo, hasCloseButton, 0}}, - {2608, {wxAuiPaneInfo, hasFlag, 1}}, - {2609, {wxAuiPaneInfo, hasGripper, 0}}, - {2610, {wxAuiPaneInfo, hasGripperTop, 0}}, - {2611, {wxAuiPaneInfo, hasMaximizeButton, 0}}, - {2612, {wxAuiPaneInfo, hasMinimizeButton, 0}}, - {2613, {wxAuiPaneInfo, hasPinButton, 0}}, - {2614, {wxAuiPaneInfo, hide, 0}}, - {2615, {wxAuiPaneInfo, isBottomDockable, 0}}, - {2616, {wxAuiPaneInfo, isDocked, 0}}, - {2617, {wxAuiPaneInfo, isFixed, 0}}, - {2618, {wxAuiPaneInfo, isFloatable, 0}}, - {2619, {wxAuiPaneInfo, isFloating, 0}}, - {2620, {wxAuiPaneInfo, isLeftDockable, 0}}, - {2621, {wxAuiPaneInfo, isMovable, 0}}, - {2622, {wxAuiPaneInfo, isOk, 0}}, - {2623, {wxAuiPaneInfo, isResizable, 0}}, - {2624, {wxAuiPaneInfo, isRightDockable, 0}}, - {2625, {wxAuiPaneInfo, isShown, 0}}, - {2626, {wxAuiPaneInfo, isToolbar, 0}}, - {2627, {wxAuiPaneInfo, isTopDockable, 0}}, - {2628, {wxAuiPaneInfo, layer, 1}}, - {2629, {wxAuiPaneInfo, left, 0}}, - {2630, {wxAuiPaneInfo, leftDockable, 1}}, - {2631, {wxAuiPaneInfo, maxSize_1, 1}}, - {2632, {wxAuiPaneInfo, maxSize_2, 2}}, - {2633, {wxAuiPaneInfo, maximizeButton, 1}}, - {2634, {wxAuiPaneInfo, minSize_1, 1}}, - {2635, {wxAuiPaneInfo, minSize_2, 2}}, - {2636, {wxAuiPaneInfo, minimizeButton, 1}}, - {2637, {wxAuiPaneInfo, movable, 1}}, - {2638, {wxAuiPaneInfo, name, 1}}, - {2639, {wxAuiPaneInfo, paneBorder, 1}}, - {2640, {wxAuiPaneInfo, pinButton, 1}}, - {2641, {wxAuiPaneInfo, position, 1}}, - {2642, {wxAuiPaneInfo, resizable, 1}}, - {2643, {wxAuiPaneInfo, right, 0}}, - {2644, {wxAuiPaneInfo, rightDockable, 1}}, - {2645, {wxAuiPaneInfo, row, 1}}, - {2646, {wxAuiPaneInfo, safeSet, 1}}, - {2647, {wxAuiPaneInfo, setFlag, 2}}, - {2648, {wxAuiPaneInfo, show, 1}}, - {2649, {wxAuiPaneInfo, toolbarPane, 0}}, - {2650, {wxAuiPaneInfo, top, 0}}, - {2651, {wxAuiPaneInfo, topDockable, 1}}, - {2652, {wxAuiPaneInfo, window, 1}}, - {2653, {wxAuiPaneInfo, getWindow, 0}}, - {2654, {wxAuiPaneInfo, getFrame, 0}}, - {2655, {wxAuiPaneInfo, getDirection, 0}}, - {2656, {wxAuiPaneInfo, getLayer, 0}}, - {2657, {wxAuiPaneInfo, getRow, 0}}, - {2658, {wxAuiPaneInfo, getPosition, 0}}, - {2659, {wxAuiPaneInfo, getFloatingPosition, 0}}, - {2660, {wxAuiPaneInfo, getFloatingSize, 0}}, - {2661, {wxAuiNotebook, new_0, 0}}, - {2662, {wxAuiNotebook, new_2, 2}}, - {2663, {wxAuiNotebook, addPage, 3}}, - {2664, {wxAuiNotebook, create, 2}}, - {2665, {wxAuiNotebook, deletePage, 1}}, - {2666, {wxAuiNotebook, getArtProvider, 0}}, - {2667, {wxAuiNotebook, getPage, 1}}, - {2668, {wxAuiNotebook, getPageBitmap, 1}}, - {2669, {wxAuiNotebook, getPageCount, 0}}, - {2670, {wxAuiNotebook, getPageIndex, 1}}, - {2671, {wxAuiNotebook, getPageText, 1}}, - {2672, {wxAuiNotebook, getSelection, 0}}, - {2673, {wxAuiNotebook, insertPage, 4}}, - {2674, {wxAuiNotebook, removePage, 1}}, - {2675, {wxAuiNotebook, setArtProvider, 1}}, - {2676, {wxAuiNotebook, setFont, 1}}, - {2677, {wxAuiNotebook, setPageBitmap, 2}}, - {2678, {wxAuiNotebook, setPageText, 2}}, - {2679, {wxAuiNotebook, setSelection, 1}}, - {2680, {wxAuiNotebook, setTabCtrlHeight, 1}}, - {2681, {wxAuiNotebook, setUniformBitmapSize, 1}}, - {2682, {wxAuiNotebook, 'Destroy', undefined}}, - {2683, {wxAuiTabArt, setFlags, 1}}, - {2684, {wxAuiTabArt, setMeasuringFont, 1}}, - {2685, {wxAuiTabArt, setNormalFont, 1}}, - {2686, {wxAuiTabArt, setSelectedFont, 1}}, - {2687, {wxAuiTabArt, setColour, 1}}, - {2688, {wxAuiTabArt, setActiveColour, 1}}, - {2689, {wxAuiDockArt, getColour, 1}}, - {2690, {wxAuiDockArt, getFont, 1}}, - {2691, {wxAuiDockArt, getMetric, 1}}, - {2692, {wxAuiDockArt, setColour, 2}}, - {2693, {wxAuiDockArt, setFont, 2}}, - {2694, {wxAuiDockArt, setMetric, 2}}, - {2695, {wxAuiSimpleTabArt, new, 0}}, - {2696, {wxAuiSimpleTabArt, 'Destroy', undefined}}, - {2697, {wxMDIParentFrame, new_0, 0}}, - {2698, {wxMDIParentFrame, new_4, 4}}, - {2699, {wxMDIParentFrame, destruct, 0}}, - {2700, {wxMDIParentFrame, activateNext, 0}}, - {2701, {wxMDIParentFrame, activatePrevious, 0}}, - {2702, {wxMDIParentFrame, arrangeIcons, 0}}, - {2703, {wxMDIParentFrame, cascade, 0}}, - {2704, {wxMDIParentFrame, create, 4}}, - {2705, {wxMDIParentFrame, getActiveChild, 0}}, - {2706, {wxMDIParentFrame, getClientWindow, 0}}, - {2707, {wxMDIParentFrame, tile, 1}}, - {2708, {wxMDIChildFrame, new_0, 0}}, - {2709, {wxMDIChildFrame, new_4, 4}}, - {2710, {wxMDIChildFrame, destruct, 0}}, - {2711, {wxMDIChildFrame, activate, 0}}, - {2712, {wxMDIChildFrame, create, 4}}, - {2713, {wxMDIChildFrame, maximize, 1}}, - {2714, {wxMDIChildFrame, restore, 0}}, - {2715, {wxMDIClientWindow, new_0, 0}}, - {2716, {wxMDIClientWindow, new_2, 2}}, - {2717, {wxMDIClientWindow, destruct, 0}}, - {2718, {wxMDIClientWindow, createClient, 2}}, - {2719, {wxLayoutAlgorithm, new, 0}}, - {2720, {wxLayoutAlgorithm, layoutFrame, 2}}, - {2721, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, - {2722, {wxLayoutAlgorithm, layoutWindow, 2}}, - {2723, {wxLayoutAlgorithm, 'Destroy', undefined}}, - {2724, {wxEvent, getId, 0}}, - {2725, {wxEvent, getSkipped, 0}}, - {2726, {wxEvent, getTimestamp, 0}}, - {2727, {wxEvent, isCommandEvent, 0}}, - {2728, {wxEvent, resumePropagation, 1}}, - {2729, {wxEvent, shouldPropagate, 0}}, - {2730, {wxEvent, skip, 1}}, - {2731, {wxEvent, stopPropagation, 0}}, - {2732, {wxCommandEvent, getClientData, 0}}, - {2733, {wxCommandEvent, getExtraLong, 0}}, - {2734, {wxCommandEvent, getInt, 0}}, - {2735, {wxCommandEvent, getSelection, 0}}, - {2736, {wxCommandEvent, getString, 0}}, - {2737, {wxCommandEvent, isChecked, 0}}, - {2738, {wxCommandEvent, isSelection, 0}}, - {2739, {wxCommandEvent, setInt, 1}}, - {2740, {wxCommandEvent, setString, 1}}, - {2741, {wxScrollEvent, getOrientation, 0}}, - {2742, {wxScrollEvent, getPosition, 0}}, - {2743, {wxScrollWinEvent, getOrientation, 0}}, - {2744, {wxScrollWinEvent, getPosition, 0}}, - {2745, {wxMouseEvent, altDown, 0}}, - {2746, {wxMouseEvent, button, 1}}, - {2747, {wxMouseEvent, buttonDClick, 1}}, - {2748, {wxMouseEvent, buttonDown, 1}}, - {2749, {wxMouseEvent, buttonUp, 1}}, - {2750, {wxMouseEvent, cmdDown, 0}}, - {2751, {wxMouseEvent, controlDown, 0}}, - {2752, {wxMouseEvent, dragging, 0}}, - {2753, {wxMouseEvent, entering, 0}}, - {2754, {wxMouseEvent, getButton, 0}}, - {2757, {wxMouseEvent, getPosition, 0}}, - {2758, {wxMouseEvent, getLogicalPosition, 1}}, - {2759, {wxMouseEvent, getLinesPerAction, 0}}, - {2760, {wxMouseEvent, getWheelRotation, 0}}, - {2761, {wxMouseEvent, getWheelDelta, 0}}, - {2762, {wxMouseEvent, getX, 0}}, - {2763, {wxMouseEvent, getY, 0}}, - {2764, {wxMouseEvent, isButton, 0}}, - {2765, {wxMouseEvent, isPageScroll, 0}}, - {2766, {wxMouseEvent, leaving, 0}}, - {2767, {wxMouseEvent, leftDClick, 0}}, - {2768, {wxMouseEvent, leftDown, 0}}, - {2769, {wxMouseEvent, leftIsDown, 0}}, - {2770, {wxMouseEvent, leftUp, 0}}, - {2771, {wxMouseEvent, metaDown, 0}}, - {2772, {wxMouseEvent, middleDClick, 0}}, - {2773, {wxMouseEvent, middleDown, 0}}, - {2774, {wxMouseEvent, middleIsDown, 0}}, - {2775, {wxMouseEvent, middleUp, 0}}, - {2776, {wxMouseEvent, moving, 0}}, - {2777, {wxMouseEvent, rightDClick, 0}}, - {2778, {wxMouseEvent, rightDown, 0}}, - {2779, {wxMouseEvent, rightIsDown, 0}}, - {2780, {wxMouseEvent, rightUp, 0}}, - {2781, {wxMouseEvent, shiftDown, 0}}, - {2782, {wxSetCursorEvent, getCursor, 0}}, - {2783, {wxSetCursorEvent, getX, 0}}, - {2784, {wxSetCursorEvent, getY, 0}}, - {2785, {wxSetCursorEvent, hasCursor, 0}}, - {2786, {wxSetCursorEvent, setCursor, 1}}, - {2787, {wxKeyEvent, altDown, 0}}, - {2788, {wxKeyEvent, cmdDown, 0}}, - {2789, {wxKeyEvent, controlDown, 0}}, - {2790, {wxKeyEvent, getKeyCode, 0}}, - {2791, {wxKeyEvent, getModifiers, 0}}, - {2794, {wxKeyEvent, getPosition, 0}}, - {2795, {wxKeyEvent, getRawKeyCode, 0}}, - {2796, {wxKeyEvent, getRawKeyFlags, 0}}, - {2797, {wxKeyEvent, getUnicodeKey, 0}}, - {2798, {wxKeyEvent, getX, 0}}, - {2799, {wxKeyEvent, getY, 0}}, - {2800, {wxKeyEvent, hasModifiers, 0}}, - {2801, {wxKeyEvent, metaDown, 0}}, - {2802, {wxKeyEvent, shiftDown, 0}}, - {2803, {wxSizeEvent, getSize, 0}}, - {2804, {wxMoveEvent, getPosition, 0}}, - {2805, {wxEraseEvent, getDC, 0}}, - {2806, {wxFocusEvent, getWindow, 0}}, - {2807, {wxChildFocusEvent, getWindow, 0}}, - {2808, {wxMenuEvent, getMenu, 0}}, - {2809, {wxMenuEvent, getMenuId, 0}}, - {2810, {wxMenuEvent, isPopup, 0}}, - {2811, {wxCloseEvent, canVeto, 0}}, - {2812, {wxCloseEvent, getLoggingOff, 0}}, - {2813, {wxCloseEvent, setCanVeto, 1}}, - {2814, {wxCloseEvent, setLoggingOff, 1}}, - {2815, {wxCloseEvent, veto, 1}}, - {2816, {wxShowEvent, setShow, 1}}, - {2817, {wxShowEvent, getShow, 0}}, - {2818, {wxIconizeEvent, iconized, 0}}, - {2819, {wxJoystickEvent, buttonDown, 1}}, - {2820, {wxJoystickEvent, buttonIsDown, 1}}, - {2821, {wxJoystickEvent, buttonUp, 1}}, - {2822, {wxJoystickEvent, getButtonChange, 0}}, - {2823, {wxJoystickEvent, getButtonState, 0}}, - {2824, {wxJoystickEvent, getJoystick, 0}}, - {2825, {wxJoystickEvent, getPosition, 0}}, - {2826, {wxJoystickEvent, getZPosition, 0}}, - {2827, {wxJoystickEvent, isButton, 0}}, - {2828, {wxJoystickEvent, isMove, 0}}, - {2829, {wxJoystickEvent, isZMove, 0}}, - {2830, {wxUpdateUIEvent, canUpdate, 1}}, - {2831, {wxUpdateUIEvent, check, 1}}, - {2832, {wxUpdateUIEvent, enable, 1}}, - {2833, {wxUpdateUIEvent, show, 1}}, - {2834, {wxUpdateUIEvent, getChecked, 0}}, - {2835, {wxUpdateUIEvent, getEnabled, 0}}, - {2836, {wxUpdateUIEvent, getShown, 0}}, - {2837, {wxUpdateUIEvent, getSetChecked, 0}}, - {2838, {wxUpdateUIEvent, getSetEnabled, 0}}, - {2839, {wxUpdateUIEvent, getSetShown, 0}}, - {2840, {wxUpdateUIEvent, getSetText, 0}}, - {2841, {wxUpdateUIEvent, getText, 0}}, - {2842, {wxUpdateUIEvent, getMode, 0}}, - {2843, {wxUpdateUIEvent, getUpdateInterval, 0}}, - {2844, {wxUpdateUIEvent, resetUpdateTime, 0}}, - {2845, {wxUpdateUIEvent, setMode, 1}}, - {2846, {wxUpdateUIEvent, setText, 1}}, - {2847, {wxUpdateUIEvent, setUpdateInterval, 1}}, - {2848, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, - {2849, {wxPaletteChangedEvent, setChangedWindow, 1}}, - {2850, {wxPaletteChangedEvent, getChangedWindow, 0}}, - {2851, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, - {2852, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, - {2853, {wxNavigationKeyEvent, getDirection, 0}}, - {2854, {wxNavigationKeyEvent, setDirection, 1}}, - {2855, {wxNavigationKeyEvent, isWindowChange, 0}}, - {2856, {wxNavigationKeyEvent, setWindowChange, 1}}, - {2857, {wxNavigationKeyEvent, isFromTab, 0}}, - {2858, {wxNavigationKeyEvent, setFromTab, 1}}, - {2859, {wxNavigationKeyEvent, getCurrentFocus, 0}}, - {2860, {wxNavigationKeyEvent, setCurrentFocus, 1}}, - {2861, {wxHelpEvent, getOrigin, 0}}, - {2862, {wxHelpEvent, getPosition, 0}}, - {2863, {wxHelpEvent, setOrigin, 1}}, - {2864, {wxHelpEvent, setPosition, 1}}, - {2865, {wxContextMenuEvent, getPosition, 0}}, - {2866, {wxContextMenuEvent, setPosition, 1}}, - {2867, {wxIdleEvent, canSend, 1}}, - {2868, {wxIdleEvent, getMode, 0}}, - {2869, {wxIdleEvent, requestMore, 1}}, - {2870, {wxIdleEvent, moreRequested, 0}}, - {2871, {wxIdleEvent, setMode, 1}}, - {2872, {wxGridEvent, altDown, 0}}, - {2873, {wxGridEvent, controlDown, 0}}, - {2874, {wxGridEvent, getCol, 0}}, - {2875, {wxGridEvent, getPosition, 0}}, - {2876, {wxGridEvent, getRow, 0}}, - {2877, {wxGridEvent, metaDown, 0}}, - {2878, {wxGridEvent, selecting, 0}}, - {2879, {wxGridEvent, shiftDown, 0}}, - {2880, {wxNotifyEvent, allow, 0}}, - {2881, {wxNotifyEvent, isAllowed, 0}}, - {2882, {wxNotifyEvent, veto, 0}}, - {2883, {wxSashEvent, getEdge, 0}}, - {2884, {wxSashEvent, getDragRect, 0}}, - {2885, {wxSashEvent, getDragStatus, 0}}, - {2886, {wxListEvent, getCacheFrom, 0}}, - {2887, {wxListEvent, getCacheTo, 0}}, - {2888, {wxListEvent, getKeyCode, 0}}, - {2889, {wxListEvent, getIndex, 0}}, - {2890, {wxListEvent, getColumn, 0}}, - {2891, {wxListEvent, getPoint, 0}}, - {2892, {wxListEvent, getLabel, 0}}, - {2893, {wxListEvent, getText, 0}}, - {2894, {wxListEvent, getImage, 0}}, - {2895, {wxListEvent, getData, 0}}, - {2896, {wxListEvent, getMask, 0}}, - {2897, {wxListEvent, getItem, 0}}, - {2898, {wxListEvent, isEditCancelled, 0}}, - {2899, {wxDateEvent, getDate, 0}}, - {2900, {wxCalendarEvent, getWeekDay, 0}}, - {2901, {wxFileDirPickerEvent, getPath, 0}}, - {2902, {wxColourPickerEvent, getColour, 0}}, - {2903, {wxFontPickerEvent, getFont, 0}}, - {2904, {wxStyledTextEvent, getPosition, 0}}, - {2905, {wxStyledTextEvent, getKey, 0}}, - {2906, {wxStyledTextEvent, getModifiers, 0}}, - {2907, {wxStyledTextEvent, getModificationType, 0}}, - {2908, {wxStyledTextEvent, getText, 0}}, - {2909, {wxStyledTextEvent, getLength, 0}}, - {2910, {wxStyledTextEvent, getLinesAdded, 0}}, - {2911, {wxStyledTextEvent, getLine, 0}}, - {2912, {wxStyledTextEvent, getFoldLevelNow, 0}}, - {2913, {wxStyledTextEvent, getFoldLevelPrev, 0}}, - {2914, {wxStyledTextEvent, getMargin, 0}}, - {2915, {wxStyledTextEvent, getMessage, 0}}, - {2916, {wxStyledTextEvent, getWParam, 0}}, - {2917, {wxStyledTextEvent, getLParam, 0}}, - {2918, {wxStyledTextEvent, getListType, 0}}, - {2919, {wxStyledTextEvent, getX, 0}}, - {2920, {wxStyledTextEvent, getY, 0}}, - {2921, {wxStyledTextEvent, getDragText, 0}}, - {2922, {wxStyledTextEvent, getDragAllowMove, 0}}, - {2923, {wxStyledTextEvent, getDragResult, 0}}, - {2924, {wxStyledTextEvent, getShift, 0}}, - {2925, {wxStyledTextEvent, getControl, 0}}, - {2926, {wxStyledTextEvent, getAlt, 0}}, - {2927, {utils, getKeyState, 1}}, - {2928, {utils, getMousePosition, 2}}, - {2929, {utils, getMouseState, 0}}, - {2930, {utils, setDetectableAutoRepeat, 1}}, - {2931, {utils, bell, 0}}, - {2932, {utils, findMenuItemId, 3}}, - {2933, {utils, genericFindWindowAtPoint, 1}}, - {2934, {utils, findWindowAtPoint, 1}}, - {2935, {utils, beginBusyCursor, 1}}, - {2936, {utils, endBusyCursor, 0}}, - {2937, {utils, isBusy, 0}}, - {2938, {utils, shutdown, 1}}, - {2939, {utils, shell, 1}}, - {2940, {utils, launchDefaultBrowser, 2}}, - {2941, {utils, getEmailAddress, 0}}, - {2942, {utils, getUserId, 0}}, - {2943, {utils, getHomeDir, 0}}, - {2944, {utils, newId, 0}}, - {2945, {utils, registerId, 1}}, - {2946, {utils, getCurrentId, 0}}, - {2947, {utils, getOsDescription, 0}}, - {2948, {utils, isPlatformLittleEndian, 0}}, - {2949, {utils, isPlatform64Bit, 0}}, - {2950, {gdicmn, displaySize, 2}}, - {2951, {gdicmn, setCursor, 1}}, - {2952, {wxPrintout, new, 1}}, - {2953, {wxPrintout, destruct, 0}}, - {2954, {wxPrintout, getDC, 0}}, - {2955, {wxPrintout, getPageSizeMM, 2}}, - {2956, {wxPrintout, getPageSizePixels, 2}}, - {2957, {wxPrintout, getPaperRectPixels, 0}}, - {2958, {wxPrintout, getPPIPrinter, 2}}, - {2959, {wxPrintout, getPPIScreen, 2}}, - {2960, {wxPrintout, getTitle, 0}}, - {2961, {wxPrintout, isPreview, 0}}, - {2962, {wxPrintout, fitThisSizeToPaper, 1}}, - {2963, {wxPrintout, fitThisSizeToPage, 1}}, - {2964, {wxPrintout, fitThisSizeToPageMargins, 2}}, - {2965, {wxPrintout, mapScreenSizeToPaper, 0}}, - {2966, {wxPrintout, mapScreenSizeToPage, 0}}, - {2967, {wxPrintout, mapScreenSizeToPageMargins, 1}}, - {2968, {wxPrintout, mapScreenSizeToDevice, 0}}, - {2969, {wxPrintout, getLogicalPaperRect, 0}}, - {2970, {wxPrintout, getLogicalPageRect, 0}}, - {2971, {wxPrintout, getLogicalPageMarginsRect, 1}}, - {2972, {wxPrintout, setLogicalOrigin, 2}}, - {2973, {wxPrintout, offsetLogicalOrigin, 2}}, - {2974, {wxStyledTextCtrl, new_2, 2}}, - {2975, {wxStyledTextCtrl, new_0, 0}}, - {2976, {wxStyledTextCtrl, destruct, 0}}, - {2977, {wxStyledTextCtrl, create, 2}}, - {2978, {wxStyledTextCtrl, addText, 1}}, - {2979, {wxStyledTextCtrl, addStyledText, 1}}, - {2980, {wxStyledTextCtrl, insertText, 2}}, - {2981, {wxStyledTextCtrl, clearAll, 0}}, - {2982, {wxStyledTextCtrl, clearDocumentStyle, 0}}, - {2983, {wxStyledTextCtrl, getLength, 0}}, - {2984, {wxStyledTextCtrl, getCharAt, 1}}, - {2985, {wxStyledTextCtrl, getCurrentPos, 0}}, - {2986, {wxStyledTextCtrl, getAnchor, 0}}, - {2987, {wxStyledTextCtrl, getStyleAt, 1}}, - {2988, {wxStyledTextCtrl, redo, 0}}, - {2989, {wxStyledTextCtrl, setUndoCollection, 1}}, - {2990, {wxStyledTextCtrl, selectAll, 0}}, - {2991, {wxStyledTextCtrl, setSavePoint, 0}}, - {2992, {wxStyledTextCtrl, getStyledText, 2}}, - {2993, {wxStyledTextCtrl, canRedo, 0}}, - {2994, {wxStyledTextCtrl, markerLineFromHandle, 1}}, - {2995, {wxStyledTextCtrl, markerDeleteHandle, 1}}, - {2996, {wxStyledTextCtrl, getUndoCollection, 0}}, - {2997, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, - {2998, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, - {2999, {wxStyledTextCtrl, positionFromPoint, 1}}, - {3000, {wxStyledTextCtrl, positionFromPointClose, 2}}, - {3001, {wxStyledTextCtrl, gotoLine, 1}}, - {3002, {wxStyledTextCtrl, gotoPos, 1}}, - {3003, {wxStyledTextCtrl, setAnchor, 1}}, - {3004, {wxStyledTextCtrl, getCurLine, 1}}, - {3005, {wxStyledTextCtrl, getEndStyled, 0}}, - {3006, {wxStyledTextCtrl, convertEOLs, 1}}, - {3007, {wxStyledTextCtrl, getEOLMode, 0}}, - {3008, {wxStyledTextCtrl, setEOLMode, 1}}, - {3009, {wxStyledTextCtrl, startStyling, 2}}, - {3010, {wxStyledTextCtrl, setStyling, 2}}, - {3011, {wxStyledTextCtrl, getBufferedDraw, 0}}, - {3012, {wxStyledTextCtrl, setBufferedDraw, 1}}, - {3013, {wxStyledTextCtrl, setTabWidth, 1}}, - {3014, {wxStyledTextCtrl, getTabWidth, 0}}, - {3015, {wxStyledTextCtrl, setCodePage, 1}}, - {3016, {wxStyledTextCtrl, markerDefine, 3}}, - {3017, {wxStyledTextCtrl, markerSetForeground, 2}}, - {3018, {wxStyledTextCtrl, markerSetBackground, 2}}, - {3019, {wxStyledTextCtrl, markerAdd, 2}}, - {3020, {wxStyledTextCtrl, markerDelete, 2}}, - {3021, {wxStyledTextCtrl, markerDeleteAll, 1}}, - {3022, {wxStyledTextCtrl, markerGet, 1}}, - {3023, {wxStyledTextCtrl, markerNext, 2}}, - {3024, {wxStyledTextCtrl, markerPrevious, 2}}, - {3025, {wxStyledTextCtrl, markerDefineBitmap, 2}}, - {3026, {wxStyledTextCtrl, markerAddSet, 2}}, - {3027, {wxStyledTextCtrl, markerSetAlpha, 2}}, - {3028, {wxStyledTextCtrl, setMarginType, 2}}, - {3029, {wxStyledTextCtrl, getMarginType, 1}}, - {3030, {wxStyledTextCtrl, setMarginWidth, 2}}, - {3031, {wxStyledTextCtrl, getMarginWidth, 1}}, - {3032, {wxStyledTextCtrl, setMarginMask, 2}}, - {3033, {wxStyledTextCtrl, getMarginMask, 1}}, - {3034, {wxStyledTextCtrl, setMarginSensitive, 2}}, - {3035, {wxStyledTextCtrl, getMarginSensitive, 1}}, - {3036, {wxStyledTextCtrl, styleClearAll, 0}}, - {3037, {wxStyledTextCtrl, styleSetForeground, 2}}, - {3038, {wxStyledTextCtrl, styleSetBackground, 2}}, - {3039, {wxStyledTextCtrl, styleSetBold, 2}}, - {3040, {wxStyledTextCtrl, styleSetItalic, 2}}, - {3041, {wxStyledTextCtrl, styleSetSize, 2}}, - {3042, {wxStyledTextCtrl, styleSetFaceName, 2}}, - {3043, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, - {3044, {wxStyledTextCtrl, styleResetDefault, 0}}, - {3045, {wxStyledTextCtrl, styleSetUnderline, 2}}, - {3046, {wxStyledTextCtrl, styleSetCase, 2}}, - {3047, {wxStyledTextCtrl, styleSetHotSpot, 2}}, - {3048, {wxStyledTextCtrl, setSelForeground, 2}}, - {3049, {wxStyledTextCtrl, setSelBackground, 2}}, - {3050, {wxStyledTextCtrl, getSelAlpha, 0}}, - {3051, {wxStyledTextCtrl, setSelAlpha, 1}}, - {3052, {wxStyledTextCtrl, setCaretForeground, 1}}, - {3053, {wxStyledTextCtrl, cmdKeyAssign, 3}}, - {3054, {wxStyledTextCtrl, cmdKeyClear, 2}}, - {3055, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, - {3056, {wxStyledTextCtrl, setStyleBytes, 2}}, - {3057, {wxStyledTextCtrl, styleSetVisible, 2}}, - {3058, {wxStyledTextCtrl, getCaretPeriod, 0}}, - {3059, {wxStyledTextCtrl, setCaretPeriod, 1}}, - {3060, {wxStyledTextCtrl, setWordChars, 1}}, - {3061, {wxStyledTextCtrl, beginUndoAction, 0}}, - {3062, {wxStyledTextCtrl, endUndoAction, 0}}, - {3063, {wxStyledTextCtrl, indicatorSetStyle, 2}}, - {3064, {wxStyledTextCtrl, indicatorGetStyle, 1}}, - {3065, {wxStyledTextCtrl, indicatorSetForeground, 2}}, - {3066, {wxStyledTextCtrl, indicatorGetForeground, 1}}, - {3067, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, - {3068, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, - {3069, {wxStyledTextCtrl, getStyleBits, 0}}, - {3070, {wxStyledTextCtrl, setLineState, 2}}, - {3071, {wxStyledTextCtrl, getLineState, 1}}, - {3072, {wxStyledTextCtrl, getMaxLineState, 0}}, - {3073, {wxStyledTextCtrl, getCaretLineVisible, 0}}, - {3074, {wxStyledTextCtrl, setCaretLineVisible, 1}}, - {3075, {wxStyledTextCtrl, getCaretLineBackground, 0}}, - {3076, {wxStyledTextCtrl, setCaretLineBackground, 1}}, - {3077, {wxStyledTextCtrl, autoCompShow, 2}}, - {3078, {wxStyledTextCtrl, autoCompCancel, 0}}, - {3079, {wxStyledTextCtrl, autoCompActive, 0}}, - {3080, {wxStyledTextCtrl, autoCompPosStart, 0}}, - {3081, {wxStyledTextCtrl, autoCompComplete, 0}}, - {3082, {wxStyledTextCtrl, autoCompStops, 1}}, - {3083, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, - {3084, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, - {3085, {wxStyledTextCtrl, autoCompSelect, 1}}, - {3086, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, - {3087, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, - {3088, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, - {3089, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, - {3090, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, - {3091, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, - {3092, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, - {3093, {wxStyledTextCtrl, userListShow, 2}}, - {3094, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, - {3095, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, - {3096, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, - {3097, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, - {3098, {wxStyledTextCtrl, registerImage, 2}}, - {3099, {wxStyledTextCtrl, clearRegisteredImages, 0}}, - {3100, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, - {3101, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, - {3102, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, - {3103, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, - {3104, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, - {3105, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, - {3106, {wxStyledTextCtrl, setIndent, 1}}, - {3107, {wxStyledTextCtrl, getIndent, 0}}, - {3108, {wxStyledTextCtrl, setUseTabs, 1}}, - {3109, {wxStyledTextCtrl, getUseTabs, 0}}, - {3110, {wxStyledTextCtrl, setLineIndentation, 2}}, - {3111, {wxStyledTextCtrl, getLineIndentation, 1}}, - {3112, {wxStyledTextCtrl, getLineIndentPosition, 1}}, - {3113, {wxStyledTextCtrl, getColumn, 1}}, - {3114, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, - {3115, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, - {3116, {wxStyledTextCtrl, setIndentationGuides, 1}}, - {3117, {wxStyledTextCtrl, getIndentationGuides, 0}}, - {3118, {wxStyledTextCtrl, setHighlightGuide, 1}}, - {3119, {wxStyledTextCtrl, getHighlightGuide, 0}}, - {3120, {wxStyledTextCtrl, getLineEndPosition, 1}}, - {3121, {wxStyledTextCtrl, getCodePage, 0}}, - {3122, {wxStyledTextCtrl, getCaretForeground, 0}}, - {3123, {wxStyledTextCtrl, getReadOnly, 0}}, - {3124, {wxStyledTextCtrl, setCurrentPos, 1}}, - {3125, {wxStyledTextCtrl, setSelectionStart, 1}}, - {3126, {wxStyledTextCtrl, getSelectionStart, 0}}, - {3127, {wxStyledTextCtrl, setSelectionEnd, 1}}, - {3128, {wxStyledTextCtrl, getSelectionEnd, 0}}, - {3129, {wxStyledTextCtrl, setPrintMagnification, 1}}, - {3130, {wxStyledTextCtrl, getPrintMagnification, 0}}, - {3131, {wxStyledTextCtrl, setPrintColourMode, 1}}, - {3132, {wxStyledTextCtrl, getPrintColourMode, 0}}, - {3133, {wxStyledTextCtrl, findText, 4}}, - {3134, {wxStyledTextCtrl, formatRange, 7}}, - {3135, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, - {3136, {wxStyledTextCtrl, getLine, 1}}, - {3137, {wxStyledTextCtrl, getLineCount, 0}}, - {3138, {wxStyledTextCtrl, setMarginLeft, 1}}, - {3139, {wxStyledTextCtrl, getMarginLeft, 0}}, - {3140, {wxStyledTextCtrl, setMarginRight, 1}}, - {3141, {wxStyledTextCtrl, getMarginRight, 0}}, - {3142, {wxStyledTextCtrl, getModify, 0}}, - {3143, {wxStyledTextCtrl, setSelection, 2}}, - {3144, {wxStyledTextCtrl, getSelectedText, 0}}, - {3145, {wxStyledTextCtrl, getTextRange, 2}}, - {3146, {wxStyledTextCtrl, hideSelection, 1}}, - {3147, {wxStyledTextCtrl, lineFromPosition, 1}}, - {3148, {wxStyledTextCtrl, positionFromLine, 1}}, - {3149, {wxStyledTextCtrl, lineScroll, 2}}, - {3150, {wxStyledTextCtrl, ensureCaretVisible, 0}}, - {3151, {wxStyledTextCtrl, replaceSelection, 1}}, - {3152, {wxStyledTextCtrl, setReadOnly, 1}}, - {3153, {wxStyledTextCtrl, canPaste, 0}}, - {3154, {wxStyledTextCtrl, canUndo, 0}}, - {3155, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, - {3156, {wxStyledTextCtrl, undo, 0}}, - {3157, {wxStyledTextCtrl, cut, 0}}, - {3158, {wxStyledTextCtrl, copy, 0}}, - {3159, {wxStyledTextCtrl, paste, 0}}, - {3160, {wxStyledTextCtrl, clear, 0}}, - {3161, {wxStyledTextCtrl, setText, 1}}, - {3162, {wxStyledTextCtrl, getText, 0}}, - {3163, {wxStyledTextCtrl, getTextLength, 0}}, - {3164, {wxStyledTextCtrl, getOvertype, 0}}, - {3165, {wxStyledTextCtrl, setCaretWidth, 1}}, - {3166, {wxStyledTextCtrl, getCaretWidth, 0}}, - {3167, {wxStyledTextCtrl, setTargetStart, 1}}, - {3168, {wxStyledTextCtrl, getTargetStart, 0}}, - {3169, {wxStyledTextCtrl, setTargetEnd, 1}}, - {3170, {wxStyledTextCtrl, getTargetEnd, 0}}, - {3171, {wxStyledTextCtrl, replaceTarget, 1}}, - {3172, {wxStyledTextCtrl, searchInTarget, 1}}, - {3173, {wxStyledTextCtrl, setSearchFlags, 1}}, - {3174, {wxStyledTextCtrl, getSearchFlags, 0}}, - {3175, {wxStyledTextCtrl, callTipShow, 2}}, - {3176, {wxStyledTextCtrl, callTipCancel, 0}}, - {3177, {wxStyledTextCtrl, callTipActive, 0}}, - {3178, {wxStyledTextCtrl, callTipPosAtStart, 0}}, - {3179, {wxStyledTextCtrl, callTipSetHighlight, 2}}, - {3180, {wxStyledTextCtrl, callTipSetBackground, 1}}, - {3181, {wxStyledTextCtrl, callTipSetForeground, 1}}, - {3182, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, - {3183, {wxStyledTextCtrl, callTipUseStyle, 1}}, - {3184, {wxStyledTextCtrl, visibleFromDocLine, 1}}, - {3185, {wxStyledTextCtrl, docLineFromVisible, 1}}, - {3186, {wxStyledTextCtrl, wrapCount, 1}}, - {3187, {wxStyledTextCtrl, setFoldLevel, 2}}, - {3188, {wxStyledTextCtrl, getFoldLevel, 1}}, - {3189, {wxStyledTextCtrl, getLastChild, 2}}, - {3190, {wxStyledTextCtrl, getFoldParent, 1}}, - {3191, {wxStyledTextCtrl, showLines, 2}}, - {3192, {wxStyledTextCtrl, hideLines, 2}}, - {3193, {wxStyledTextCtrl, getLineVisible, 1}}, - {3194, {wxStyledTextCtrl, setFoldExpanded, 2}}, - {3195, {wxStyledTextCtrl, getFoldExpanded, 1}}, - {3196, {wxStyledTextCtrl, toggleFold, 1}}, - {3197, {wxStyledTextCtrl, ensureVisible, 1}}, - {3198, {wxStyledTextCtrl, setFoldFlags, 1}}, - {3199, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, - {3200, {wxStyledTextCtrl, setTabIndents, 1}}, - {3201, {wxStyledTextCtrl, getTabIndents, 0}}, - {3202, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, - {3203, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, - {3204, {wxStyledTextCtrl, setMouseDwellTime, 1}}, - {3205, {wxStyledTextCtrl, getMouseDwellTime, 0}}, - {3206, {wxStyledTextCtrl, wordStartPosition, 2}}, - {3207, {wxStyledTextCtrl, wordEndPosition, 2}}, - {3208, {wxStyledTextCtrl, setWrapMode, 1}}, - {3209, {wxStyledTextCtrl, getWrapMode, 0}}, - {3210, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, - {3211, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, - {3212, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, - {3213, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, - {3214, {wxStyledTextCtrl, setWrapStartIndent, 1}}, - {3215, {wxStyledTextCtrl, getWrapStartIndent, 0}}, - {3216, {wxStyledTextCtrl, setLayoutCache, 1}}, - {3217, {wxStyledTextCtrl, getLayoutCache, 0}}, - {3218, {wxStyledTextCtrl, setScrollWidth, 1}}, - {3219, {wxStyledTextCtrl, getScrollWidth, 0}}, - {3220, {wxStyledTextCtrl, textWidth, 2}}, - {3221, {wxStyledTextCtrl, getEndAtLastLine, 0}}, - {3222, {wxStyledTextCtrl, textHeight, 1}}, - {3223, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, - {3224, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, - {3225, {wxStyledTextCtrl, appendText, 1}}, - {3226, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, - {3227, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, - {3228, {wxStyledTextCtrl, targetFromSelection, 0}}, - {3229, {wxStyledTextCtrl, linesJoin, 0}}, - {3230, {wxStyledTextCtrl, linesSplit, 1}}, - {3231, {wxStyledTextCtrl, setFoldMarginColour, 2}}, - {3232, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, - {3233, {wxStyledTextCtrl, lineDown, 0}}, - {3234, {wxStyledTextCtrl, lineDownExtend, 0}}, - {3235, {wxStyledTextCtrl, lineUp, 0}}, - {3236, {wxStyledTextCtrl, lineUpExtend, 0}}, - {3237, {wxStyledTextCtrl, charLeft, 0}}, - {3238, {wxStyledTextCtrl, charLeftExtend, 0}}, - {3239, {wxStyledTextCtrl, charRight, 0}}, - {3240, {wxStyledTextCtrl, charRightExtend, 0}}, - {3241, {wxStyledTextCtrl, wordLeft, 0}}, - {3242, {wxStyledTextCtrl, wordLeftExtend, 0}}, - {3243, {wxStyledTextCtrl, wordRight, 0}}, - {3244, {wxStyledTextCtrl, wordRightExtend, 0}}, - {3245, {wxStyledTextCtrl, home, 0}}, - {3246, {wxStyledTextCtrl, homeExtend, 0}}, - {3247, {wxStyledTextCtrl, lineEnd, 0}}, - {3248, {wxStyledTextCtrl, lineEndExtend, 0}}, - {3249, {wxStyledTextCtrl, documentStart, 0}}, - {3250, {wxStyledTextCtrl, documentStartExtend, 0}}, - {3251, {wxStyledTextCtrl, documentEnd, 0}}, - {3252, {wxStyledTextCtrl, documentEndExtend, 0}}, - {3253, {wxStyledTextCtrl, pageUp, 0}}, - {3254, {wxStyledTextCtrl, pageUpExtend, 0}}, - {3255, {wxStyledTextCtrl, pageDown, 0}}, - {3256, {wxStyledTextCtrl, pageDownExtend, 0}}, - {3257, {wxStyledTextCtrl, editToggleOvertype, 0}}, - {3258, {wxStyledTextCtrl, cancel, 0}}, - {3259, {wxStyledTextCtrl, deleteBack, 0}}, - {3260, {wxStyledTextCtrl, tab, 0}}, - {3261, {wxStyledTextCtrl, backTab, 0}}, - {3262, {wxStyledTextCtrl, newLine, 0}}, - {3263, {wxStyledTextCtrl, formFeed, 0}}, - {3264, {wxStyledTextCtrl, vCHome, 0}}, - {3265, {wxStyledTextCtrl, vCHomeExtend, 0}}, - {3266, {wxStyledTextCtrl, zoomIn, 0}}, - {3267, {wxStyledTextCtrl, zoomOut, 0}}, - {3268, {wxStyledTextCtrl, delWordLeft, 0}}, - {3269, {wxStyledTextCtrl, delWordRight, 0}}, - {3270, {wxStyledTextCtrl, lineCut, 0}}, - {3271, {wxStyledTextCtrl, lineDelete, 0}}, - {3272, {wxStyledTextCtrl, lineTranspose, 0}}, - {3273, {wxStyledTextCtrl, lineDuplicate, 0}}, - {3274, {wxStyledTextCtrl, lowerCase, 0}}, - {3275, {wxStyledTextCtrl, upperCase, 0}}, - {3276, {wxStyledTextCtrl, lineScrollDown, 0}}, - {3277, {wxStyledTextCtrl, lineScrollUp, 0}}, - {3278, {wxStyledTextCtrl, deleteBackNotLine, 0}}, - {3279, {wxStyledTextCtrl, homeDisplay, 0}}, - {3280, {wxStyledTextCtrl, homeDisplayExtend, 0}}, - {3281, {wxStyledTextCtrl, lineEndDisplay, 0}}, - {3282, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, - {3283, {wxStyledTextCtrl, homeWrapExtend, 0}}, - {3284, {wxStyledTextCtrl, lineEndWrap, 0}}, - {3285, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, - {3286, {wxStyledTextCtrl, vCHomeWrap, 0}}, - {3287, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, - {3288, {wxStyledTextCtrl, lineCopy, 0}}, - {3289, {wxStyledTextCtrl, moveCaretInsideView, 0}}, - {3290, {wxStyledTextCtrl, lineLength, 1}}, - {3291, {wxStyledTextCtrl, braceHighlight, 2}}, - {3292, {wxStyledTextCtrl, braceBadLight, 1}}, - {3293, {wxStyledTextCtrl, braceMatch, 1}}, - {3294, {wxStyledTextCtrl, getViewEOL, 0}}, - {3295, {wxStyledTextCtrl, setViewEOL, 1}}, - {3296, {wxStyledTextCtrl, setModEventMask, 1}}, - {3297, {wxStyledTextCtrl, getEdgeColumn, 0}}, - {3298, {wxStyledTextCtrl, setEdgeColumn, 1}}, - {3299, {wxStyledTextCtrl, setEdgeMode, 1}}, - {3300, {wxStyledTextCtrl, getEdgeMode, 0}}, - {3301, {wxStyledTextCtrl, getEdgeColour, 0}}, - {3302, {wxStyledTextCtrl, setEdgeColour, 1}}, - {3303, {wxStyledTextCtrl, searchAnchor, 0}}, - {3304, {wxStyledTextCtrl, searchNext, 2}}, - {3305, {wxStyledTextCtrl, searchPrev, 2}}, - {3306, {wxStyledTextCtrl, linesOnScreen, 0}}, - {3307, {wxStyledTextCtrl, usePopUp, 1}}, - {3308, {wxStyledTextCtrl, selectionIsRectangle, 0}}, - {3309, {wxStyledTextCtrl, setZoom, 1}}, - {3310, {wxStyledTextCtrl, getZoom, 0}}, - {3311, {wxStyledTextCtrl, getModEventMask, 0}}, - {3312, {wxStyledTextCtrl, setSTCFocus, 1}}, - {3313, {wxStyledTextCtrl, getSTCFocus, 0}}, - {3314, {wxStyledTextCtrl, setStatus, 1}}, - {3315, {wxStyledTextCtrl, getStatus, 0}}, - {3316, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, - {3317, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, - {3318, {wxStyledTextCtrl, setSTCCursor, 1}}, - {3319, {wxStyledTextCtrl, getSTCCursor, 0}}, - {3320, {wxStyledTextCtrl, setControlCharSymbol, 1}}, - {3321, {wxStyledTextCtrl, getControlCharSymbol, 0}}, - {3322, {wxStyledTextCtrl, wordPartLeft, 0}}, - {3323, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, - {3324, {wxStyledTextCtrl, wordPartRight, 0}}, - {3325, {wxStyledTextCtrl, wordPartRightExtend, 0}}, - {3326, {wxStyledTextCtrl, setVisiblePolicy, 2}}, - {3327, {wxStyledTextCtrl, delLineLeft, 0}}, - {3328, {wxStyledTextCtrl, delLineRight, 0}}, - {3329, {wxStyledTextCtrl, getXOffset, 0}}, - {3330, {wxStyledTextCtrl, chooseCaretX, 0}}, - {3331, {wxStyledTextCtrl, setXCaretPolicy, 2}}, - {3332, {wxStyledTextCtrl, setYCaretPolicy, 2}}, - {3333, {wxStyledTextCtrl, getPrintWrapMode, 0}}, - {3334, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, - {3335, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, - {3336, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, - {3337, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, - {3338, {wxStyledTextCtrl, paraDownExtend, 0}}, - {3339, {wxStyledTextCtrl, paraUp, 0}}, - {3340, {wxStyledTextCtrl, paraUpExtend, 0}}, - {3341, {wxStyledTextCtrl, positionBefore, 1}}, - {3342, {wxStyledTextCtrl, positionAfter, 1}}, - {3343, {wxStyledTextCtrl, copyRange, 2}}, - {3344, {wxStyledTextCtrl, copyText, 2}}, - {3345, {wxStyledTextCtrl, setSelectionMode, 1}}, - {3346, {wxStyledTextCtrl, getSelectionMode, 0}}, - {3347, {wxStyledTextCtrl, lineDownRectExtend, 0}}, - {3348, {wxStyledTextCtrl, lineUpRectExtend, 0}}, - {3349, {wxStyledTextCtrl, charLeftRectExtend, 0}}, - {3350, {wxStyledTextCtrl, charRightRectExtend, 0}}, - {3351, {wxStyledTextCtrl, homeRectExtend, 0}}, - {3352, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, - {3353, {wxStyledTextCtrl, lineEndRectExtend, 0}}, - {3354, {wxStyledTextCtrl, pageUpRectExtend, 0}}, - {3355, {wxStyledTextCtrl, pageDownRectExtend, 0}}, - {3356, {wxStyledTextCtrl, stutteredPageUp, 0}}, - {3357, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, - {3358, {wxStyledTextCtrl, stutteredPageDown, 0}}, - {3359, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, - {3360, {wxStyledTextCtrl, wordLeftEnd, 0}}, - {3361, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, - {3362, {wxStyledTextCtrl, wordRightEnd, 0}}, - {3363, {wxStyledTextCtrl, wordRightEndExtend, 0}}, - {3364, {wxStyledTextCtrl, setWhitespaceChars, 1}}, - {3365, {wxStyledTextCtrl, setCharsDefault, 0}}, - {3366, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, - {3367, {wxStyledTextCtrl, allocate, 1}}, - {3368, {wxStyledTextCtrl, findColumn, 2}}, - {3369, {wxStyledTextCtrl, getCaretSticky, 0}}, - {3370, {wxStyledTextCtrl, setCaretSticky, 1}}, - {3371, {wxStyledTextCtrl, toggleCaretSticky, 0}}, - {3372, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, - {3373, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, - {3374, {wxStyledTextCtrl, selectionDuplicate, 0}}, - {3375, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, - {3376, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, - {3377, {wxStyledTextCtrl, startRecord, 0}}, - {3378, {wxStyledTextCtrl, stopRecord, 0}}, - {3379, {wxStyledTextCtrl, setLexer, 1}}, - {3380, {wxStyledTextCtrl, getLexer, 0}}, - {3381, {wxStyledTextCtrl, colourise, 2}}, - {3382, {wxStyledTextCtrl, setProperty, 2}}, - {3383, {wxStyledTextCtrl, setKeyWords, 2}}, - {3384, {wxStyledTextCtrl, setLexerLanguage, 1}}, - {3385, {wxStyledTextCtrl, getProperty, 1}}, - {3386, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, - {3387, {wxStyledTextCtrl, getCurrentLine, 0}}, - {3388, {wxStyledTextCtrl, styleSetSpec, 2}}, - {3389, {wxStyledTextCtrl, styleSetFont, 2}}, - {3390, {wxStyledTextCtrl, styleSetFontAttr, 7}}, - {3391, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, - {3392, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, - {3393, {wxStyledTextCtrl, cmdKeyExecute, 1}}, - {3394, {wxStyledTextCtrl, setMargins, 2}}, - {3395, {wxStyledTextCtrl, getSelection, 2}}, - {3396, {wxStyledTextCtrl, pointFromPosition, 1}}, - {3397, {wxStyledTextCtrl, scrollToLine, 1}}, - {3398, {wxStyledTextCtrl, scrollToColumn, 1}}, - {3399, {wxStyledTextCtrl, setVScrollBar, 1}}, - {3400, {wxStyledTextCtrl, setHScrollBar, 1}}, - {3401, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, - {3402, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, - {3403, {wxStyledTextCtrl, saveFile, 1}}, - {3404, {wxStyledTextCtrl, loadFile, 1}}, - {3405, {wxStyledTextCtrl, doDragOver, 3}}, - {3406, {wxStyledTextCtrl, doDropText, 3}}, - {3407, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, - {3408, {wxStyledTextCtrl, addTextRaw, 1}}, - {3409, {wxStyledTextCtrl, insertTextRaw, 2}}, - {3410, {wxStyledTextCtrl, getCurLineRaw, 1}}, - {3411, {wxStyledTextCtrl, getLineRaw, 1}}, - {3412, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, - {3413, {wxStyledTextCtrl, getTextRangeRaw, 2}}, - {3414, {wxStyledTextCtrl, setTextRaw, 1}}, - {3415, {wxStyledTextCtrl, getTextRaw, 0}}, - {3416, {wxStyledTextCtrl, appendTextRaw, 1}}, - {3417, {wxArtProvider, getBitmap, 2}}, - {3418, {wxArtProvider, getIcon, 2}}, - {3419, {wxTreeEvent, getKeyCode, 0}}, - {3420, {wxTreeEvent, getItem, 0}}, - {3421, {wxTreeEvent, getKeyEvent, 0}}, - {3422, {wxTreeEvent, getLabel, 0}}, - {3423, {wxTreeEvent, getOldItem, 0}}, - {3424, {wxTreeEvent, getPoint, 0}}, - {3425, {wxTreeEvent, isEditCancelled, 0}}, - {3426, {wxTreeEvent, setToolTip, 1}}, - {3427, {wxNotebookEvent, getOldSelection, 0}}, - {3428, {wxNotebookEvent, getSelection, 0}}, - {3429, {wxNotebookEvent, setOldSelection, 1}}, - {3430, {wxNotebookEvent, setSelection, 1}}, - {3431, {wxFileDataObject, new, 0}}, - {3432, {wxFileDataObject, addFile, 1}}, - {3433, {wxFileDataObject, getFilenames, 0}}, - {3434, {wxFileDataObject, 'Destroy', undefined}}, - {3435, {wxTextDataObject, new, 1}}, - {3436, {wxTextDataObject, getTextLength, 0}}, - {3437, {wxTextDataObject, getText, 0}}, - {3438, {wxTextDataObject, setText, 1}}, - {3439, {wxTextDataObject, 'Destroy', undefined}}, - {3440, {wxBitmapDataObject, new_1_1, 1}}, - {3441, {wxBitmapDataObject, new_1_0, 1}}, - {3442, {wxBitmapDataObject, getBitmap, 0}}, - {3443, {wxBitmapDataObject, setBitmap, 1}}, - {3444, {wxBitmapDataObject, 'Destroy', undefined}}, - {3446, {wxClipboard, new, 0}}, - {3447, {wxClipboard, destruct, 0}}, - {3448, {wxClipboard, addData, 1}}, - {3449, {wxClipboard, clear, 0}}, - {3450, {wxClipboard, close, 0}}, - {3451, {wxClipboard, flush, 0}}, - {3452, {wxClipboard, getData, 1}}, - {3453, {wxClipboard, isOpened, 0}}, - {3454, {wxClipboard, open, 0}}, - {3455, {wxClipboard, setData, 1}}, - {3457, {wxClipboard, usePrimarySelection, 1}}, - {3458, {wxClipboard, isSupported, 1}}, - {3459, {wxClipboard, get, 0}}, - {3460, {wxSpinEvent, getPosition, 0}}, - {3461, {wxSpinEvent, setPosition, 1}}, - {3462, {wxSplitterWindow, new_0, 0}}, - {3463, {wxSplitterWindow, new_2, 2}}, - {3464, {wxSplitterWindow, destruct, 0}}, - {3465, {wxSplitterWindow, create, 2}}, - {3466, {wxSplitterWindow, getMinimumPaneSize, 0}}, - {3467, {wxSplitterWindow, getSashGravity, 0}}, - {3468, {wxSplitterWindow, getSashPosition, 0}}, - {3469, {wxSplitterWindow, getSplitMode, 0}}, - {3470, {wxSplitterWindow, getWindow1, 0}}, - {3471, {wxSplitterWindow, getWindow2, 0}}, - {3472, {wxSplitterWindow, initialize, 1}}, - {3473, {wxSplitterWindow, isSplit, 0}}, - {3474, {wxSplitterWindow, replaceWindow, 2}}, - {3475, {wxSplitterWindow, setSashGravity, 1}}, - {3476, {wxSplitterWindow, setSashPosition, 2}}, - {3477, {wxSplitterWindow, setSashSize, 1}}, - {3478, {wxSplitterWindow, setMinimumPaneSize, 1}}, - {3479, {wxSplitterWindow, setSplitMode, 1}}, - {3480, {wxSplitterWindow, splitHorizontally, 3}}, - {3481, {wxSplitterWindow, splitVertically, 3}}, - {3482, {wxSplitterWindow, unsplit, 1}}, - {3483, {wxSplitterWindow, updateSize, 0}}, - {3484, {wxSplitterEvent, getSashPosition, 0}}, - {3485, {wxSplitterEvent, getX, 0}}, - {3486, {wxSplitterEvent, getY, 0}}, - {3487, {wxSplitterEvent, getWindowBeingRemoved, 0}}, - {3488, {wxSplitterEvent, setSashPosition, 1}}, - {3489, {wxHtmlWindow, new_0, 0}}, - {3490, {wxHtmlWindow, new_2, 2}}, - {3491, {wxHtmlWindow, appendToPage, 1}}, - {3492, {wxHtmlWindow, getOpenedAnchor, 0}}, - {3493, {wxHtmlWindow, getOpenedPage, 0}}, - {3494, {wxHtmlWindow, getOpenedPageTitle, 0}}, - {3495, {wxHtmlWindow, getRelatedFrame, 0}}, - {3496, {wxHtmlWindow, historyBack, 0}}, - {3497, {wxHtmlWindow, historyCanBack, 0}}, - {3498, {wxHtmlWindow, historyCanForward, 0}}, - {3499, {wxHtmlWindow, historyClear, 0}}, - {3500, {wxHtmlWindow, historyForward, 0}}, - {3501, {wxHtmlWindow, loadFile, 1}}, - {3502, {wxHtmlWindow, loadPage, 1}}, - {3503, {wxHtmlWindow, selectAll, 0}}, - {3504, {wxHtmlWindow, selectionToText, 0}}, - {3505, {wxHtmlWindow, selectLine, 1}}, - {3506, {wxHtmlWindow, selectWord, 1}}, - {3507, {wxHtmlWindow, setBorders, 1}}, - {3508, {wxHtmlWindow, setFonts, 3}}, - {3509, {wxHtmlWindow, setPage, 1}}, - {3510, {wxHtmlWindow, setRelatedFrame, 2}}, - {3511, {wxHtmlWindow, setRelatedStatusBar, 1}}, - {3512, {wxHtmlWindow, toText, 0}}, - {3513, {wxHtmlWindow, 'Destroy', undefined}}, - {3514, {wxHtmlLinkEvent, getLinkInfo, 0}}, - {3515, {wxSystemSettings, getColour, 1}}, - {3516, {wxSystemSettings, getFont, 1}}, - {3517, {wxSystemSettings, getMetric, 2}}, - {3518, {wxSystemSettings, getScreenType, 0}}, - {3519, {wxSystemOptions, getOption, 1}}, - {3520, {wxSystemOptions, getOptionInt, 1}}, - {3521, {wxSystemOptions, hasOption, 1}}, - {3522, {wxSystemOptions, isFalse, 1}}, - {3523, {wxSystemOptions, setOption_2_1, 2}}, - {3524, {wxSystemOptions, setOption_2_0, 2}}, - {3525, {wxAuiNotebookEvent, setSelection, 1}}, - {3526, {wxAuiNotebookEvent, getSelection, 0}}, - {3527, {wxAuiNotebookEvent, setOldSelection, 1}}, - {3528, {wxAuiNotebookEvent, getOldSelection, 0}}, - {3529, {wxAuiNotebookEvent, setDragSource, 1}}, - {3530, {wxAuiNotebookEvent, getDragSource, 0}}, - {3531, {wxAuiManagerEvent, setManager, 1}}, - {3532, {wxAuiManagerEvent, getManager, 0}}, - {3533, {wxAuiManagerEvent, setPane, 1}}, - {3534, {wxAuiManagerEvent, getPane, 0}}, - {3535, {wxAuiManagerEvent, setButton, 1}}, - {3536, {wxAuiManagerEvent, getButton, 0}}, - {3537, {wxAuiManagerEvent, setDC, 1}}, - {3538, {wxAuiManagerEvent, getDC, 0}}, - {3539, {wxAuiManagerEvent, veto, 1}}, - {3540, {wxAuiManagerEvent, getVeto, 0}}, - {3541, {wxAuiManagerEvent, setCanVeto, 1}}, - {3542, {wxAuiManagerEvent, canVeto, 0}}, - {3543, {wxLogNull, new, 0}}, - {3544, {wxLogNull, 'Destroy', undefined}}, - {3545, {wxTaskBarIcon, new, 0}}, - {3546, {wxTaskBarIcon, destruct, 0}}, - {3547, {wxTaskBarIcon, popupMenu, 1}}, - {3548, {wxTaskBarIcon, removeIcon, 0}}, - {3549, {wxTaskBarIcon, setIcon, 2}}, - {3550, {wxLocale, new_0, 0}}, - {3552, {wxLocale, new_2, 2}}, - {3553, {wxLocale, destruct, 0}}, - {3555, {wxLocale, init, 1}}, - {3556, {wxLocale, addCatalog_1, 1}}, - {3557, {wxLocale, addCatalog_3, 3}}, - {3558, {wxLocale, addCatalogLookupPathPrefix, 1}}, - {3559, {wxLocale, getCanonicalName, 0}}, - {3560, {wxLocale, getLanguage, 0}}, - {3561, {wxLocale, getLanguageName, 1}}, - {3562, {wxLocale, getLocale, 0}}, - {3563, {wxLocale, getName, 0}}, - {3564, {wxLocale, getString_2, 2}}, - {3565, {wxLocale, getString_4, 4}}, - {3566, {wxLocale, getHeaderValue, 2}}, - {3567, {wxLocale, getSysName, 0}}, - {3568, {wxLocale, getSystemEncoding, 0}}, - {3569, {wxLocale, getSystemEncodingName, 0}}, - {3570, {wxLocale, getSystemLanguage, 0}}, - {3571, {wxLocale, isLoaded, 1}}, - {3572, {wxLocale, isOk, 0}}, - {3573, {wxActivateEvent, getActive, 0}}, - {3575, {wxPopupWindow, new_2, 2}}, - {3576, {wxPopupWindow, new_0, 0}}, - {3578, {wxPopupWindow, destruct, 0}}, - {3579, {wxPopupWindow, create, 2}}, - {3580, {wxPopupWindow, position, 2}}, - {3581, {wxPopupTransientWindow, new_0, 0}}, - {3582, {wxPopupTransientWindow, new_2, 2}}, - {3583, {wxPopupTransientWindow, destruct, 0}}, - {3584, {wxPopupTransientWindow, popup, 1}}, - {3585, {wxPopupTransientWindow, dismiss, 0}}, - {3586, {wxOverlay, new, 0}}, - {3587, {wxOverlay, destruct, 0}}, - {3588, {wxOverlay, reset, 0}}, - {3589, {wxDCOverlay, new_6, 6}}, - {3590, {wxDCOverlay, new_2, 2}}, - {3591, {wxDCOverlay, destruct, 0}}, - {3592, {wxDCOverlay, clear, 0}}, + {984, {wxToolBar, addStretchableSpace, 0}}, + {985, {wxToolBar, insertStretchableSpace, 1}}, + {986, {wxToolBar, deleteTool, 1}}, + {987, {wxToolBar, deleteToolByPos, 1}}, + {988, {wxToolBar, enableTool, 2}}, + {989, {wxToolBar, findById, 1}}, + {990, {wxToolBar, findControl, 1}}, + {991, {wxToolBar, findToolForPosition, 2}}, + {992, {wxToolBar, getToolSize, 0}}, + {993, {wxToolBar, getToolBitmapSize, 0}}, + {994, {wxToolBar, getMargins, 0}}, + {995, {wxToolBar, getToolEnabled, 1}}, + {996, {wxToolBar, getToolLongHelp, 1}}, + {997, {wxToolBar, getToolPacking, 0}}, + {998, {wxToolBar, getToolPos, 1}}, + {999, {wxToolBar, getToolSeparation, 0}}, + {1000, {wxToolBar, getToolShortHelp, 1}}, + {1001, {wxToolBar, getToolState, 1}}, + {1002, {wxToolBar, insertControl, 2}}, + {1003, {wxToolBar, insertSeparator, 1}}, + {1004, {wxToolBar, insertTool_5, 5}}, + {1005, {wxToolBar, insertTool_2, 2}}, + {1006, {wxToolBar, insertTool_4, 4}}, + {1007, {wxToolBar, realize, 0}}, + {1008, {wxToolBar, removeTool, 1}}, + {1009, {wxToolBar, setMargins, 2}}, + {1010, {wxToolBar, setToolBitmapSize, 1}}, + {1011, {wxToolBar, setToolLongHelp, 2}}, + {1012, {wxToolBar, setToolPacking, 1}}, + {1013, {wxToolBar, setToolShortHelp, 2}}, + {1014, {wxToolBar, setToolSeparation, 1}}, + {1015, {wxToolBar, toggleTool, 2}}, + {1017, {wxStatusBar, new_0, 0}}, + {1018, {wxStatusBar, new_2, 2}}, + {1020, {wxStatusBar, destruct, 0}}, + {1021, {wxStatusBar, create, 2}}, + {1022, {wxStatusBar, getFieldRect, 2}}, + {1023, {wxStatusBar, getFieldsCount, 0}}, + {1024, {wxStatusBar, getStatusText, 1}}, + {1025, {wxStatusBar, popStatusText, 1}}, + {1026, {wxStatusBar, pushStatusText, 2}}, + {1027, {wxStatusBar, setFieldsCount, 2}}, + {1028, {wxStatusBar, setMinHeight, 1}}, + {1029, {wxStatusBar, setStatusText, 2}}, + {1030, {wxStatusBar, setStatusWidths, 2}}, + {1031, {wxStatusBar, setStatusStyles, 2}}, + {1032, {wxBitmap, new_0, 0}}, + {1033, {wxBitmap, new_3, 3}}, + {1034, {wxBitmap, new_4, 4}}, + {1035, {wxBitmap, new_2_0, 2}}, + {1036, {wxBitmap, new_2_1, 2}}, + {1037, {wxBitmap, destruct, 0}}, + {1038, {wxBitmap, convertToImage, 0}}, + {1039, {wxBitmap, copyFromIcon, 1}}, + {1040, {wxBitmap, create, 3}}, + {1041, {wxBitmap, getDepth, 0}}, + {1042, {wxBitmap, getHeight, 0}}, + {1043, {wxBitmap, getPalette, 0}}, + {1044, {wxBitmap, getMask, 0}}, + {1045, {wxBitmap, getWidth, 0}}, + {1046, {wxBitmap, getSubBitmap, 1}}, + {1047, {wxBitmap, loadFile, 2}}, + {1048, {wxBitmap, ok, 0}}, + {1049, {wxBitmap, saveFile, 3}}, + {1050, {wxBitmap, setDepth, 1}}, + {1051, {wxBitmap, setHeight, 1}}, + {1052, {wxBitmap, setMask, 1}}, + {1053, {wxBitmap, setPalette, 1}}, + {1054, {wxBitmap, setWidth, 1}}, + {1055, {wxIcon, new_0, 0}}, + {1056, {wxIcon, new_2, 2}}, + {1057, {wxIcon, new_1, 1}}, + {1058, {wxIcon, copyFromBitmap, 1}}, + {1059, {wxIcon, 'Destroy', undefined}}, + {1060, {wxIconBundle, new_0, 0}}, + {1061, {wxIconBundle, new_2, 2}}, + {1062, {wxIconBundle, new_1_0, 1}}, + {1063, {wxIconBundle, new_1_1, 1}}, + {1064, {wxIconBundle, destruct, 0}}, + {1065, {wxIconBundle, addIcon_2, 2}}, + {1066, {wxIconBundle, addIcon_1, 1}}, + {1067, {wxIconBundle, getIcon_1_1, 1}}, + {1068, {wxIconBundle, getIcon_1_0, 1}}, + {1069, {wxCursor, new_0, 0}}, + {1070, {wxCursor, new_1_0, 1}}, + {1071, {wxCursor, new_1_1, 1}}, + {1072, {wxCursor, new_4, 4}}, + {1073, {wxCursor, destruct, 0}}, + {1074, {wxCursor, ok, 0}}, + {1075, {wxMask, new_0, 0}}, + {1076, {wxMask, new_2_1, 2}}, + {1077, {wxMask, new_2_0, 2}}, + {1078, {wxMask, new_1, 1}}, + {1079, {wxMask, destruct, 0}}, + {1080, {wxMask, create_2_1, 2}}, + {1081, {wxMask, create_2_0, 2}}, + {1082, {wxMask, create_1, 1}}, + {1083, {wxImage, new_0, 0}}, + {1084, {wxImage, new_3_0, 3}}, + {1085, {wxImage, new_4, 4}}, + {1086, {wxImage, new_5, 5}}, + {1087, {wxImage, new_2, 2}}, + {1088, {wxImage, new_3_1, 3}}, + {1089, {wxImage, blur, 1}}, + {1090, {wxImage, blurHorizontal, 1}}, + {1091, {wxImage, blurVertical, 1}}, + {1092, {wxImage, convertAlphaToMask, 1}}, + {1093, {wxImage, convertToGreyscale, 1}}, + {1094, {wxImage, convertToMono, 3}}, + {1095, {wxImage, copy, 0}}, + {1096, {wxImage, create_3, 3}}, + {1097, {wxImage, create_4, 4}}, + {1098, {wxImage, create_5, 5}}, + {1099, {wxImage, 'Destroy', 0}}, + {1100, {wxImage, findFirstUnusedColour, 4}}, + {1101, {wxImage, getImageExtWildcard, 0}}, + {1102, {wxImage, getAlpha_2, 2}}, + {1103, {wxImage, getAlpha_0, 0}}, + {1104, {wxImage, getBlue, 2}}, + {1105, {wxImage, getData, 0}}, + {1106, {wxImage, getGreen, 2}}, + {1107, {wxImage, getImageCount, 2}}, + {1108, {wxImage, getHeight, 0}}, + {1109, {wxImage, getMaskBlue, 0}}, + {1110, {wxImage, getMaskGreen, 0}}, + {1111, {wxImage, getMaskRed, 0}}, + {1112, {wxImage, getOrFindMaskColour, 3}}, + {1113, {wxImage, getPalette, 0}}, + {1114, {wxImage, getRed, 2}}, + {1115, {wxImage, getSubImage, 1}}, + {1116, {wxImage, getWidth, 0}}, + {1117, {wxImage, hasAlpha, 0}}, + {1118, {wxImage, hasMask, 0}}, + {1119, {wxImage, getOption, 1}}, + {1120, {wxImage, getOptionInt, 1}}, + {1121, {wxImage, hasOption, 1}}, + {1122, {wxImage, initAlpha, 0}}, + {1123, {wxImage, initStandardHandlers, 0}}, + {1124, {wxImage, isTransparent, 3}}, + {1125, {wxImage, loadFile_2, 2}}, + {1126, {wxImage, loadFile_3, 3}}, + {1127, {wxImage, ok, 0}}, + {1128, {wxImage, removeHandler, 1}}, + {1129, {wxImage, mirror, 1}}, + {1130, {wxImage, replace, 6}}, + {1131, {wxImage, rescale, 3}}, + {1132, {wxImage, resize, 3}}, + {1133, {wxImage, rotate, 3}}, + {1134, {wxImage, rotateHue, 1}}, + {1135, {wxImage, rotate90, 1}}, + {1136, {wxImage, saveFile_1, 1}}, + {1137, {wxImage, saveFile_2_0, 2}}, + {1138, {wxImage, saveFile_2_1, 2}}, + {1139, {wxImage, scale, 3}}, + {1140, {wxImage, size, 3}}, + {1141, {wxImage, setAlpha_3, 3}}, + {1142, {wxImage, setAlpha_2, 2}}, + {1143, {wxImage, setData_2, 2}}, + {1144, {wxImage, setData_4, 4}}, + {1145, {wxImage, setMask, 1}}, + {1146, {wxImage, setMaskColour, 3}}, + {1147, {wxImage, setMaskFromImage, 4}}, + {1148, {wxImage, setOption_2_1, 2}}, + {1149, {wxImage, setOption_2_0, 2}}, + {1150, {wxImage, setPalette, 1}}, + {1151, {wxImage, setRGB_5, 5}}, + {1152, {wxImage, setRGB_4, 4}}, + {1153, {wxImage, 'Destroy', undefined}}, + {1154, {wxBrush, new_0, 0}}, + {1155, {wxBrush, new_2, 2}}, + {1156, {wxBrush, new_1, 1}}, + {1158, {wxBrush, destruct, 0}}, + {1159, {wxBrush, getColour, 0}}, + {1160, {wxBrush, getStipple, 0}}, + {1161, {wxBrush, getStyle, 0}}, + {1162, {wxBrush, isHatch, 0}}, + {1163, {wxBrush, isOk, 0}}, + {1164, {wxBrush, setColour_1, 1}}, + {1165, {wxBrush, setColour_3, 3}}, + {1166, {wxBrush, setStipple, 1}}, + {1167, {wxBrush, setStyle, 1}}, + {1168, {wxPen, new_0, 0}}, + {1169, {wxPen, new_2, 2}}, + {1170, {wxPen, destruct, 0}}, + {1171, {wxPen, getCap, 0}}, + {1172, {wxPen, getColour, 0}}, + {1173, {wxPen, getJoin, 0}}, + {1174, {wxPen, getStyle, 0}}, + {1175, {wxPen, getWidth, 0}}, + {1176, {wxPen, isOk, 0}}, + {1177, {wxPen, setCap, 1}}, + {1178, {wxPen, setColour_1, 1}}, + {1179, {wxPen, setColour_3, 3}}, + {1180, {wxPen, setJoin, 1}}, + {1181, {wxPen, setStyle, 1}}, + {1182, {wxPen, setWidth, 1}}, + {1183, {wxRegion, new_0, 0}}, + {1184, {wxRegion, new_4, 4}}, + {1185, {wxRegion, new_2, 2}}, + {1186, {wxRegion, new_1_1, 1}}, + {1188, {wxRegion, new_1_0, 1}}, + {1190, {wxRegion, destruct, 0}}, + {1191, {wxRegion, clear, 0}}, + {1192, {wxRegion, contains_2, 2}}, + {1193, {wxRegion, contains_1_0, 1}}, + {1194, {wxRegion, contains_4, 4}}, + {1195, {wxRegion, contains_1_1, 1}}, + {1196, {wxRegion, convertToBitmap, 0}}, + {1197, {wxRegion, getBox, 0}}, + {1198, {wxRegion, intersect_4, 4}}, + {1199, {wxRegion, intersect_1_1, 1}}, + {1200, {wxRegion, intersect_1_0, 1}}, + {1201, {wxRegion, isEmpty, 0}}, + {1202, {wxRegion, subtract_4, 4}}, + {1203, {wxRegion, subtract_1_1, 1}}, + {1204, {wxRegion, subtract_1_0, 1}}, + {1205, {wxRegion, offset_2, 2}}, + {1206, {wxRegion, offset_1, 1}}, + {1207, {wxRegion, union_4, 4}}, + {1208, {wxRegion, union_1_2, 1}}, + {1209, {wxRegion, union_1_1, 1}}, + {1210, {wxRegion, union_1_0, 1}}, + {1211, {wxRegion, union_3, 3}}, + {1212, {wxRegion, xor_4, 4}}, + {1213, {wxRegion, xor_1_1, 1}}, + {1214, {wxRegion, xor_1_0, 1}}, + {1215, {wxAcceleratorTable, new_0, 0}}, + {1216, {wxAcceleratorTable, new_2, 2}}, + {1217, {wxAcceleratorTable, destruct, 0}}, + {1218, {wxAcceleratorTable, ok, 0}}, + {1219, {wxAcceleratorEntry, new_1_0, 1}}, + {1220, {wxAcceleratorEntry, new_1_1, 1}}, + {1221, {wxAcceleratorEntry, getCommand, 0}}, + {1222, {wxAcceleratorEntry, getFlags, 0}}, + {1223, {wxAcceleratorEntry, getKeyCode, 0}}, + {1224, {wxAcceleratorEntry, set, 4}}, + {1225, {wxAcceleratorEntry, 'Destroy', undefined}}, + {1230, {wxCaret, new_3, 3}}, + {1231, {wxCaret, new_2, 2}}, + {1233, {wxCaret, destruct, 0}}, + {1234, {wxCaret, create_3, 3}}, + {1235, {wxCaret, create_2, 2}}, + {1236, {wxCaret, getBlinkTime, 0}}, + {1238, {wxCaret, getPosition, 0}}, + {1240, {wxCaret, getSize, 0}}, + {1241, {wxCaret, getWindow, 0}}, + {1242, {wxCaret, hide, 0}}, + {1243, {wxCaret, isOk, 0}}, + {1244, {wxCaret, isVisible, 0}}, + {1245, {wxCaret, move_2, 2}}, + {1246, {wxCaret, move_1, 1}}, + {1247, {wxCaret, setBlinkTime, 1}}, + {1248, {wxCaret, setSize_2, 2}}, + {1249, {wxCaret, setSize_1, 1}}, + {1250, {wxCaret, show, 1}}, + {1251, {wxSizer, add_2_1, 2}}, + {1252, {wxSizer, add_2_0, 2}}, + {1253, {wxSizer, add_3, 3}}, + {1254, {wxSizer, add_2_3, 2}}, + {1255, {wxSizer, add_2_2, 2}}, + {1256, {wxSizer, addSpacer, 1}}, + {1257, {wxSizer, addStretchSpacer, 1}}, + {1258, {wxSizer, calcMin, 0}}, + {1259, {wxSizer, clear, 1}}, + {1260, {wxSizer, detach_1_2, 1}}, + {1261, {wxSizer, detach_1_1, 1}}, + {1262, {wxSizer, detach_1_0, 1}}, + {1263, {wxSizer, fit, 1}}, + {1264, {wxSizer, fitInside, 1}}, + {1265, {wxSizer, getChildren, 0}}, + {1266, {wxSizer, getItem_2_1, 2}}, + {1267, {wxSizer, getItem_2_0, 2}}, + {1268, {wxSizer, getItem_1, 1}}, + {1269, {wxSizer, getSize, 0}}, + {1270, {wxSizer, getPosition, 0}}, + {1271, {wxSizer, getMinSize, 0}}, + {1272, {wxSizer, hide_2_0, 2}}, + {1273, {wxSizer, hide_2_1, 2}}, + {1274, {wxSizer, hide_1, 1}}, + {1275, {wxSizer, insert_3_1, 3}}, + {1276, {wxSizer, insert_3_0, 3}}, + {1277, {wxSizer, insert_4, 4}}, + {1278, {wxSizer, insert_3_3, 3}}, + {1279, {wxSizer, insert_3_2, 3}}, + {1280, {wxSizer, insert_2, 2}}, + {1281, {wxSizer, insertSpacer, 2}}, + {1282, {wxSizer, insertStretchSpacer, 2}}, + {1283, {wxSizer, isShown_1_2, 1}}, + {1284, {wxSizer, isShown_1_1, 1}}, + {1285, {wxSizer, isShown_1_0, 1}}, + {1286, {wxSizer, layout, 0}}, + {1287, {wxSizer, prepend_2_1, 2}}, + {1288, {wxSizer, prepend_2_0, 2}}, + {1289, {wxSizer, prepend_3, 3}}, + {1290, {wxSizer, prepend_2_3, 2}}, + {1291, {wxSizer, prepend_2_2, 2}}, + {1292, {wxSizer, prepend_1, 1}}, + {1293, {wxSizer, prependSpacer, 1}}, + {1294, {wxSizer, prependStretchSpacer, 1}}, + {1295, {wxSizer, recalcSizes, 0}}, + {1296, {wxSizer, remove_1_1, 1}}, + {1297, {wxSizer, remove_1_0, 1}}, + {1298, {wxSizer, replace_3_1, 3}}, + {1299, {wxSizer, replace_3_0, 3}}, + {1300, {wxSizer, replace_2, 2}}, + {1301, {wxSizer, setDimension, 4}}, + {1302, {wxSizer, setMinSize_2, 2}}, + {1303, {wxSizer, setMinSize_1, 1}}, + {1304, {wxSizer, setItemMinSize_3_2, 3}}, + {1305, {wxSizer, setItemMinSize_2_2, 2}}, + {1306, {wxSizer, setItemMinSize_3_1, 3}}, + {1307, {wxSizer, setItemMinSize_2_1, 2}}, + {1308, {wxSizer, setItemMinSize_3_0, 3}}, + {1309, {wxSizer, setItemMinSize_2_0, 2}}, + {1310, {wxSizer, setSizeHints, 1}}, + {1311, {wxSizer, setVirtualSizeHints, 1}}, + {1312, {wxSizer, show_2_2, 2}}, + {1313, {wxSizer, show_2_1, 2}}, + {1314, {wxSizer, show_2_0, 2}}, + {1315, {wxSizer, show_1, 1}}, + {1316, {wxSizerFlags, new, 1}}, + {1317, {wxSizerFlags, align, 1}}, + {1318, {wxSizerFlags, border_2, 2}}, + {1319, {wxSizerFlags, border_1, 1}}, + {1320, {wxSizerFlags, center, 0}}, + {1321, {wxSizerFlags, centre, 0}}, + {1322, {wxSizerFlags, expand, 0}}, + {1323, {wxSizerFlags, left, 0}}, + {1324, {wxSizerFlags, proportion, 1}}, + {1325, {wxSizerFlags, right, 0}}, + {1326, {wxSizerFlags, 'Destroy', undefined}}, + {1327, {wxSizerItem, new_5_1, 5}}, + {1328, {wxSizerItem, new_2_1, 2}}, + {1329, {wxSizerItem, new_5_0, 5}}, + {1330, {wxSizerItem, new_2_0, 2}}, + {1331, {wxSizerItem, new_6, 6}}, + {1332, {wxSizerItem, new_3, 3}}, + {1333, {wxSizerItem, new_0, 0}}, + {1334, {wxSizerItem, destruct, 0}}, + {1335, {wxSizerItem, calcMin, 0}}, + {1336, {wxSizerItem, deleteWindows, 0}}, + {1337, {wxSizerItem, detachSizer, 0}}, + {1338, {wxSizerItem, getBorder, 0}}, + {1339, {wxSizerItem, getFlag, 0}}, + {1340, {wxSizerItem, getMinSize, 0}}, + {1341, {wxSizerItem, getPosition, 0}}, + {1342, {wxSizerItem, getProportion, 0}}, + {1343, {wxSizerItem, getRatio, 0}}, + {1344, {wxSizerItem, getRect, 0}}, + {1345, {wxSizerItem, getSize, 0}}, + {1346, {wxSizerItem, getSizer, 0}}, + {1347, {wxSizerItem, getSpacer, 0}}, + {1348, {wxSizerItem, getUserData, 0}}, + {1349, {wxSizerItem, getWindow, 0}}, + {1350, {wxSizerItem, isSizer, 0}}, + {1351, {wxSizerItem, isShown, 0}}, + {1352, {wxSizerItem, isSpacer, 0}}, + {1353, {wxSizerItem, isWindow, 0}}, + {1354, {wxSizerItem, setBorder, 1}}, + {1355, {wxSizerItem, setDimension, 2}}, + {1356, {wxSizerItem, setFlag, 1}}, + {1357, {wxSizerItem, setInitSize, 2}}, + {1358, {wxSizerItem, setMinSize_1, 1}}, + {1359, {wxSizerItem, setMinSize_2, 2}}, + {1360, {wxSizerItem, setProportion, 1}}, + {1361, {wxSizerItem, setRatio_2, 2}}, + {1362, {wxSizerItem, setRatio_1_1, 1}}, + {1363, {wxSizerItem, setRatio_1_0, 1}}, + {1364, {wxSizerItem, setSizer, 1}}, + {1365, {wxSizerItem, setSpacer_1, 1}}, + {1366, {wxSizerItem, setSpacer_2, 2}}, + {1367, {wxSizerItem, setWindow, 1}}, + {1368, {wxSizerItem, show, 1}}, + {1369, {wxBoxSizer, new, 1}}, + {1370, {wxBoxSizer, getOrientation, 0}}, + {1371, {wxBoxSizer, 'Destroy', undefined}}, + {1372, {wxStaticBoxSizer, new_2, 2}}, + {1373, {wxStaticBoxSizer, new_3, 3}}, + {1374, {wxStaticBoxSizer, getStaticBox, 0}}, + {1375, {wxStaticBoxSizer, 'Destroy', undefined}}, + {1376, {wxGridSizer, new_4, 4}}, + {1377, {wxGridSizer, new_2, 2}}, + {1378, {wxGridSizer, getCols, 0}}, + {1379, {wxGridSizer, getHGap, 0}}, + {1380, {wxGridSizer, getRows, 0}}, + {1381, {wxGridSizer, getVGap, 0}}, + {1382, {wxGridSizer, setCols, 1}}, + {1383, {wxGridSizer, setHGap, 1}}, + {1384, {wxGridSizer, setRows, 1}}, + {1385, {wxGridSizer, setVGap, 1}}, + {1386, {wxGridSizer, 'Destroy', undefined}}, + {1387, {wxFlexGridSizer, new_4, 4}}, + {1388, {wxFlexGridSizer, new_2, 2}}, + {1389, {wxFlexGridSizer, addGrowableCol, 2}}, + {1390, {wxFlexGridSizer, addGrowableRow, 2}}, + {1391, {wxFlexGridSizer, getFlexibleDirection, 0}}, + {1392, {wxFlexGridSizer, getNonFlexibleGrowMode, 0}}, + {1393, {wxFlexGridSizer, removeGrowableCol, 1}}, + {1394, {wxFlexGridSizer, removeGrowableRow, 1}}, + {1395, {wxFlexGridSizer, setFlexibleDirection, 1}}, + {1396, {wxFlexGridSizer, setNonFlexibleGrowMode, 1}}, + {1397, {wxFlexGridSizer, 'Destroy', undefined}}, + {1398, {wxGridBagSizer, new, 1}}, + {1399, {wxGridBagSizer, add_3_2, 3}}, + {1400, {wxGridBagSizer, add_3_1, 3}}, + {1401, {wxGridBagSizer, add_4, 4}}, + {1402, {wxGridBagSizer, add_1_0, 1}}, + {1403, {wxGridBagSizer, add_2_1, 2}}, + {1404, {wxGridBagSizer, add_2_0, 2}}, + {1405, {wxGridBagSizer, add_3_0, 3}}, + {1406, {wxGridBagSizer, add_1_1, 1}}, + {1407, {wxGridBagSizer, calcMin, 0}}, + {1408, {wxGridBagSizer, checkForIntersection_2, 2}}, + {1409, {wxGridBagSizer, checkForIntersection_3, 3}}, + {1410, {wxGridBagSizer, findItem_1_1, 1}}, + {1411, {wxGridBagSizer, findItem_1_0, 1}}, + {1412, {wxGridBagSizer, findItemAtPoint, 1}}, + {1413, {wxGridBagSizer, findItemAtPosition, 1}}, + {1414, {wxGridBagSizer, findItemWithData, 1}}, + {1415, {wxGridBagSizer, getCellSize, 2}}, + {1416, {wxGridBagSizer, getEmptyCellSize, 0}}, + {1417, {wxGridBagSizer, getItemPosition_1_2, 1}}, + {1418, {wxGridBagSizer, getItemPosition_1_1, 1}}, + {1419, {wxGridBagSizer, getItemPosition_1_0, 1}}, + {1420, {wxGridBagSizer, getItemSpan_1_2, 1}}, + {1421, {wxGridBagSizer, getItemSpan_1_1, 1}}, + {1422, {wxGridBagSizer, getItemSpan_1_0, 1}}, + {1423, {wxGridBagSizer, setEmptyCellSize, 1}}, + {1424, {wxGridBagSizer, setItemPosition_2_2, 2}}, + {1425, {wxGridBagSizer, setItemPosition_2_1, 2}}, + {1426, {wxGridBagSizer, setItemPosition_2_0, 2}}, + {1427, {wxGridBagSizer, setItemSpan_2_2, 2}}, + {1428, {wxGridBagSizer, setItemSpan_2_1, 2}}, + {1429, {wxGridBagSizer, setItemSpan_2_0, 2}}, + {1430, {wxGridBagSizer, 'Destroy', undefined}}, + {1431, {wxStdDialogButtonSizer, new, 0}}, + {1432, {wxStdDialogButtonSizer, addButton, 1}}, + {1433, {wxStdDialogButtonSizer, realize, 0}}, + {1434, {wxStdDialogButtonSizer, setAffirmativeButton, 1}}, + {1435, {wxStdDialogButtonSizer, setCancelButton, 1}}, + {1436, {wxStdDialogButtonSizer, setNegativeButton, 1}}, + {1437, {wxStdDialogButtonSizer, 'Destroy', undefined}}, + {1438, {wxFont, new_0, 0}}, + {1439, {wxFont, new_1, 1}}, + {1440, {wxFont, new_5, 5}}, + {1442, {wxFont, destruct, 0}}, + {1443, {wxFont, isFixedWidth, 0}}, + {1444, {wxFont, getDefaultEncoding, 0}}, + {1445, {wxFont, getFaceName, 0}}, + {1446, {wxFont, getFamily, 0}}, + {1447, {wxFont, getNativeFontInfoDesc, 0}}, + {1448, {wxFont, getNativeFontInfoUserDesc, 0}}, + {1449, {wxFont, getPointSize, 0}}, + {1450, {wxFont, getStyle, 0}}, + {1451, {wxFont, getUnderlined, 0}}, + {1452, {wxFont, getWeight, 0}}, + {1453, {wxFont, ok, 0}}, + {1454, {wxFont, setDefaultEncoding, 1}}, + {1455, {wxFont, setFaceName, 1}}, + {1456, {wxFont, setFamily, 1}}, + {1457, {wxFont, setPointSize, 1}}, + {1458, {wxFont, setStyle, 1}}, + {1459, {wxFont, setUnderlined, 1}}, + {1460, {wxFont, setWeight, 1}}, + {1461, {wxToolTip, enable, 1}}, + {1462, {wxToolTip, setDelay, 1}}, + {1463, {wxToolTip, new, 1}}, + {1464, {wxToolTip, setTip, 1}}, + {1465, {wxToolTip, getTip, 0}}, + {1466, {wxToolTip, getWindow, 0}}, + {1467, {wxToolTip, 'Destroy', undefined}}, + {1469, {wxButton, new_3, 3}}, + {1470, {wxButton, new_0, 0}}, + {1471, {wxButton, destruct, 0}}, + {1472, {wxButton, create, 3}}, + {1473, {wxButton, getDefaultSize, 0}}, + {1474, {wxButton, setDefault, 0}}, + {1475, {wxButton, setLabel, 1}}, + {1477, {wxBitmapButton, new_4, 4}}, + {1478, {wxBitmapButton, new_0, 0}}, + {1479, {wxBitmapButton, create, 4}}, + {1480, {wxBitmapButton, getBitmapDisabled, 0}}, + {1482, {wxBitmapButton, getBitmapFocus, 0}}, + {1484, {wxBitmapButton, getBitmapLabel, 0}}, + {1486, {wxBitmapButton, getBitmapSelected, 0}}, + {1488, {wxBitmapButton, setBitmapDisabled, 1}}, + {1489, {wxBitmapButton, setBitmapFocus, 1}}, + {1490, {wxBitmapButton, setBitmapLabel, 1}}, + {1491, {wxBitmapButton, setBitmapSelected, 1}}, + {1492, {wxBitmapButton, 'Destroy', undefined}}, + {1493, {wxToggleButton, new_0, 0}}, + {1494, {wxToggleButton, new_4, 4}}, + {1495, {wxToggleButton, create, 4}}, + {1496, {wxToggleButton, getValue, 0}}, + {1497, {wxToggleButton, setValue, 1}}, + {1498, {wxToggleButton, 'Destroy', undefined}}, + {1499, {wxCalendarCtrl, new_0, 0}}, + {1500, {wxCalendarCtrl, new_3, 3}}, + {1501, {wxCalendarCtrl, create, 3}}, + {1502, {wxCalendarCtrl, destruct, 0}}, + {1503, {wxCalendarCtrl, setDate, 1}}, + {1504, {wxCalendarCtrl, getDate, 0}}, + {1505, {wxCalendarCtrl, enableYearChange, 1}}, + {1506, {wxCalendarCtrl, enableMonthChange, 1}}, + {1507, {wxCalendarCtrl, enableHolidayDisplay, 1}}, + {1508, {wxCalendarCtrl, setHeaderColours, 2}}, + {1509, {wxCalendarCtrl, getHeaderColourFg, 0}}, + {1510, {wxCalendarCtrl, getHeaderColourBg, 0}}, + {1511, {wxCalendarCtrl, setHighlightColours, 2}}, + {1512, {wxCalendarCtrl, getHighlightColourFg, 0}}, + {1513, {wxCalendarCtrl, getHighlightColourBg, 0}}, + {1514, {wxCalendarCtrl, setHolidayColours, 2}}, + {1515, {wxCalendarCtrl, getHolidayColourFg, 0}}, + {1516, {wxCalendarCtrl, getHolidayColourBg, 0}}, + {1517, {wxCalendarCtrl, getAttr, 1}}, + {1518, {wxCalendarCtrl, setAttr, 2}}, + {1519, {wxCalendarCtrl, setHoliday, 1}}, + {1520, {wxCalendarCtrl, resetAttr, 1}}, + {1521, {wxCalendarCtrl, hitTest, 2}}, + {1522, {wxCalendarDateAttr, new_0, 0}}, + {1523, {wxCalendarDateAttr, new_2_1, 2}}, + {1524, {wxCalendarDateAttr, new_2_0, 2}}, + {1525, {wxCalendarDateAttr, setTextColour, 1}}, + {1526, {wxCalendarDateAttr, setBackgroundColour, 1}}, + {1527, {wxCalendarDateAttr, setBorderColour, 1}}, + {1528, {wxCalendarDateAttr, setFont, 1}}, + {1529, {wxCalendarDateAttr, setBorder, 1}}, + {1530, {wxCalendarDateAttr, setHoliday, 1}}, + {1531, {wxCalendarDateAttr, hasTextColour, 0}}, + {1532, {wxCalendarDateAttr, hasBackgroundColour, 0}}, + {1533, {wxCalendarDateAttr, hasBorderColour, 0}}, + {1534, {wxCalendarDateAttr, hasFont, 0}}, + {1535, {wxCalendarDateAttr, hasBorder, 0}}, + {1536, {wxCalendarDateAttr, isHoliday, 0}}, + {1537, {wxCalendarDateAttr, getTextColour, 0}}, + {1538, {wxCalendarDateAttr, getBackgroundColour, 0}}, + {1539, {wxCalendarDateAttr, getBorderColour, 0}}, + {1540, {wxCalendarDateAttr, getFont, 0}}, + {1541, {wxCalendarDateAttr, getBorder, 0}}, + {1542, {wxCalendarDateAttr, 'Destroy', undefined}}, + {1544, {wxCheckBox, new_4, 4}}, + {1545, {wxCheckBox, new_0, 0}}, + {1546, {wxCheckBox, create, 4}}, + {1547, {wxCheckBox, getValue, 0}}, + {1548, {wxCheckBox, get3StateValue, 0}}, + {1549, {wxCheckBox, is3rdStateAllowedForUser, 0}}, + {1550, {wxCheckBox, is3State, 0}}, + {1551, {wxCheckBox, isChecked, 0}}, + {1552, {wxCheckBox, setValue, 1}}, + {1553, {wxCheckBox, set3StateValue, 1}}, + {1554, {wxCheckBox, 'Destroy', undefined}}, + {1555, {wxCheckListBox, new_0, 0}}, + {1557, {wxCheckListBox, new_3, 3}}, + {1558, {wxCheckListBox, check, 2}}, + {1559, {wxCheckListBox, isChecked, 1}}, + {1560, {wxCheckListBox, 'Destroy', undefined}}, + {1563, {wxChoice, new_3, 3}}, + {1564, {wxChoice, new_0, 0}}, + {1566, {wxChoice, destruct, 0}}, + {1568, {wxChoice, create, 6}}, + {1569, {wxChoice, delete, 1}}, + {1570, {wxChoice, getColumns, 0}}, + {1571, {wxChoice, setColumns, 1}}, + {1572, {wxComboBox, new_0, 0}}, + {1574, {wxComboBox, new_3, 3}}, + {1575, {wxComboBox, destruct, 0}}, + {1577, {wxComboBox, create, 7}}, + {1578, {wxComboBox, canCopy, 0}}, + {1579, {wxComboBox, canCut, 0}}, + {1580, {wxComboBox, canPaste, 0}}, + {1581, {wxComboBox, canRedo, 0}}, + {1582, {wxComboBox, canUndo, 0}}, + {1583, {wxComboBox, copy, 0}}, + {1584, {wxComboBox, cut, 0}}, + {1585, {wxComboBox, getInsertionPoint, 0}}, + {1586, {wxComboBox, getLastPosition, 0}}, + {1587, {wxComboBox, getValue, 0}}, + {1588, {wxComboBox, paste, 0}}, + {1589, {wxComboBox, redo, 0}}, + {1590, {wxComboBox, replace, 3}}, + {1591, {wxComboBox, remove, 2}}, + {1592, {wxComboBox, setInsertionPoint, 1}}, + {1593, {wxComboBox, setInsertionPointEnd, 0}}, + {1594, {wxComboBox, setSelection_1, 1}}, + {1595, {wxComboBox, setSelection_2, 2}}, + {1596, {wxComboBox, setValue, 1}}, + {1597, {wxComboBox, undo, 0}}, + {1598, {wxGauge, new_0, 0}}, + {1599, {wxGauge, new_4, 4}}, + {1600, {wxGauge, create, 4}}, + {1601, {wxGauge, getBezelFace, 0}}, + {1602, {wxGauge, getRange, 0}}, + {1603, {wxGauge, getShadowWidth, 0}}, + {1604, {wxGauge, getValue, 0}}, + {1605, {wxGauge, isVertical, 0}}, + {1606, {wxGauge, setBezelFace, 1}}, + {1607, {wxGauge, setRange, 1}}, + {1608, {wxGauge, setShadowWidth, 1}}, + {1609, {wxGauge, setValue, 1}}, + {1610, {wxGauge, pulse, 0}}, + {1611, {wxGauge, 'Destroy', undefined}}, + {1612, {wxGenericDirCtrl, new_0, 0}}, + {1613, {wxGenericDirCtrl, new_2, 2}}, + {1614, {wxGenericDirCtrl, destruct, 0}}, + {1615, {wxGenericDirCtrl, create, 2}}, + {1616, {wxGenericDirCtrl, init, 0}}, + {1617, {wxGenericDirCtrl, collapseTree, 0}}, + {1618, {wxGenericDirCtrl, expandPath, 1}}, + {1619, {wxGenericDirCtrl, getDefaultPath, 0}}, + {1620, {wxGenericDirCtrl, getPath, 0}}, + {1621, {wxGenericDirCtrl, getFilePath, 0}}, + {1622, {wxGenericDirCtrl, getFilter, 0}}, + {1623, {wxGenericDirCtrl, getFilterIndex, 0}}, + {1624, {wxGenericDirCtrl, getRootId, 0}}, + {1625, {wxGenericDirCtrl, getTreeCtrl, 0}}, + {1626, {wxGenericDirCtrl, reCreateTree, 0}}, + {1627, {wxGenericDirCtrl, setDefaultPath, 1}}, + {1628, {wxGenericDirCtrl, setFilter, 1}}, + {1629, {wxGenericDirCtrl, setFilterIndex, 1}}, + {1630, {wxGenericDirCtrl, setPath, 1}}, + {1632, {wxStaticBox, new_4, 4}}, + {1633, {wxStaticBox, new_0, 0}}, + {1634, {wxStaticBox, create, 4}}, + {1635, {wxStaticBox, 'Destroy', undefined}}, + {1637, {wxStaticLine, new_2, 2}}, + {1638, {wxStaticLine, new_0, 0}}, + {1639, {wxStaticLine, create, 2}}, + {1640, {wxStaticLine, isVertical, 0}}, + {1641, {wxStaticLine, getDefaultSize, 0}}, + {1642, {wxStaticLine, 'Destroy', undefined}}, + {1645, {wxListBox, new_3, 3}}, + {1646, {wxListBox, new_0, 0}}, + {1648, {wxListBox, destruct, 0}}, + {1650, {wxListBox, create, 6}}, + {1651, {wxListBox, deselect, 1}}, + {1652, {wxListBox, getSelections, 1}}, + {1653, {wxListBox, insertItems, 2}}, + {1654, {wxListBox, isSelected, 1}}, + {1655, {wxListBox, set, 1}}, + {1656, {wxListBox, hitTest, 1}}, + {1657, {wxListBox, setFirstItem_1_0, 1}}, + {1658, {wxListBox, setFirstItem_1_1, 1}}, + {1659, {wxListCtrl, new_0, 0}}, + {1660, {wxListCtrl, new_2, 2}}, + {1661, {wxListCtrl, arrange, 1}}, + {1662, {wxListCtrl, assignImageList, 2}}, + {1663, {wxListCtrl, clearAll, 0}}, + {1664, {wxListCtrl, create, 2}}, + {1665, {wxListCtrl, deleteAllItems, 0}}, + {1666, {wxListCtrl, deleteColumn, 1}}, + {1667, {wxListCtrl, deleteItem, 1}}, + {1668, {wxListCtrl, editLabel, 1}}, + {1669, {wxListCtrl, ensureVisible, 1}}, + {1670, {wxListCtrl, findItem_3_0, 3}}, + {1671, {wxListCtrl, findItem_3_1, 3}}, + {1672, {wxListCtrl, getColumn, 2}}, + {1673, {wxListCtrl, getColumnCount, 0}}, + {1674, {wxListCtrl, getColumnWidth, 1}}, + {1675, {wxListCtrl, getCountPerPage, 0}}, + {1676, {wxListCtrl, getEditControl, 0}}, + {1677, {wxListCtrl, getImageList, 1}}, + {1678, {wxListCtrl, getItem, 1}}, + {1679, {wxListCtrl, getItemBackgroundColour, 1}}, + {1680, {wxListCtrl, getItemCount, 0}}, + {1681, {wxListCtrl, getItemData, 1}}, + {1682, {wxListCtrl, getItemFont, 1}}, + {1683, {wxListCtrl, getItemPosition, 2}}, + {1684, {wxListCtrl, getItemRect, 3}}, + {1685, {wxListCtrl, getItemSpacing, 0}}, + {1686, {wxListCtrl, getItemState, 2}}, + {1687, {wxListCtrl, getItemText, 1}}, + {1688, {wxListCtrl, getItemTextColour, 1}}, + {1689, {wxListCtrl, getNextItem, 2}}, + {1690, {wxListCtrl, getSelectedItemCount, 0}}, + {1691, {wxListCtrl, getTextColour, 0}}, + {1692, {wxListCtrl, getTopItem, 0}}, + {1693, {wxListCtrl, getViewRect, 0}}, + {1694, {wxListCtrl, hitTest, 2}}, + {1695, {wxListCtrl, insertColumn_2, 2}}, + {1696, {wxListCtrl, insertColumn_3, 3}}, + {1697, {wxListCtrl, insertItem_1, 1}}, + {1698, {wxListCtrl, insertItem_2_1, 2}}, + {1699, {wxListCtrl, insertItem_2_0, 2}}, + {1700, {wxListCtrl, insertItem_3, 3}}, + {1701, {wxListCtrl, refreshItem, 1}}, + {1702, {wxListCtrl, refreshItems, 2}}, + {1703, {wxListCtrl, scrollList, 2}}, + {1704, {wxListCtrl, setBackgroundColour, 1}}, + {1705, {wxListCtrl, setColumn, 2}}, + {1706, {wxListCtrl, setColumnWidth, 2}}, + {1707, {wxListCtrl, setImageList, 2}}, + {1708, {wxListCtrl, setItem_1, 1}}, + {1709, {wxListCtrl, setItem_4, 4}}, + {1710, {wxListCtrl, setItemBackgroundColour, 2}}, + {1711, {wxListCtrl, setItemCount, 1}}, + {1712, {wxListCtrl, setItemData, 2}}, + {1713, {wxListCtrl, setItemFont, 2}}, + {1714, {wxListCtrl, setItemImage, 3}}, + {1715, {wxListCtrl, setItemColumnImage, 3}}, + {1716, {wxListCtrl, setItemPosition, 2}}, + {1717, {wxListCtrl, setItemState, 3}}, + {1718, {wxListCtrl, setItemText, 2}}, + {1719, {wxListCtrl, setItemTextColour, 2}}, + {1720, {wxListCtrl, setSingleStyle, 2}}, + {1721, {wxListCtrl, setTextColour, 1}}, + {1722, {wxListCtrl, setWindowStyleFlag, 1}}, + {1723, {wxListCtrl, sortItems, 2}}, + {1724, {wxListCtrl, 'Destroy', undefined}}, + {1725, {wxListView, clearColumnImage, 1}}, + {1726, {wxListView, focus, 1}}, + {1727, {wxListView, getFirstSelected, 0}}, + {1728, {wxListView, getFocusedItem, 0}}, + {1729, {wxListView, getNextSelected, 1}}, + {1730, {wxListView, isSelected, 1}}, + {1731, {wxListView, select, 2}}, + {1732, {wxListView, setColumnImage, 2}}, + {1733, {wxListItem, new_0, 0}}, + {1734, {wxListItem, new_1, 1}}, + {1735, {wxListItem, destruct, 0}}, + {1736, {wxListItem, clear, 0}}, + {1737, {wxListItem, getAlign, 0}}, + {1738, {wxListItem, getBackgroundColour, 0}}, + {1739, {wxListItem, getColumn, 0}}, + {1740, {wxListItem, getFont, 0}}, + {1741, {wxListItem, getId, 0}}, + {1742, {wxListItem, getImage, 0}}, + {1743, {wxListItem, getMask, 0}}, + {1744, {wxListItem, getState, 0}}, + {1745, {wxListItem, getText, 0}}, + {1746, {wxListItem, getTextColour, 0}}, + {1747, {wxListItem, getWidth, 0}}, + {1748, {wxListItem, setAlign, 1}}, + {1749, {wxListItem, setBackgroundColour, 1}}, + {1750, {wxListItem, setColumn, 1}}, + {1751, {wxListItem, setFont, 1}}, + {1752, {wxListItem, setId, 1}}, + {1753, {wxListItem, setImage, 1}}, + {1754, {wxListItem, setMask, 1}}, + {1755, {wxListItem, setState, 1}}, + {1756, {wxListItem, setStateMask, 1}}, + {1757, {wxListItem, setText, 1}}, + {1758, {wxListItem, setTextColour, 1}}, + {1759, {wxListItem, setWidth, 1}}, + {1760, {wxListItemAttr, new_0, 0}}, + {1761, {wxListItemAttr, new_3, 3}}, + {1762, {wxListItemAttr, getBackgroundColour, 0}}, + {1763, {wxListItemAttr, getFont, 0}}, + {1764, {wxListItemAttr, getTextColour, 0}}, + {1765, {wxListItemAttr, hasBackgroundColour, 0}}, + {1766, {wxListItemAttr, hasFont, 0}}, + {1767, {wxListItemAttr, hasTextColour, 0}}, + {1768, {wxListItemAttr, setBackgroundColour, 1}}, + {1769, {wxListItemAttr, setFont, 1}}, + {1770, {wxListItemAttr, setTextColour, 1}}, + {1771, {wxListItemAttr, 'Destroy', undefined}}, + {1772, {wxImageList, new_0, 0}}, + {1773, {wxImageList, new_3, 3}}, + {1774, {wxImageList, add_1, 1}}, + {1775, {wxImageList, add_2_0, 2}}, + {1776, {wxImageList, add_2_1, 2}}, + {1777, {wxImageList, create, 3}}, + {1779, {wxImageList, draw, 5}}, + {1780, {wxImageList, getBitmap, 1}}, + {1781, {wxImageList, getIcon, 1}}, + {1782, {wxImageList, getImageCount, 0}}, + {1783, {wxImageList, getSize, 3}}, + {1784, {wxImageList, remove, 1}}, + {1785, {wxImageList, removeAll, 0}}, + {1786, {wxImageList, replace_2, 2}}, + {1787, {wxImageList, replace_3, 3}}, + {1788, {wxImageList, 'Destroy', undefined}}, + {1789, {wxTextAttr, new_0, 0}}, + {1790, {wxTextAttr, new_2, 2}}, + {1791, {wxTextAttr, getAlignment, 0}}, + {1792, {wxTextAttr, getBackgroundColour, 0}}, + {1793, {wxTextAttr, getFont, 0}}, + {1794, {wxTextAttr, getLeftIndent, 0}}, + {1795, {wxTextAttr, getLeftSubIndent, 0}}, + {1796, {wxTextAttr, getRightIndent, 0}}, + {1797, {wxTextAttr, getTabs, 0}}, + {1798, {wxTextAttr, getTextColour, 0}}, + {1799, {wxTextAttr, hasBackgroundColour, 0}}, + {1800, {wxTextAttr, hasFont, 0}}, + {1801, {wxTextAttr, hasTextColour, 0}}, + {1802, {wxTextAttr, getFlags, 0}}, + {1803, {wxTextAttr, isDefault, 0}}, + {1804, {wxTextAttr, setAlignment, 1}}, + {1805, {wxTextAttr, setBackgroundColour, 1}}, + {1806, {wxTextAttr, setFlags, 1}}, + {1807, {wxTextAttr, setFont, 2}}, + {1808, {wxTextAttr, setLeftIndent, 2}}, + {1809, {wxTextAttr, setRightIndent, 1}}, + {1810, {wxTextAttr, setTabs, 1}}, + {1811, {wxTextAttr, setTextColour, 1}}, + {1812, {wxTextAttr, 'Destroy', undefined}}, + {1814, {wxTextCtrl, new_3, 3}}, + {1815, {wxTextCtrl, new_0, 0}}, + {1817, {wxTextCtrl, destruct, 0}}, + {1818, {wxTextCtrl, appendText, 1}}, + {1819, {wxTextCtrl, canCopy, 0}}, + {1820, {wxTextCtrl, canCut, 0}}, + {1821, {wxTextCtrl, canPaste, 0}}, + {1822, {wxTextCtrl, canRedo, 0}}, + {1823, {wxTextCtrl, canUndo, 0}}, + {1824, {wxTextCtrl, clear, 0}}, + {1825, {wxTextCtrl, copy, 0}}, + {1826, {wxTextCtrl, create, 3}}, + {1827, {wxTextCtrl, cut, 0}}, + {1828, {wxTextCtrl, discardEdits, 0}}, + {1829, {wxTextCtrl, changeValue, 1}}, + {1830, {wxTextCtrl, emulateKeyPress, 1}}, + {1831, {wxTextCtrl, getDefaultStyle, 0}}, + {1832, {wxTextCtrl, getInsertionPoint, 0}}, + {1833, {wxTextCtrl, getLastPosition, 0}}, + {1834, {wxTextCtrl, getLineLength, 1}}, + {1835, {wxTextCtrl, getLineText, 1}}, + {1836, {wxTextCtrl, getNumberOfLines, 0}}, + {1837, {wxTextCtrl, getRange, 2}}, + {1838, {wxTextCtrl, getSelection, 2}}, + {1839, {wxTextCtrl, getStringSelection, 0}}, + {1840, {wxTextCtrl, getStyle, 2}}, + {1841, {wxTextCtrl, getValue, 0}}, + {1842, {wxTextCtrl, isEditable, 0}}, + {1843, {wxTextCtrl, isModified, 0}}, + {1844, {wxTextCtrl, isMultiLine, 0}}, + {1845, {wxTextCtrl, isSingleLine, 0}}, + {1846, {wxTextCtrl, loadFile, 2}}, + {1847, {wxTextCtrl, markDirty, 0}}, + {1848, {wxTextCtrl, paste, 0}}, + {1849, {wxTextCtrl, positionToXY, 3}}, + {1850, {wxTextCtrl, redo, 0}}, + {1851, {wxTextCtrl, remove, 2}}, + {1852, {wxTextCtrl, replace, 3}}, + {1853, {wxTextCtrl, saveFile, 1}}, + {1854, {wxTextCtrl, setDefaultStyle, 1}}, + {1855, {wxTextCtrl, setEditable, 1}}, + {1856, {wxTextCtrl, setInsertionPoint, 1}}, + {1857, {wxTextCtrl, setInsertionPointEnd, 0}}, + {1859, {wxTextCtrl, setMaxLength, 1}}, + {1860, {wxTextCtrl, setSelection, 2}}, + {1861, {wxTextCtrl, setStyle, 3}}, + {1862, {wxTextCtrl, setValue, 1}}, + {1863, {wxTextCtrl, showPosition, 1}}, + {1864, {wxTextCtrl, undo, 0}}, + {1865, {wxTextCtrl, writeText, 1}}, + {1866, {wxTextCtrl, xYToPosition, 2}}, + {1869, {wxNotebook, new_0, 0}}, + {1870, {wxNotebook, new_3, 3}}, + {1871, {wxNotebook, destruct, 0}}, + {1872, {wxNotebook, addPage, 3}}, + {1873, {wxNotebook, advanceSelection, 1}}, + {1874, {wxNotebook, assignImageList, 1}}, + {1875, {wxNotebook, create, 3}}, + {1876, {wxNotebook, deleteAllPages, 0}}, + {1877, {wxNotebook, deletePage, 1}}, + {1878, {wxNotebook, removePage, 1}}, + {1879, {wxNotebook, getCurrentPage, 0}}, + {1880, {wxNotebook, getImageList, 0}}, + {1882, {wxNotebook, getPage, 1}}, + {1883, {wxNotebook, getPageCount, 0}}, + {1884, {wxNotebook, getPageImage, 1}}, + {1885, {wxNotebook, getPageText, 1}}, + {1886, {wxNotebook, getRowCount, 0}}, + {1887, {wxNotebook, getSelection, 0}}, + {1888, {wxNotebook, getThemeBackgroundColour, 0}}, + {1890, {wxNotebook, hitTest, 2}}, + {1892, {wxNotebook, insertPage, 4}}, + {1893, {wxNotebook, setImageList, 1}}, + {1894, {wxNotebook, setPadding, 1}}, + {1895, {wxNotebook, setPageSize, 1}}, + {1896, {wxNotebook, setPageImage, 2}}, + {1897, {wxNotebook, setPageText, 2}}, + {1898, {wxNotebook, setSelection, 1}}, + {1899, {wxNotebook, changeSelection, 1}}, + {1900, {wxChoicebook, new_0, 0}}, + {1901, {wxChoicebook, new_3, 3}}, + {1902, {wxChoicebook, addPage, 3}}, + {1903, {wxChoicebook, advanceSelection, 1}}, + {1904, {wxChoicebook, assignImageList, 1}}, + {1905, {wxChoicebook, create, 3}}, + {1906, {wxChoicebook, deleteAllPages, 0}}, + {1907, {wxChoicebook, deletePage, 1}}, + {1908, {wxChoicebook, removePage, 1}}, + {1909, {wxChoicebook, getCurrentPage, 0}}, + {1910, {wxChoicebook, getImageList, 0}}, + {1912, {wxChoicebook, getPage, 1}}, + {1913, {wxChoicebook, getPageCount, 0}}, + {1914, {wxChoicebook, getPageImage, 1}}, + {1915, {wxChoicebook, getPageText, 1}}, + {1916, {wxChoicebook, getSelection, 0}}, + {1917, {wxChoicebook, hitTest, 2}}, + {1918, {wxChoicebook, insertPage, 4}}, + {1919, {wxChoicebook, setImageList, 1}}, + {1920, {wxChoicebook, setPageSize, 1}}, + {1921, {wxChoicebook, setPageImage, 2}}, + {1922, {wxChoicebook, setPageText, 2}}, + {1923, {wxChoicebook, setSelection, 1}}, + {1924, {wxChoicebook, changeSelection, 1}}, + {1925, {wxChoicebook, 'Destroy', undefined}}, + {1926, {wxToolbook, new_0, 0}}, + {1927, {wxToolbook, new_3, 3}}, + {1928, {wxToolbook, addPage, 3}}, + {1929, {wxToolbook, advanceSelection, 1}}, + {1930, {wxToolbook, assignImageList, 1}}, + {1931, {wxToolbook, create, 3}}, + {1932, {wxToolbook, deleteAllPages, 0}}, + {1933, {wxToolbook, deletePage, 1}}, + {1934, {wxToolbook, removePage, 1}}, + {1935, {wxToolbook, getCurrentPage, 0}}, + {1936, {wxToolbook, getImageList, 0}}, + {1938, {wxToolbook, getPage, 1}}, + {1939, {wxToolbook, getPageCount, 0}}, + {1940, {wxToolbook, getPageImage, 1}}, + {1941, {wxToolbook, getPageText, 1}}, + {1942, {wxToolbook, getSelection, 0}}, + {1944, {wxToolbook, hitTest, 2}}, + {1945, {wxToolbook, insertPage, 4}}, + {1946, {wxToolbook, setImageList, 1}}, + {1947, {wxToolbook, setPageSize, 1}}, + {1948, {wxToolbook, setPageImage, 2}}, + {1949, {wxToolbook, setPageText, 2}}, + {1950, {wxToolbook, setSelection, 1}}, + {1951, {wxToolbook, changeSelection, 1}}, + {1952, {wxToolbook, 'Destroy', undefined}}, + {1953, {wxListbook, new_0, 0}}, + {1954, {wxListbook, new_3, 3}}, + {1955, {wxListbook, addPage, 3}}, + {1956, {wxListbook, advanceSelection, 1}}, + {1957, {wxListbook, assignImageList, 1}}, + {1958, {wxListbook, create, 3}}, + {1959, {wxListbook, deleteAllPages, 0}}, + {1960, {wxListbook, deletePage, 1}}, + {1961, {wxListbook, removePage, 1}}, + {1962, {wxListbook, getCurrentPage, 0}}, + {1963, {wxListbook, getImageList, 0}}, + {1965, {wxListbook, getPage, 1}}, + {1966, {wxListbook, getPageCount, 0}}, + {1967, {wxListbook, getPageImage, 1}}, + {1968, {wxListbook, getPageText, 1}}, + {1969, {wxListbook, getSelection, 0}}, + {1971, {wxListbook, hitTest, 2}}, + {1972, {wxListbook, insertPage, 4}}, + {1973, {wxListbook, setImageList, 1}}, + {1974, {wxListbook, setPageSize, 1}}, + {1975, {wxListbook, setPageImage, 2}}, + {1976, {wxListbook, setPageText, 2}}, + {1977, {wxListbook, setSelection, 1}}, + {1978, {wxListbook, changeSelection, 1}}, + {1979, {wxListbook, 'Destroy', undefined}}, + {1980, {wxTreebook, new_0, 0}}, + {1981, {wxTreebook, new_3, 3}}, + {1982, {wxTreebook, addPage, 3}}, + {1983, {wxTreebook, advanceSelection, 1}}, + {1984, {wxTreebook, assignImageList, 1}}, + {1985, {wxTreebook, create, 3}}, + {1986, {wxTreebook, deleteAllPages, 0}}, + {1987, {wxTreebook, deletePage, 1}}, + {1988, {wxTreebook, removePage, 1}}, + {1989, {wxTreebook, getCurrentPage, 0}}, + {1990, {wxTreebook, getImageList, 0}}, + {1992, {wxTreebook, getPage, 1}}, + {1993, {wxTreebook, getPageCount, 0}}, + {1994, {wxTreebook, getPageImage, 1}}, + {1995, {wxTreebook, getPageText, 1}}, + {1996, {wxTreebook, getSelection, 0}}, + {1997, {wxTreebook, expandNode, 2}}, + {1998, {wxTreebook, isNodeExpanded, 1}}, + {2000, {wxTreebook, hitTest, 2}}, + {2001, {wxTreebook, insertPage, 4}}, + {2002, {wxTreebook, insertSubPage, 4}}, + {2003, {wxTreebook, setImageList, 1}}, + {2004, {wxTreebook, setPageSize, 1}}, + {2005, {wxTreebook, setPageImage, 2}}, + {2006, {wxTreebook, setPageText, 2}}, + {2007, {wxTreebook, setSelection, 1}}, + {2008, {wxTreebook, changeSelection, 1}}, + {2009, {wxTreebook, 'Destroy', undefined}}, + {2012, {wxTreeCtrl, new_2, 2}}, + {2013, {wxTreeCtrl, new_0, 0}}, + {2015, {wxTreeCtrl, destruct, 0}}, + {2016, {wxTreeCtrl, addRoot, 2}}, + {2017, {wxTreeCtrl, appendItem, 3}}, + {2018, {wxTreeCtrl, assignImageList, 1}}, + {2019, {wxTreeCtrl, assignStateImageList, 1}}, + {2020, {wxTreeCtrl, collapse, 1}}, + {2021, {wxTreeCtrl, collapseAndReset, 1}}, + {2022, {wxTreeCtrl, create, 2}}, + {2023, {wxTreeCtrl, delete, 1}}, + {2024, {wxTreeCtrl, deleteAllItems, 0}}, + {2025, {wxTreeCtrl, deleteChildren, 1}}, + {2026, {wxTreeCtrl, editLabel, 1}}, + {2027, {wxTreeCtrl, ensureVisible, 1}}, + {2028, {wxTreeCtrl, expand, 1}}, + {2029, {wxTreeCtrl, getBoundingRect, 3}}, + {2031, {wxTreeCtrl, getChildrenCount, 2}}, + {2032, {wxTreeCtrl, getCount, 0}}, + {2033, {wxTreeCtrl, getEditControl, 0}}, + {2034, {wxTreeCtrl, getFirstChild, 2}}, + {2035, {wxTreeCtrl, getNextChild, 2}}, + {2036, {wxTreeCtrl, getFirstVisibleItem, 0}}, + {2037, {wxTreeCtrl, getImageList, 0}}, + {2038, {wxTreeCtrl, getIndent, 0}}, + {2039, {wxTreeCtrl, getItemBackgroundColour, 1}}, + {2040, {wxTreeCtrl, getItemData, 1}}, + {2041, {wxTreeCtrl, getItemFont, 1}}, + {2042, {wxTreeCtrl, getItemImage_1, 1}}, + {2043, {wxTreeCtrl, getItemImage_2, 2}}, + {2044, {wxTreeCtrl, getItemText, 1}}, + {2045, {wxTreeCtrl, getItemTextColour, 1}}, + {2046, {wxTreeCtrl, getLastChild, 1}}, + {2047, {wxTreeCtrl, getNextSibling, 1}}, + {2048, {wxTreeCtrl, getNextVisible, 1}}, + {2049, {wxTreeCtrl, getItemParent, 1}}, + {2050, {wxTreeCtrl, getPrevSibling, 1}}, + {2051, {wxTreeCtrl, getPrevVisible, 1}}, + {2052, {wxTreeCtrl, getRootItem, 0}}, + {2053, {wxTreeCtrl, getSelection, 0}}, + {2054, {wxTreeCtrl, getSelections, 1}}, + {2055, {wxTreeCtrl, getStateImageList, 0}}, + {2056, {wxTreeCtrl, hitTest, 2}}, + {2058, {wxTreeCtrl, insertItem, 4}}, + {2059, {wxTreeCtrl, isBold, 1}}, + {2060, {wxTreeCtrl, isExpanded, 1}}, + {2061, {wxTreeCtrl, isSelected, 1}}, + {2062, {wxTreeCtrl, isVisible, 1}}, + {2063, {wxTreeCtrl, itemHasChildren, 1}}, + {2064, {wxTreeCtrl, isTreeItemIdOk, 1}}, + {2065, {wxTreeCtrl, prependItem, 3}}, + {2066, {wxTreeCtrl, scrollTo, 1}}, + {2067, {wxTreeCtrl, selectItem_1, 1}}, + {2068, {wxTreeCtrl, selectItem_2, 2}}, + {2069, {wxTreeCtrl, setIndent, 1}}, + {2070, {wxTreeCtrl, setImageList, 1}}, + {2071, {wxTreeCtrl, setItemBackgroundColour, 2}}, + {2072, {wxTreeCtrl, setItemBold, 2}}, + {2073, {wxTreeCtrl, setItemData, 2}}, + {2074, {wxTreeCtrl, setItemDropHighlight, 2}}, + {2075, {wxTreeCtrl, setItemFont, 2}}, + {2076, {wxTreeCtrl, setItemHasChildren, 2}}, + {2077, {wxTreeCtrl, setItemImage_2, 2}}, + {2078, {wxTreeCtrl, setItemImage_3, 3}}, + {2079, {wxTreeCtrl, setItemText, 2}}, + {2080, {wxTreeCtrl, setItemTextColour, 2}}, + {2081, {wxTreeCtrl, setStateImageList, 1}}, + {2082, {wxTreeCtrl, setWindowStyle, 1}}, + {2083, {wxTreeCtrl, sortChildren, 1}}, + {2084, {wxTreeCtrl, toggle, 1}}, + {2085, {wxTreeCtrl, toggleItemSelection, 1}}, + {2086, {wxTreeCtrl, unselect, 0}}, + {2087, {wxTreeCtrl, unselectAll, 0}}, + {2088, {wxTreeCtrl, unselectItem, 1}}, + {2089, {wxScrollBar, new_0, 0}}, + {2090, {wxScrollBar, new_3, 3}}, + {2091, {wxScrollBar, destruct, 0}}, + {2092, {wxScrollBar, create, 3}}, + {2093, {wxScrollBar, getRange, 0}}, + {2094, {wxScrollBar, getPageSize, 0}}, + {2095, {wxScrollBar, getThumbPosition, 0}}, + {2096, {wxScrollBar, getThumbSize, 0}}, + {2097, {wxScrollBar, setThumbPosition, 1}}, + {2098, {wxScrollBar, setScrollbar, 5}}, + {2100, {wxSpinButton, new_2, 2}}, + {2101, {wxSpinButton, new_0, 0}}, + {2102, {wxSpinButton, create, 2}}, + {2103, {wxSpinButton, getMax, 0}}, + {2104, {wxSpinButton, getMin, 0}}, + {2105, {wxSpinButton, getValue, 0}}, + {2106, {wxSpinButton, setRange, 2}}, + {2107, {wxSpinButton, setValue, 1}}, + {2108, {wxSpinButton, 'Destroy', undefined}}, + {2109, {wxSpinCtrl, new_0, 0}}, + {2110, {wxSpinCtrl, new_2, 2}}, + {2112, {wxSpinCtrl, create, 2}}, + {2115, {wxSpinCtrl, setValue_1_1, 1}}, + {2116, {wxSpinCtrl, setValue_1_0, 1}}, + {2118, {wxSpinCtrl, getValue, 0}}, + {2120, {wxSpinCtrl, setRange, 2}}, + {2121, {wxSpinCtrl, setSelection, 2}}, + {2123, {wxSpinCtrl, getMin, 0}}, + {2125, {wxSpinCtrl, getMax, 0}}, + {2126, {wxSpinCtrl, 'Destroy', undefined}}, + {2127, {wxStaticText, new_0, 0}}, + {2128, {wxStaticText, new_4, 4}}, + {2129, {wxStaticText, create, 4}}, + {2130, {wxStaticText, getLabel, 0}}, + {2131, {wxStaticText, setLabel, 1}}, + {2132, {wxStaticText, wrap, 1}}, + {2133, {wxStaticText, 'Destroy', undefined}}, + {2134, {wxStaticBitmap, new_0, 0}}, + {2135, {wxStaticBitmap, new_4, 4}}, + {2136, {wxStaticBitmap, create, 4}}, + {2137, {wxStaticBitmap, getBitmap, 0}}, + {2138, {wxStaticBitmap, setBitmap, 1}}, + {2139, {wxStaticBitmap, 'Destroy', undefined}}, + {2140, {wxRadioBox, new, 7}}, + {2142, {wxRadioBox, destruct, 0}}, + {2143, {wxRadioBox, create, 7}}, + {2144, {wxRadioBox, enable_2, 2}}, + {2145, {wxRadioBox, enable_1, 1}}, + {2146, {wxRadioBox, getSelection, 0}}, + {2147, {wxRadioBox, getString, 1}}, + {2148, {wxRadioBox, setSelection, 1}}, + {2149, {wxRadioBox, show_2, 2}}, + {2150, {wxRadioBox, show_1, 1}}, + {2151, {wxRadioBox, getColumnCount, 0}}, + {2152, {wxRadioBox, getItemHelpText, 1}}, + {2153, {wxRadioBox, getItemToolTip, 1}}, + {2155, {wxRadioBox, getItemFromPoint, 1}}, + {2156, {wxRadioBox, getRowCount, 0}}, + {2157, {wxRadioBox, isItemEnabled, 1}}, + {2158, {wxRadioBox, isItemShown, 1}}, + {2159, {wxRadioBox, setItemHelpText, 2}}, + {2160, {wxRadioBox, setItemToolTip, 2}}, + {2161, {wxRadioButton, new_0, 0}}, + {2162, {wxRadioButton, new_4, 4}}, + {2163, {wxRadioButton, create, 4}}, + {2164, {wxRadioButton, getValue, 0}}, + {2165, {wxRadioButton, setValue, 1}}, + {2166, {wxRadioButton, 'Destroy', undefined}}, + {2168, {wxSlider, new_6, 6}}, + {2169, {wxSlider, new_0, 0}}, + {2170, {wxSlider, create, 6}}, + {2171, {wxSlider, getLineSize, 0}}, + {2172, {wxSlider, getMax, 0}}, + {2173, {wxSlider, getMin, 0}}, + {2174, {wxSlider, getPageSize, 0}}, + {2175, {wxSlider, getThumbLength, 0}}, + {2176, {wxSlider, getValue, 0}}, + {2177, {wxSlider, setLineSize, 1}}, + {2178, {wxSlider, setPageSize, 1}}, + {2179, {wxSlider, setRange, 2}}, + {2180, {wxSlider, setThumbLength, 1}}, + {2181, {wxSlider, setValue, 1}}, + {2182, {wxSlider, 'Destroy', undefined}}, + {2184, {wxDialog, new_4, 4}}, + {2185, {wxDialog, new_0, 0}}, + {2187, {wxDialog, destruct, 0}}, + {2188, {wxDialog, create, 4}}, + {2189, {wxDialog, createButtonSizer, 1}}, + {2190, {wxDialog, createStdDialogButtonSizer, 1}}, + {2191, {wxDialog, endModal, 1}}, + {2192, {wxDialog, getAffirmativeId, 0}}, + {2193, {wxDialog, getReturnCode, 0}}, + {2194, {wxDialog, isModal, 0}}, + {2195, {wxDialog, setAffirmativeId, 1}}, + {2196, {wxDialog, setReturnCode, 1}}, + {2197, {wxDialog, show, 1}}, + {2198, {wxDialog, showModal, 0}}, + {2199, {wxColourDialog, new_0, 0}}, + {2200, {wxColourDialog, new_2, 2}}, + {2201, {wxColourDialog, destruct, 0}}, + {2202, {wxColourDialog, create, 2}}, + {2203, {wxColourDialog, getColourData, 0}}, + {2204, {wxColourData, new_0, 0}}, + {2205, {wxColourData, new_1, 1}}, + {2206, {wxColourData, destruct, 0}}, + {2207, {wxColourData, getChooseFull, 0}}, + {2208, {wxColourData, getColour, 0}}, + {2210, {wxColourData, getCustomColour, 1}}, + {2211, {wxColourData, setChooseFull, 1}}, + {2212, {wxColourData, setColour, 1}}, + {2213, {wxColourData, setCustomColour, 2}}, + {2214, {wxPalette, new_0, 0}}, + {2215, {wxPalette, new_4, 4}}, + {2217, {wxPalette, destruct, 0}}, + {2218, {wxPalette, create, 4}}, + {2219, {wxPalette, getColoursCount, 0}}, + {2220, {wxPalette, getPixel, 3}}, + {2221, {wxPalette, getRGB, 4}}, + {2222, {wxPalette, isOk, 0}}, + {2226, {wxDirDialog, new, 2}}, + {2227, {wxDirDialog, destruct, 0}}, + {2228, {wxDirDialog, getPath, 0}}, + {2229, {wxDirDialog, getMessage, 0}}, + {2230, {wxDirDialog, setMessage, 1}}, + {2231, {wxDirDialog, setPath, 1}}, + {2235, {wxFileDialog, new, 2}}, + {2236, {wxFileDialog, destruct, 0}}, + {2237, {wxFileDialog, getDirectory, 0}}, + {2238, {wxFileDialog, getFilename, 0}}, + {2239, {wxFileDialog, getFilenames, 1}}, + {2240, {wxFileDialog, getFilterIndex, 0}}, + {2241, {wxFileDialog, getMessage, 0}}, + {2242, {wxFileDialog, getPath, 0}}, + {2243, {wxFileDialog, getPaths, 1}}, + {2244, {wxFileDialog, getWildcard, 0}}, + {2245, {wxFileDialog, setDirectory, 1}}, + {2246, {wxFileDialog, setFilename, 1}}, + {2247, {wxFileDialog, setFilterIndex, 1}}, + {2248, {wxFileDialog, setMessage, 1}}, + {2249, {wxFileDialog, setPath, 1}}, + {2250, {wxFileDialog, setWildcard, 1}}, + {2251, {wxPickerBase, setInternalMargin, 1}}, + {2252, {wxPickerBase, getInternalMargin, 0}}, + {2253, {wxPickerBase, setTextCtrlProportion, 1}}, + {2254, {wxPickerBase, setPickerCtrlProportion, 1}}, + {2255, {wxPickerBase, getTextCtrlProportion, 0}}, + {2256, {wxPickerBase, getPickerCtrlProportion, 0}}, + {2257, {wxPickerBase, hasTextCtrl, 0}}, + {2258, {wxPickerBase, getTextCtrl, 0}}, + {2259, {wxPickerBase, isTextCtrlGrowable, 0}}, + {2260, {wxPickerBase, setPickerCtrlGrowable, 1}}, + {2261, {wxPickerBase, setTextCtrlGrowable, 1}}, + {2262, {wxPickerBase, isPickerCtrlGrowable, 0}}, + {2263, {wxFilePickerCtrl, new_0, 0}}, + {2264, {wxFilePickerCtrl, new_3, 3}}, + {2265, {wxFilePickerCtrl, create, 3}}, + {2266, {wxFilePickerCtrl, getPath, 0}}, + {2267, {wxFilePickerCtrl, setPath, 1}}, + {2268, {wxFilePickerCtrl, 'Destroy', undefined}}, + {2269, {wxDirPickerCtrl, new_0, 0}}, + {2270, {wxDirPickerCtrl, new_3, 3}}, + {2271, {wxDirPickerCtrl, create, 3}}, + {2272, {wxDirPickerCtrl, getPath, 0}}, + {2273, {wxDirPickerCtrl, setPath, 1}}, + {2274, {wxDirPickerCtrl, 'Destroy', undefined}}, + {2275, {wxColourPickerCtrl, new_0, 0}}, + {2276, {wxColourPickerCtrl, new_3, 3}}, + {2277, {wxColourPickerCtrl, create, 3}}, + {2278, {wxColourPickerCtrl, getColour, 0}}, + {2279, {wxColourPickerCtrl, setColour_1_1, 1}}, + {2280, {wxColourPickerCtrl, setColour_1_0, 1}}, + {2281, {wxColourPickerCtrl, 'Destroy', undefined}}, + {2282, {wxDatePickerCtrl, new_0, 0}}, + {2283, {wxDatePickerCtrl, new_3, 3}}, + {2284, {wxDatePickerCtrl, getRange, 2}}, + {2285, {wxDatePickerCtrl, getValue, 0}}, + {2286, {wxDatePickerCtrl, setRange, 2}}, + {2287, {wxDatePickerCtrl, setValue, 1}}, + {2288, {wxDatePickerCtrl, 'Destroy', undefined}}, + {2289, {wxFontPickerCtrl, new_0, 0}}, + {2290, {wxFontPickerCtrl, new_3, 3}}, + {2291, {wxFontPickerCtrl, create, 3}}, + {2292, {wxFontPickerCtrl, getSelectedFont, 0}}, + {2293, {wxFontPickerCtrl, setSelectedFont, 1}}, + {2294, {wxFontPickerCtrl, getMaxPointSize, 0}}, + {2295, {wxFontPickerCtrl, setMaxPointSize, 1}}, + {2296, {wxFontPickerCtrl, 'Destroy', undefined}}, + {2299, {wxFindReplaceDialog, new_0, 0}}, + {2300, {wxFindReplaceDialog, new_4, 4}}, + {2301, {wxFindReplaceDialog, destruct, 0}}, + {2302, {wxFindReplaceDialog, create, 4}}, + {2303, {wxFindReplaceDialog, getData, 0}}, + {2304, {wxFindReplaceData, new_0, 0}}, + {2305, {wxFindReplaceData, new_1, 1}}, + {2306, {wxFindReplaceData, getFindString, 0}}, + {2307, {wxFindReplaceData, getReplaceString, 0}}, + {2308, {wxFindReplaceData, getFlags, 0}}, + {2309, {wxFindReplaceData, setFlags, 1}}, + {2310, {wxFindReplaceData, setFindString, 1}}, + {2311, {wxFindReplaceData, setReplaceString, 1}}, + {2312, {wxFindReplaceData, 'Destroy', undefined}}, + {2313, {wxMultiChoiceDialog, new_0, 0}}, + {2315, {wxMultiChoiceDialog, new_5, 5}}, + {2316, {wxMultiChoiceDialog, getSelections, 0}}, + {2317, {wxMultiChoiceDialog, setSelections, 1}}, + {2318, {wxMultiChoiceDialog, 'Destroy', undefined}}, + {2319, {wxSingleChoiceDialog, new_0, 0}}, + {2321, {wxSingleChoiceDialog, new_5, 5}}, + {2322, {wxSingleChoiceDialog, getSelection, 0}}, + {2323, {wxSingleChoiceDialog, getStringSelection, 0}}, + {2324, {wxSingleChoiceDialog, setSelection, 1}}, + {2325, {wxSingleChoiceDialog, 'Destroy', undefined}}, + {2326, {wxTextEntryDialog, new, 3}}, + {2327, {wxTextEntryDialog, getValue, 0}}, + {2328, {wxTextEntryDialog, setValue, 1}}, + {2329, {wxTextEntryDialog, 'Destroy', undefined}}, + {2330, {wxPasswordEntryDialog, new, 3}}, + {2331, {wxPasswordEntryDialog, 'Destroy', undefined}}, + {2332, {wxFontData, new_0, 0}}, + {2333, {wxFontData, new_1, 1}}, + {2334, {wxFontData, destruct, 0}}, + {2335, {wxFontData, enableEffects, 1}}, + {2336, {wxFontData, getAllowSymbols, 0}}, + {2337, {wxFontData, getColour, 0}}, + {2338, {wxFontData, getChosenFont, 0}}, + {2339, {wxFontData, getEnableEffects, 0}}, + {2340, {wxFontData, getInitialFont, 0}}, + {2341, {wxFontData, getShowHelp, 0}}, + {2342, {wxFontData, setAllowSymbols, 1}}, + {2343, {wxFontData, setChosenFont, 1}}, + {2344, {wxFontData, setColour, 1}}, + {2345, {wxFontData, setInitialFont, 1}}, + {2346, {wxFontData, setRange, 2}}, + {2347, {wxFontData, setShowHelp, 1}}, + {2351, {wxFontDialog, new_0, 0}}, + {2353, {wxFontDialog, new_2, 2}}, + {2355, {wxFontDialog, create, 2}}, + {2356, {wxFontDialog, getFontData, 0}}, + {2358, {wxFontDialog, 'Destroy', undefined}}, + {2359, {wxProgressDialog, new, 3}}, + {2360, {wxProgressDialog, destruct, 0}}, + {2361, {wxProgressDialog, resume, 0}}, + {2362, {wxProgressDialog, update_2, 2}}, + {2363, {wxProgressDialog, update_0, 0}}, + {2364, {wxMessageDialog, new, 3}}, + {2365, {wxMessageDialog, destruct, 0}}, + {2366, {wxPageSetupDialog, new, 2}}, + {2367, {wxPageSetupDialog, destruct, 0}}, + {2368, {wxPageSetupDialog, getPageSetupData, 0}}, + {2369, {wxPageSetupDialog, showModal, 0}}, + {2370, {wxPageSetupDialogData, new_0, 0}}, + {2371, {wxPageSetupDialogData, new_1_0, 1}}, + {2372, {wxPageSetupDialogData, new_1_1, 1}}, + {2373, {wxPageSetupDialogData, destruct, 0}}, + {2374, {wxPageSetupDialogData, enableHelp, 1}}, + {2375, {wxPageSetupDialogData, enableMargins, 1}}, + {2376, {wxPageSetupDialogData, enableOrientation, 1}}, + {2377, {wxPageSetupDialogData, enablePaper, 1}}, + {2378, {wxPageSetupDialogData, enablePrinter, 1}}, + {2379, {wxPageSetupDialogData, getDefaultMinMargins, 0}}, + {2380, {wxPageSetupDialogData, getEnableMargins, 0}}, + {2381, {wxPageSetupDialogData, getEnableOrientation, 0}}, + {2382, {wxPageSetupDialogData, getEnablePaper, 0}}, + {2383, {wxPageSetupDialogData, getEnablePrinter, 0}}, + {2384, {wxPageSetupDialogData, getEnableHelp, 0}}, + {2385, {wxPageSetupDialogData, getDefaultInfo, 0}}, + {2386, {wxPageSetupDialogData, getMarginTopLeft, 0}}, + {2387, {wxPageSetupDialogData, getMarginBottomRight, 0}}, + {2388, {wxPageSetupDialogData, getMinMarginTopLeft, 0}}, + {2389, {wxPageSetupDialogData, getMinMarginBottomRight, 0}}, + {2390, {wxPageSetupDialogData, getPaperId, 0}}, + {2391, {wxPageSetupDialogData, getPaperSize, 0}}, + {2393, {wxPageSetupDialogData, getPrintData, 0}}, + {2394, {wxPageSetupDialogData, isOk, 0}}, + {2395, {wxPageSetupDialogData, setDefaultInfo, 1}}, + {2396, {wxPageSetupDialogData, setDefaultMinMargins, 1}}, + {2397, {wxPageSetupDialogData, setMarginTopLeft, 1}}, + {2398, {wxPageSetupDialogData, setMarginBottomRight, 1}}, + {2399, {wxPageSetupDialogData, setMinMarginTopLeft, 1}}, + {2400, {wxPageSetupDialogData, setMinMarginBottomRight, 1}}, + {2401, {wxPageSetupDialogData, setPaperId, 1}}, + {2402, {wxPageSetupDialogData, setPaperSize_1_1, 1}}, + {2403, {wxPageSetupDialogData, setPaperSize_1_0, 1}}, + {2404, {wxPageSetupDialogData, setPrintData, 1}}, + {2405, {wxPrintDialog, new_2_0, 2}}, + {2406, {wxPrintDialog, new_2_1, 2}}, + {2407, {wxPrintDialog, destruct, 0}}, + {2408, {wxPrintDialog, getPrintDialogData, 0}}, + {2409, {wxPrintDialog, getPrintDC, 0}}, + {2410, {wxPrintDialogData, new_0, 0}}, + {2411, {wxPrintDialogData, new_1_1, 1}}, + {2412, {wxPrintDialogData, new_1_0, 1}}, + {2413, {wxPrintDialogData, destruct, 0}}, + {2414, {wxPrintDialogData, enableHelp, 1}}, + {2415, {wxPrintDialogData, enablePageNumbers, 1}}, + {2416, {wxPrintDialogData, enablePrintToFile, 1}}, + {2417, {wxPrintDialogData, enableSelection, 1}}, + {2418, {wxPrintDialogData, getAllPages, 0}}, + {2419, {wxPrintDialogData, getCollate, 0}}, + {2420, {wxPrintDialogData, getFromPage, 0}}, + {2421, {wxPrintDialogData, getMaxPage, 0}}, + {2422, {wxPrintDialogData, getMinPage, 0}}, + {2423, {wxPrintDialogData, getNoCopies, 0}}, + {2424, {wxPrintDialogData, getPrintData, 0}}, + {2425, {wxPrintDialogData, getPrintToFile, 0}}, + {2426, {wxPrintDialogData, getSelection, 0}}, + {2427, {wxPrintDialogData, getToPage, 0}}, + {2428, {wxPrintDialogData, isOk, 0}}, + {2429, {wxPrintDialogData, setCollate, 1}}, + {2430, {wxPrintDialogData, setFromPage, 1}}, + {2431, {wxPrintDialogData, setMaxPage, 1}}, + {2432, {wxPrintDialogData, setMinPage, 1}}, + {2433, {wxPrintDialogData, setNoCopies, 1}}, + {2434, {wxPrintDialogData, setPrintData, 1}}, + {2435, {wxPrintDialogData, setPrintToFile, 1}}, + {2436, {wxPrintDialogData, setSelection, 1}}, + {2437, {wxPrintDialogData, setToPage, 1}}, + {2438, {wxPrintData, new_0, 0}}, + {2439, {wxPrintData, new_1, 1}}, + {2440, {wxPrintData, destruct, 0}}, + {2441, {wxPrintData, getCollate, 0}}, + {2442, {wxPrintData, getBin, 0}}, + {2443, {wxPrintData, getColour, 0}}, + {2444, {wxPrintData, getDuplex, 0}}, + {2445, {wxPrintData, getNoCopies, 0}}, + {2446, {wxPrintData, getOrientation, 0}}, + {2447, {wxPrintData, getPaperId, 0}}, + {2448, {wxPrintData, getPrinterName, 0}}, + {2449, {wxPrintData, getQuality, 0}}, + {2450, {wxPrintData, isOk, 0}}, + {2451, {wxPrintData, setBin, 1}}, + {2452, {wxPrintData, setCollate, 1}}, + {2453, {wxPrintData, setColour, 1}}, + {2454, {wxPrintData, setDuplex, 1}}, + {2455, {wxPrintData, setNoCopies, 1}}, + {2456, {wxPrintData, setOrientation, 1}}, + {2457, {wxPrintData, setPaperId, 1}}, + {2458, {wxPrintData, setPrinterName, 1}}, + {2459, {wxPrintData, setQuality, 1}}, + {2462, {wxPrintPreview, new_2, 2}}, + {2463, {wxPrintPreview, new_3, 3}}, + {2465, {wxPrintPreview, destruct, 0}}, + {2466, {wxPrintPreview, getCanvas, 0}}, + {2467, {wxPrintPreview, getCurrentPage, 0}}, + {2468, {wxPrintPreview, getFrame, 0}}, + {2469, {wxPrintPreview, getMaxPage, 0}}, + {2470, {wxPrintPreview, getMinPage, 0}}, + {2471, {wxPrintPreview, getPrintout, 0}}, + {2472, {wxPrintPreview, getPrintoutForPrinting, 0}}, + {2473, {wxPrintPreview, isOk, 0}}, + {2474, {wxPrintPreview, paintPage, 2}}, + {2475, {wxPrintPreview, print, 1}}, + {2476, {wxPrintPreview, renderPage, 1}}, + {2477, {wxPrintPreview, setCanvas, 1}}, + {2478, {wxPrintPreview, setCurrentPage, 1}}, + {2479, {wxPrintPreview, setFrame, 1}}, + {2480, {wxPrintPreview, setPrintout, 1}}, + {2481, {wxPrintPreview, setZoom, 1}}, + {2482, {wxPreviewFrame, new, 3}}, + {2483, {wxPreviewFrame, destruct, 0}}, + {2484, {wxPreviewFrame, createControlBar, 0}}, + {2485, {wxPreviewFrame, createCanvas, 0}}, + {2486, {wxPreviewFrame, initialize, 0}}, + {2487, {wxPreviewFrame, onCloseWindow, 1}}, + {2488, {wxPreviewControlBar, new, 4}}, + {2489, {wxPreviewControlBar, destruct, 0}}, + {2490, {wxPreviewControlBar, createButtons, 0}}, + {2491, {wxPreviewControlBar, getPrintPreview, 0}}, + {2492, {wxPreviewControlBar, getZoomControl, 0}}, + {2493, {wxPreviewControlBar, setZoomControl, 1}}, + {2495, {wxPrinter, new, 1}}, + {2496, {wxPrinter, createAbortWindow, 2}}, + {2497, {wxPrinter, getAbort, 0}}, + {2498, {wxPrinter, getLastError, 0}}, + {2499, {wxPrinter, getPrintDialogData, 0}}, + {2500, {wxPrinter, print, 3}}, + {2501, {wxPrinter, printDialog, 1}}, + {2502, {wxPrinter, reportError, 3}}, + {2503, {wxPrinter, setup, 1}}, + {2504, {wxPrinter, 'Destroy', undefined}}, + {2505, {wxXmlResource, new_1, 1}}, + {2506, {wxXmlResource, new_2, 2}}, + {2507, {wxXmlResource, destruct, 0}}, + {2508, {wxXmlResource, attachUnknownControl, 3}}, + {2509, {wxXmlResource, clearHandlers, 0}}, + {2510, {wxXmlResource, compareVersion, 4}}, + {2511, {wxXmlResource, get, 0}}, + {2512, {wxXmlResource, getFlags, 0}}, + {2513, {wxXmlResource, getVersion, 0}}, + {2514, {wxXmlResource, getXRCID, 2}}, + {2515, {wxXmlResource, initAllHandlers, 0}}, + {2516, {wxXmlResource, load, 1}}, + {2517, {wxXmlResource, loadBitmap, 1}}, + {2518, {wxXmlResource, loadDialog_2, 2}}, + {2519, {wxXmlResource, loadDialog_3, 3}}, + {2520, {wxXmlResource, loadFrame_2, 2}}, + {2521, {wxXmlResource, loadFrame_3, 3}}, + {2522, {wxXmlResource, loadIcon, 1}}, + {2523, {wxXmlResource, loadMenu, 1}}, + {2524, {wxXmlResource, loadMenuBar_2, 2}}, + {2525, {wxXmlResource, loadMenuBar_1, 1}}, + {2526, {wxXmlResource, loadPanel_2, 2}}, + {2527, {wxXmlResource, loadPanel_3, 3}}, + {2528, {wxXmlResource, loadToolBar, 2}}, + {2529, {wxXmlResource, set, 1}}, + {2530, {wxXmlResource, setFlags, 1}}, + {2531, {wxXmlResource, unload, 1}}, + {2532, {wxXmlResource, xrcctrl, 3}}, + {2533, {wxHtmlEasyPrinting, new, 1}}, + {2534, {wxHtmlEasyPrinting, destruct, 0}}, + {2535, {wxHtmlEasyPrinting, getPrintData, 0}}, + {2536, {wxHtmlEasyPrinting, getPageSetupData, 0}}, + {2537, {wxHtmlEasyPrinting, previewFile, 1}}, + {2538, {wxHtmlEasyPrinting, previewText, 2}}, + {2539, {wxHtmlEasyPrinting, printFile, 1}}, + {2540, {wxHtmlEasyPrinting, printText, 2}}, + {2541, {wxHtmlEasyPrinting, pageSetup, 0}}, + {2542, {wxHtmlEasyPrinting, setFonts, 3}}, + {2543, {wxHtmlEasyPrinting, setHeader, 2}}, + {2544, {wxHtmlEasyPrinting, setFooter, 2}}, + {2546, {wxGLCanvas, new_2, 2}}, + {2547, {wxGLCanvas, new_3_1, 3}}, + {2548, {wxGLCanvas, new_3_0, 3}}, + {2549, {wxGLCanvas, getContext, 0}}, + {2551, {wxGLCanvas, setCurrent, 0}}, + {2552, {wxGLCanvas, swapBuffers, 0}}, + {2553, {wxGLCanvas, 'Destroy', undefined}}, + {2554, {wxAuiManager, new, 1}}, + {2555, {wxAuiManager, destruct, 0}}, + {2556, {wxAuiManager, addPane_2_1, 2}}, + {2557, {wxAuiManager, addPane_3, 3}}, + {2558, {wxAuiManager, addPane_2_0, 2}}, + {2559, {wxAuiManager, detachPane, 1}}, + {2560, {wxAuiManager, getAllPanes, 0}}, + {2561, {wxAuiManager, getArtProvider, 0}}, + {2562, {wxAuiManager, getDockSizeConstraint, 2}}, + {2563, {wxAuiManager, getFlags, 0}}, + {2564, {wxAuiManager, getManagedWindow, 0}}, + {2565, {wxAuiManager, getManager, 1}}, + {2566, {wxAuiManager, getPane_1_1, 1}}, + {2567, {wxAuiManager, getPane_1_0, 1}}, + {2568, {wxAuiManager, hideHint, 0}}, + {2569, {wxAuiManager, insertPane, 3}}, + {2570, {wxAuiManager, loadPaneInfo, 2}}, + {2571, {wxAuiManager, loadPerspective, 2}}, + {2572, {wxAuiManager, savePaneInfo, 1}}, + {2573, {wxAuiManager, savePerspective, 0}}, + {2574, {wxAuiManager, setArtProvider, 1}}, + {2575, {wxAuiManager, setDockSizeConstraint, 2}}, + {2576, {wxAuiManager, setFlags, 1}}, + {2577, {wxAuiManager, setManagedWindow, 1}}, + {2578, {wxAuiManager, showHint, 1}}, + {2579, {wxAuiManager, unInit, 0}}, + {2580, {wxAuiManager, update, 0}}, + {2581, {wxAuiPaneInfo, new_0, 0}}, + {2582, {wxAuiPaneInfo, new_1, 1}}, + {2583, {wxAuiPaneInfo, destruct, 0}}, + {2584, {wxAuiPaneInfo, bestSize_1, 1}}, + {2585, {wxAuiPaneInfo, bestSize_2, 2}}, + {2586, {wxAuiPaneInfo, bottom, 0}}, + {2587, {wxAuiPaneInfo, bottomDockable, 1}}, + {2588, {wxAuiPaneInfo, caption, 1}}, + {2589, {wxAuiPaneInfo, captionVisible, 1}}, + {2590, {wxAuiPaneInfo, centre, 0}}, + {2591, {wxAuiPaneInfo, centrePane, 0}}, + {2592, {wxAuiPaneInfo, closeButton, 1}}, + {2593, {wxAuiPaneInfo, defaultPane, 0}}, + {2594, {wxAuiPaneInfo, destroyOnClose, 1}}, + {2595, {wxAuiPaneInfo, direction, 1}}, + {2596, {wxAuiPaneInfo, dock, 0}}, + {2597, {wxAuiPaneInfo, dockable, 1}}, + {2598, {wxAuiPaneInfo, fixed, 0}}, + {2599, {wxAuiPaneInfo, float, 0}}, + {2600, {wxAuiPaneInfo, floatable, 1}}, + {2601, {wxAuiPaneInfo, floatingPosition_1, 1}}, + {2602, {wxAuiPaneInfo, floatingPosition_2, 2}}, + {2603, {wxAuiPaneInfo, floatingSize_1, 1}}, + {2604, {wxAuiPaneInfo, floatingSize_2, 2}}, + {2605, {wxAuiPaneInfo, gripper, 1}}, + {2606, {wxAuiPaneInfo, gripperTop, 1}}, + {2607, {wxAuiPaneInfo, hasBorder, 0}}, + {2608, {wxAuiPaneInfo, hasCaption, 0}}, + {2609, {wxAuiPaneInfo, hasCloseButton, 0}}, + {2610, {wxAuiPaneInfo, hasFlag, 1}}, + {2611, {wxAuiPaneInfo, hasGripper, 0}}, + {2612, {wxAuiPaneInfo, hasGripperTop, 0}}, + {2613, {wxAuiPaneInfo, hasMaximizeButton, 0}}, + {2614, {wxAuiPaneInfo, hasMinimizeButton, 0}}, + {2615, {wxAuiPaneInfo, hasPinButton, 0}}, + {2616, {wxAuiPaneInfo, hide, 0}}, + {2617, {wxAuiPaneInfo, isBottomDockable, 0}}, + {2618, {wxAuiPaneInfo, isDocked, 0}}, + {2619, {wxAuiPaneInfo, isFixed, 0}}, + {2620, {wxAuiPaneInfo, isFloatable, 0}}, + {2621, {wxAuiPaneInfo, isFloating, 0}}, + {2622, {wxAuiPaneInfo, isLeftDockable, 0}}, + {2623, {wxAuiPaneInfo, isMovable, 0}}, + {2624, {wxAuiPaneInfo, isOk, 0}}, + {2625, {wxAuiPaneInfo, isResizable, 0}}, + {2626, {wxAuiPaneInfo, isRightDockable, 0}}, + {2627, {wxAuiPaneInfo, isShown, 0}}, + {2628, {wxAuiPaneInfo, isToolbar, 0}}, + {2629, {wxAuiPaneInfo, isTopDockable, 0}}, + {2630, {wxAuiPaneInfo, layer, 1}}, + {2631, {wxAuiPaneInfo, left, 0}}, + {2632, {wxAuiPaneInfo, leftDockable, 1}}, + {2633, {wxAuiPaneInfo, maxSize_1, 1}}, + {2634, {wxAuiPaneInfo, maxSize_2, 2}}, + {2635, {wxAuiPaneInfo, maximizeButton, 1}}, + {2636, {wxAuiPaneInfo, minSize_1, 1}}, + {2637, {wxAuiPaneInfo, minSize_2, 2}}, + {2638, {wxAuiPaneInfo, minimizeButton, 1}}, + {2639, {wxAuiPaneInfo, movable, 1}}, + {2640, {wxAuiPaneInfo, name, 1}}, + {2641, {wxAuiPaneInfo, paneBorder, 1}}, + {2642, {wxAuiPaneInfo, pinButton, 1}}, + {2643, {wxAuiPaneInfo, position, 1}}, + {2644, {wxAuiPaneInfo, resizable, 1}}, + {2645, {wxAuiPaneInfo, right, 0}}, + {2646, {wxAuiPaneInfo, rightDockable, 1}}, + {2647, {wxAuiPaneInfo, row, 1}}, + {2648, {wxAuiPaneInfo, safeSet, 1}}, + {2649, {wxAuiPaneInfo, setFlag, 2}}, + {2650, {wxAuiPaneInfo, show, 1}}, + {2651, {wxAuiPaneInfo, toolbarPane, 0}}, + {2652, {wxAuiPaneInfo, top, 0}}, + {2653, {wxAuiPaneInfo, topDockable, 1}}, + {2654, {wxAuiPaneInfo, window, 1}}, + {2655, {wxAuiPaneInfo, getWindow, 0}}, + {2656, {wxAuiPaneInfo, getFrame, 0}}, + {2657, {wxAuiPaneInfo, getDirection, 0}}, + {2658, {wxAuiPaneInfo, getLayer, 0}}, + {2659, {wxAuiPaneInfo, getRow, 0}}, + {2660, {wxAuiPaneInfo, getPosition, 0}}, + {2661, {wxAuiPaneInfo, getFloatingPosition, 0}}, + {2662, {wxAuiPaneInfo, getFloatingSize, 0}}, + {2663, {wxAuiNotebook, new_0, 0}}, + {2664, {wxAuiNotebook, new_2, 2}}, + {2665, {wxAuiNotebook, addPage, 3}}, + {2666, {wxAuiNotebook, create, 2}}, + {2667, {wxAuiNotebook, deletePage, 1}}, + {2668, {wxAuiNotebook, getArtProvider, 0}}, + {2669, {wxAuiNotebook, getPage, 1}}, + {2670, {wxAuiNotebook, getPageBitmap, 1}}, + {2671, {wxAuiNotebook, getPageCount, 0}}, + {2672, {wxAuiNotebook, getPageIndex, 1}}, + {2673, {wxAuiNotebook, getPageText, 1}}, + {2674, {wxAuiNotebook, getSelection, 0}}, + {2675, {wxAuiNotebook, insertPage, 4}}, + {2676, {wxAuiNotebook, removePage, 1}}, + {2677, {wxAuiNotebook, setArtProvider, 1}}, + {2678, {wxAuiNotebook, setFont, 1}}, + {2679, {wxAuiNotebook, setPageBitmap, 2}}, + {2680, {wxAuiNotebook, setPageText, 2}}, + {2681, {wxAuiNotebook, setSelection, 1}}, + {2682, {wxAuiNotebook, setTabCtrlHeight, 1}}, + {2683, {wxAuiNotebook, setUniformBitmapSize, 1}}, + {2684, {wxAuiNotebook, 'Destroy', undefined}}, + {2685, {wxAuiTabArt, setFlags, 1}}, + {2686, {wxAuiTabArt, setMeasuringFont, 1}}, + {2687, {wxAuiTabArt, setNormalFont, 1}}, + {2688, {wxAuiTabArt, setSelectedFont, 1}}, + {2689, {wxAuiTabArt, setColour, 1}}, + {2690, {wxAuiTabArt, setActiveColour, 1}}, + {2691, {wxAuiDockArt, getColour, 1}}, + {2692, {wxAuiDockArt, getFont, 1}}, + {2693, {wxAuiDockArt, getMetric, 1}}, + {2694, {wxAuiDockArt, setColour, 2}}, + {2695, {wxAuiDockArt, setFont, 2}}, + {2696, {wxAuiDockArt, setMetric, 2}}, + {2697, {wxAuiSimpleTabArt, new, 0}}, + {2698, {wxAuiSimpleTabArt, 'Destroy', undefined}}, + {2699, {wxMDIParentFrame, new_0, 0}}, + {2700, {wxMDIParentFrame, new_4, 4}}, + {2701, {wxMDIParentFrame, destruct, 0}}, + {2702, {wxMDIParentFrame, activateNext, 0}}, + {2703, {wxMDIParentFrame, activatePrevious, 0}}, + {2704, {wxMDIParentFrame, arrangeIcons, 0}}, + {2705, {wxMDIParentFrame, cascade, 0}}, + {2706, {wxMDIParentFrame, create, 4}}, + {2707, {wxMDIParentFrame, getActiveChild, 0}}, + {2708, {wxMDIParentFrame, getClientWindow, 0}}, + {2709, {wxMDIParentFrame, tile, 1}}, + {2710, {wxMDIChildFrame, new_0, 0}}, + {2711, {wxMDIChildFrame, new_4, 4}}, + {2712, {wxMDIChildFrame, destruct, 0}}, + {2713, {wxMDIChildFrame, activate, 0}}, + {2714, {wxMDIChildFrame, create, 4}}, + {2715, {wxMDIChildFrame, maximize, 1}}, + {2716, {wxMDIChildFrame, restore, 0}}, + {2717, {wxMDIClientWindow, new_0, 0}}, + {2718, {wxMDIClientWindow, new_2, 2}}, + {2719, {wxMDIClientWindow, destruct, 0}}, + {2720, {wxMDIClientWindow, createClient, 2}}, + {2721, {wxLayoutAlgorithm, new, 0}}, + {2722, {wxLayoutAlgorithm, layoutFrame, 2}}, + {2723, {wxLayoutAlgorithm, layoutMDIFrame, 2}}, + {2724, {wxLayoutAlgorithm, layoutWindow, 2}}, + {2725, {wxLayoutAlgorithm, 'Destroy', undefined}}, + {2726, {wxEvent, getId, 0}}, + {2727, {wxEvent, getSkipped, 0}}, + {2728, {wxEvent, getTimestamp, 0}}, + {2729, {wxEvent, isCommandEvent, 0}}, + {2730, {wxEvent, resumePropagation, 1}}, + {2731, {wxEvent, shouldPropagate, 0}}, + {2732, {wxEvent, skip, 1}}, + {2733, {wxEvent, stopPropagation, 0}}, + {2734, {wxCommandEvent, getClientData, 0}}, + {2735, {wxCommandEvent, getExtraLong, 0}}, + {2736, {wxCommandEvent, getInt, 0}}, + {2737, {wxCommandEvent, getSelection, 0}}, + {2738, {wxCommandEvent, getString, 0}}, + {2739, {wxCommandEvent, isChecked, 0}}, + {2740, {wxCommandEvent, isSelection, 0}}, + {2741, {wxCommandEvent, setInt, 1}}, + {2742, {wxCommandEvent, setString, 1}}, + {2743, {wxScrollEvent, getOrientation, 0}}, + {2744, {wxScrollEvent, getPosition, 0}}, + {2745, {wxScrollWinEvent, getOrientation, 0}}, + {2746, {wxScrollWinEvent, getPosition, 0}}, + {2747, {wxMouseEvent, altDown, 0}}, + {2748, {wxMouseEvent, button, 1}}, + {2749, {wxMouseEvent, buttonDClick, 1}}, + {2750, {wxMouseEvent, buttonDown, 1}}, + {2751, {wxMouseEvent, buttonUp, 1}}, + {2752, {wxMouseEvent, cmdDown, 0}}, + {2753, {wxMouseEvent, controlDown, 0}}, + {2754, {wxMouseEvent, dragging, 0}}, + {2755, {wxMouseEvent, entering, 0}}, + {2756, {wxMouseEvent, getButton, 0}}, + {2759, {wxMouseEvent, getPosition, 0}}, + {2760, {wxMouseEvent, getLogicalPosition, 1}}, + {2761, {wxMouseEvent, getLinesPerAction, 0}}, + {2762, {wxMouseEvent, getWheelRotation, 0}}, + {2763, {wxMouseEvent, getWheelDelta, 0}}, + {2764, {wxMouseEvent, getX, 0}}, + {2765, {wxMouseEvent, getY, 0}}, + {2766, {wxMouseEvent, isButton, 0}}, + {2767, {wxMouseEvent, isPageScroll, 0}}, + {2768, {wxMouseEvent, leaving, 0}}, + {2769, {wxMouseEvent, leftDClick, 0}}, + {2770, {wxMouseEvent, leftDown, 0}}, + {2771, {wxMouseEvent, leftIsDown, 0}}, + {2772, {wxMouseEvent, leftUp, 0}}, + {2773, {wxMouseEvent, metaDown, 0}}, + {2774, {wxMouseEvent, middleDClick, 0}}, + {2775, {wxMouseEvent, middleDown, 0}}, + {2776, {wxMouseEvent, middleIsDown, 0}}, + {2777, {wxMouseEvent, middleUp, 0}}, + {2778, {wxMouseEvent, moving, 0}}, + {2779, {wxMouseEvent, rightDClick, 0}}, + {2780, {wxMouseEvent, rightDown, 0}}, + {2781, {wxMouseEvent, rightIsDown, 0}}, + {2782, {wxMouseEvent, rightUp, 0}}, + {2783, {wxMouseEvent, shiftDown, 0}}, + {2784, {wxSetCursorEvent, getCursor, 0}}, + {2785, {wxSetCursorEvent, getX, 0}}, + {2786, {wxSetCursorEvent, getY, 0}}, + {2787, {wxSetCursorEvent, hasCursor, 0}}, + {2788, {wxSetCursorEvent, setCursor, 1}}, + {2789, {wxKeyEvent, altDown, 0}}, + {2790, {wxKeyEvent, cmdDown, 0}}, + {2791, {wxKeyEvent, controlDown, 0}}, + {2792, {wxKeyEvent, getKeyCode, 0}}, + {2793, {wxKeyEvent, getModifiers, 0}}, + {2796, {wxKeyEvent, getPosition, 0}}, + {2797, {wxKeyEvent, getRawKeyCode, 0}}, + {2798, {wxKeyEvent, getRawKeyFlags, 0}}, + {2799, {wxKeyEvent, getUnicodeKey, 0}}, + {2800, {wxKeyEvent, getX, 0}}, + {2801, {wxKeyEvent, getY, 0}}, + {2802, {wxKeyEvent, hasModifiers, 0}}, + {2803, {wxKeyEvent, metaDown, 0}}, + {2804, {wxKeyEvent, shiftDown, 0}}, + {2805, {wxSizeEvent, getSize, 0}}, + {2806, {wxMoveEvent, getPosition, 0}}, + {2807, {wxEraseEvent, getDC, 0}}, + {2808, {wxFocusEvent, getWindow, 0}}, + {2809, {wxChildFocusEvent, getWindow, 0}}, + {2810, {wxMenuEvent, getMenu, 0}}, + {2811, {wxMenuEvent, getMenuId, 0}}, + {2812, {wxMenuEvent, isPopup, 0}}, + {2813, {wxCloseEvent, canVeto, 0}}, + {2814, {wxCloseEvent, getLoggingOff, 0}}, + {2815, {wxCloseEvent, setCanVeto, 1}}, + {2816, {wxCloseEvent, setLoggingOff, 1}}, + {2817, {wxCloseEvent, veto, 1}}, + {2818, {wxShowEvent, setShow, 1}}, + {2819, {wxShowEvent, getShow, 0}}, + {2820, {wxIconizeEvent, iconized, 0}}, + {2821, {wxJoystickEvent, buttonDown, 1}}, + {2822, {wxJoystickEvent, buttonIsDown, 1}}, + {2823, {wxJoystickEvent, buttonUp, 1}}, + {2824, {wxJoystickEvent, getButtonChange, 0}}, + {2825, {wxJoystickEvent, getButtonState, 0}}, + {2826, {wxJoystickEvent, getJoystick, 0}}, + {2827, {wxJoystickEvent, getPosition, 0}}, + {2828, {wxJoystickEvent, getZPosition, 0}}, + {2829, {wxJoystickEvent, isButton, 0}}, + {2830, {wxJoystickEvent, isMove, 0}}, + {2831, {wxJoystickEvent, isZMove, 0}}, + {2832, {wxUpdateUIEvent, canUpdate, 1}}, + {2833, {wxUpdateUIEvent, check, 1}}, + {2834, {wxUpdateUIEvent, enable, 1}}, + {2835, {wxUpdateUIEvent, show, 1}}, + {2836, {wxUpdateUIEvent, getChecked, 0}}, + {2837, {wxUpdateUIEvent, getEnabled, 0}}, + {2838, {wxUpdateUIEvent, getShown, 0}}, + {2839, {wxUpdateUIEvent, getSetChecked, 0}}, + {2840, {wxUpdateUIEvent, getSetEnabled, 0}}, + {2841, {wxUpdateUIEvent, getSetShown, 0}}, + {2842, {wxUpdateUIEvent, getSetText, 0}}, + {2843, {wxUpdateUIEvent, getText, 0}}, + {2844, {wxUpdateUIEvent, getMode, 0}}, + {2845, {wxUpdateUIEvent, getUpdateInterval, 0}}, + {2846, {wxUpdateUIEvent, resetUpdateTime, 0}}, + {2847, {wxUpdateUIEvent, setMode, 1}}, + {2848, {wxUpdateUIEvent, setText, 1}}, + {2849, {wxUpdateUIEvent, setUpdateInterval, 1}}, + {2850, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}}, + {2851, {wxPaletteChangedEvent, setChangedWindow, 1}}, + {2852, {wxPaletteChangedEvent, getChangedWindow, 0}}, + {2853, {wxQueryNewPaletteEvent, setPaletteRealized, 1}}, + {2854, {wxQueryNewPaletteEvent, getPaletteRealized, 0}}, + {2855, {wxNavigationKeyEvent, getDirection, 0}}, + {2856, {wxNavigationKeyEvent, setDirection, 1}}, + {2857, {wxNavigationKeyEvent, isWindowChange, 0}}, + {2858, {wxNavigationKeyEvent, setWindowChange, 1}}, + {2859, {wxNavigationKeyEvent, isFromTab, 0}}, + {2860, {wxNavigationKeyEvent, setFromTab, 1}}, + {2861, {wxNavigationKeyEvent, getCurrentFocus, 0}}, + {2862, {wxNavigationKeyEvent, setCurrentFocus, 1}}, + {2863, {wxHelpEvent, getOrigin, 0}}, + {2864, {wxHelpEvent, getPosition, 0}}, + {2865, {wxHelpEvent, setOrigin, 1}}, + {2866, {wxHelpEvent, setPosition, 1}}, + {2867, {wxContextMenuEvent, getPosition, 0}}, + {2868, {wxContextMenuEvent, setPosition, 1}}, + {2869, {wxIdleEvent, canSend, 1}}, + {2870, {wxIdleEvent, getMode, 0}}, + {2871, {wxIdleEvent, requestMore, 1}}, + {2872, {wxIdleEvent, moreRequested, 0}}, + {2873, {wxIdleEvent, setMode, 1}}, + {2874, {wxGridEvent, altDown, 0}}, + {2875, {wxGridEvent, controlDown, 0}}, + {2876, {wxGridEvent, getCol, 0}}, + {2877, {wxGridEvent, getPosition, 0}}, + {2878, {wxGridEvent, getRow, 0}}, + {2879, {wxGridEvent, metaDown, 0}}, + {2880, {wxGridEvent, selecting, 0}}, + {2881, {wxGridEvent, shiftDown, 0}}, + {2882, {wxNotifyEvent, allow, 0}}, + {2883, {wxNotifyEvent, isAllowed, 0}}, + {2884, {wxNotifyEvent, veto, 0}}, + {2885, {wxSashEvent, getEdge, 0}}, + {2886, {wxSashEvent, getDragRect, 0}}, + {2887, {wxSashEvent, getDragStatus, 0}}, + {2888, {wxListEvent, getCacheFrom, 0}}, + {2889, {wxListEvent, getCacheTo, 0}}, + {2890, {wxListEvent, getKeyCode, 0}}, + {2891, {wxListEvent, getIndex, 0}}, + {2892, {wxListEvent, getColumn, 0}}, + {2893, {wxListEvent, getPoint, 0}}, + {2894, {wxListEvent, getLabel, 0}}, + {2895, {wxListEvent, getText, 0}}, + {2896, {wxListEvent, getImage, 0}}, + {2897, {wxListEvent, getData, 0}}, + {2898, {wxListEvent, getMask, 0}}, + {2899, {wxListEvent, getItem, 0}}, + {2900, {wxListEvent, isEditCancelled, 0}}, + {2901, {wxDateEvent, getDate, 0}}, + {2902, {wxCalendarEvent, getWeekDay, 0}}, + {2903, {wxFileDirPickerEvent, getPath, 0}}, + {2904, {wxColourPickerEvent, getColour, 0}}, + {2905, {wxFontPickerEvent, getFont, 0}}, + {2906, {wxStyledTextEvent, getPosition, 0}}, + {2907, {wxStyledTextEvent, getKey, 0}}, + {2908, {wxStyledTextEvent, getModifiers, 0}}, + {2909, {wxStyledTextEvent, getModificationType, 0}}, + {2910, {wxStyledTextEvent, getText, 0}}, + {2911, {wxStyledTextEvent, getLength, 0}}, + {2912, {wxStyledTextEvent, getLinesAdded, 0}}, + {2913, {wxStyledTextEvent, getLine, 0}}, + {2914, {wxStyledTextEvent, getFoldLevelNow, 0}}, + {2915, {wxStyledTextEvent, getFoldLevelPrev, 0}}, + {2916, {wxStyledTextEvent, getMargin, 0}}, + {2917, {wxStyledTextEvent, getMessage, 0}}, + {2918, {wxStyledTextEvent, getWParam, 0}}, + {2919, {wxStyledTextEvent, getLParam, 0}}, + {2920, {wxStyledTextEvent, getListType, 0}}, + {2921, {wxStyledTextEvent, getX, 0}}, + {2922, {wxStyledTextEvent, getY, 0}}, + {2923, {wxStyledTextEvent, getDragText, 0}}, + {2924, {wxStyledTextEvent, getDragAllowMove, 0}}, + {2925, {wxStyledTextEvent, getDragResult, 0}}, + {2926, {wxStyledTextEvent, getShift, 0}}, + {2927, {wxStyledTextEvent, getControl, 0}}, + {2928, {wxStyledTextEvent, getAlt, 0}}, + {2929, {utils, getKeyState, 1}}, + {2930, {utils, getMousePosition, 2}}, + {2931, {utils, getMouseState, 0}}, + {2932, {utils, setDetectableAutoRepeat, 1}}, + {2933, {utils, bell, 0}}, + {2934, {utils, findMenuItemId, 3}}, + {2935, {utils, genericFindWindowAtPoint, 1}}, + {2936, {utils, findWindowAtPoint, 1}}, + {2937, {utils, beginBusyCursor, 1}}, + {2938, {utils, endBusyCursor, 0}}, + {2939, {utils, isBusy, 0}}, + {2940, {utils, shutdown, 1}}, + {2941, {utils, shell, 1}}, + {2942, {utils, launchDefaultBrowser, 2}}, + {2943, {utils, getEmailAddress, 0}}, + {2944, {utils, getUserId, 0}}, + {2945, {utils, getHomeDir, 0}}, + {2946, {utils, newId, 0}}, + {2947, {utils, registerId, 1}}, + {2948, {utils, getCurrentId, 0}}, + {2949, {utils, getOsDescription, 0}}, + {2950, {utils, isPlatformLittleEndian, 0}}, + {2951, {utils, isPlatform64Bit, 0}}, + {2952, {gdicmn, displaySize, 2}}, + {2953, {gdicmn, setCursor, 1}}, + {2954, {wxPrintout, new, 1}}, + {2955, {wxPrintout, destruct, 0}}, + {2956, {wxPrintout, getDC, 0}}, + {2957, {wxPrintout, getPageSizeMM, 2}}, + {2958, {wxPrintout, getPageSizePixels, 2}}, + {2959, {wxPrintout, getPaperRectPixels, 0}}, + {2960, {wxPrintout, getPPIPrinter, 2}}, + {2961, {wxPrintout, getPPIScreen, 2}}, + {2962, {wxPrintout, getTitle, 0}}, + {2963, {wxPrintout, isPreview, 0}}, + {2964, {wxPrintout, fitThisSizeToPaper, 1}}, + {2965, {wxPrintout, fitThisSizeToPage, 1}}, + {2966, {wxPrintout, fitThisSizeToPageMargins, 2}}, + {2967, {wxPrintout, mapScreenSizeToPaper, 0}}, + {2968, {wxPrintout, mapScreenSizeToPage, 0}}, + {2969, {wxPrintout, mapScreenSizeToPageMargins, 1}}, + {2970, {wxPrintout, mapScreenSizeToDevice, 0}}, + {2971, {wxPrintout, getLogicalPaperRect, 0}}, + {2972, {wxPrintout, getLogicalPageRect, 0}}, + {2973, {wxPrintout, getLogicalPageMarginsRect, 1}}, + {2974, {wxPrintout, setLogicalOrigin, 2}}, + {2975, {wxPrintout, offsetLogicalOrigin, 2}}, + {2976, {wxStyledTextCtrl, new_2, 2}}, + {2977, {wxStyledTextCtrl, new_0, 0}}, + {2978, {wxStyledTextCtrl, destruct, 0}}, + {2979, {wxStyledTextCtrl, create, 2}}, + {2980, {wxStyledTextCtrl, addText, 1}}, + {2981, {wxStyledTextCtrl, addStyledText, 1}}, + {2982, {wxStyledTextCtrl, insertText, 2}}, + {2983, {wxStyledTextCtrl, clearAll, 0}}, + {2984, {wxStyledTextCtrl, clearDocumentStyle, 0}}, + {2985, {wxStyledTextCtrl, getLength, 0}}, + {2986, {wxStyledTextCtrl, getCharAt, 1}}, + {2987, {wxStyledTextCtrl, getCurrentPos, 0}}, + {2988, {wxStyledTextCtrl, getAnchor, 0}}, + {2989, {wxStyledTextCtrl, getStyleAt, 1}}, + {2990, {wxStyledTextCtrl, redo, 0}}, + {2991, {wxStyledTextCtrl, setUndoCollection, 1}}, + {2992, {wxStyledTextCtrl, selectAll, 0}}, + {2993, {wxStyledTextCtrl, setSavePoint, 0}}, + {2994, {wxStyledTextCtrl, getStyledText, 2}}, + {2995, {wxStyledTextCtrl, canRedo, 0}}, + {2996, {wxStyledTextCtrl, markerLineFromHandle, 1}}, + {2997, {wxStyledTextCtrl, markerDeleteHandle, 1}}, + {2998, {wxStyledTextCtrl, getUndoCollection, 0}}, + {2999, {wxStyledTextCtrl, getViewWhiteSpace, 0}}, + {3000, {wxStyledTextCtrl, setViewWhiteSpace, 1}}, + {3001, {wxStyledTextCtrl, positionFromPoint, 1}}, + {3002, {wxStyledTextCtrl, positionFromPointClose, 2}}, + {3003, {wxStyledTextCtrl, gotoLine, 1}}, + {3004, {wxStyledTextCtrl, gotoPos, 1}}, + {3005, {wxStyledTextCtrl, setAnchor, 1}}, + {3006, {wxStyledTextCtrl, getCurLine, 1}}, + {3007, {wxStyledTextCtrl, getEndStyled, 0}}, + {3008, {wxStyledTextCtrl, convertEOLs, 1}}, + {3009, {wxStyledTextCtrl, getEOLMode, 0}}, + {3010, {wxStyledTextCtrl, setEOLMode, 1}}, + {3011, {wxStyledTextCtrl, startStyling, 2}}, + {3012, {wxStyledTextCtrl, setStyling, 2}}, + {3013, {wxStyledTextCtrl, getBufferedDraw, 0}}, + {3014, {wxStyledTextCtrl, setBufferedDraw, 1}}, + {3015, {wxStyledTextCtrl, setTabWidth, 1}}, + {3016, {wxStyledTextCtrl, getTabWidth, 0}}, + {3017, {wxStyledTextCtrl, setCodePage, 1}}, + {3018, {wxStyledTextCtrl, markerDefine, 3}}, + {3019, {wxStyledTextCtrl, markerSetForeground, 2}}, + {3020, {wxStyledTextCtrl, markerSetBackground, 2}}, + {3021, {wxStyledTextCtrl, markerAdd, 2}}, + {3022, {wxStyledTextCtrl, markerDelete, 2}}, + {3023, {wxStyledTextCtrl, markerDeleteAll, 1}}, + {3024, {wxStyledTextCtrl, markerGet, 1}}, + {3025, {wxStyledTextCtrl, markerNext, 2}}, + {3026, {wxStyledTextCtrl, markerPrevious, 2}}, + {3027, {wxStyledTextCtrl, markerDefineBitmap, 2}}, + {3028, {wxStyledTextCtrl, markerAddSet, 2}}, + {3029, {wxStyledTextCtrl, markerSetAlpha, 2}}, + {3030, {wxStyledTextCtrl, setMarginType, 2}}, + {3031, {wxStyledTextCtrl, getMarginType, 1}}, + {3032, {wxStyledTextCtrl, setMarginWidth, 2}}, + {3033, {wxStyledTextCtrl, getMarginWidth, 1}}, + {3034, {wxStyledTextCtrl, setMarginMask, 2}}, + {3035, {wxStyledTextCtrl, getMarginMask, 1}}, + {3036, {wxStyledTextCtrl, setMarginSensitive, 2}}, + {3037, {wxStyledTextCtrl, getMarginSensitive, 1}}, + {3038, {wxStyledTextCtrl, styleClearAll, 0}}, + {3039, {wxStyledTextCtrl, styleSetForeground, 2}}, + {3040, {wxStyledTextCtrl, styleSetBackground, 2}}, + {3041, {wxStyledTextCtrl, styleSetBold, 2}}, + {3042, {wxStyledTextCtrl, styleSetItalic, 2}}, + {3043, {wxStyledTextCtrl, styleSetSize, 2}}, + {3044, {wxStyledTextCtrl, styleSetFaceName, 2}}, + {3045, {wxStyledTextCtrl, styleSetEOLFilled, 2}}, + {3046, {wxStyledTextCtrl, styleResetDefault, 0}}, + {3047, {wxStyledTextCtrl, styleSetUnderline, 2}}, + {3048, {wxStyledTextCtrl, styleSetCase, 2}}, + {3049, {wxStyledTextCtrl, styleSetHotSpot, 2}}, + {3050, {wxStyledTextCtrl, setSelForeground, 2}}, + {3051, {wxStyledTextCtrl, setSelBackground, 2}}, + {3052, {wxStyledTextCtrl, getSelAlpha, 0}}, + {3053, {wxStyledTextCtrl, setSelAlpha, 1}}, + {3054, {wxStyledTextCtrl, setCaretForeground, 1}}, + {3055, {wxStyledTextCtrl, cmdKeyAssign, 3}}, + {3056, {wxStyledTextCtrl, cmdKeyClear, 2}}, + {3057, {wxStyledTextCtrl, cmdKeyClearAll, 0}}, + {3058, {wxStyledTextCtrl, setStyleBytes, 2}}, + {3059, {wxStyledTextCtrl, styleSetVisible, 2}}, + {3060, {wxStyledTextCtrl, getCaretPeriod, 0}}, + {3061, {wxStyledTextCtrl, setCaretPeriod, 1}}, + {3062, {wxStyledTextCtrl, setWordChars, 1}}, + {3063, {wxStyledTextCtrl, beginUndoAction, 0}}, + {3064, {wxStyledTextCtrl, endUndoAction, 0}}, + {3065, {wxStyledTextCtrl, indicatorSetStyle, 2}}, + {3066, {wxStyledTextCtrl, indicatorGetStyle, 1}}, + {3067, {wxStyledTextCtrl, indicatorSetForeground, 2}}, + {3068, {wxStyledTextCtrl, indicatorGetForeground, 1}}, + {3069, {wxStyledTextCtrl, setWhitespaceForeground, 2}}, + {3070, {wxStyledTextCtrl, setWhitespaceBackground, 2}}, + {3071, {wxStyledTextCtrl, getStyleBits, 0}}, + {3072, {wxStyledTextCtrl, setLineState, 2}}, + {3073, {wxStyledTextCtrl, getLineState, 1}}, + {3074, {wxStyledTextCtrl, getMaxLineState, 0}}, + {3075, {wxStyledTextCtrl, getCaretLineVisible, 0}}, + {3076, {wxStyledTextCtrl, setCaretLineVisible, 1}}, + {3077, {wxStyledTextCtrl, getCaretLineBackground, 0}}, + {3078, {wxStyledTextCtrl, setCaretLineBackground, 1}}, + {3079, {wxStyledTextCtrl, autoCompShow, 2}}, + {3080, {wxStyledTextCtrl, autoCompCancel, 0}}, + {3081, {wxStyledTextCtrl, autoCompActive, 0}}, + {3082, {wxStyledTextCtrl, autoCompPosStart, 0}}, + {3083, {wxStyledTextCtrl, autoCompComplete, 0}}, + {3084, {wxStyledTextCtrl, autoCompStops, 1}}, + {3085, {wxStyledTextCtrl, autoCompSetSeparator, 1}}, + {3086, {wxStyledTextCtrl, autoCompGetSeparator, 0}}, + {3087, {wxStyledTextCtrl, autoCompSelect, 1}}, + {3088, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}}, + {3089, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}}, + {3090, {wxStyledTextCtrl, autoCompSetFillUps, 1}}, + {3091, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}}, + {3092, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}}, + {3093, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}}, + {3094, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}}, + {3095, {wxStyledTextCtrl, userListShow, 2}}, + {3096, {wxStyledTextCtrl, autoCompSetAutoHide, 1}}, + {3097, {wxStyledTextCtrl, autoCompGetAutoHide, 0}}, + {3098, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}}, + {3099, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}}, + {3100, {wxStyledTextCtrl, registerImage, 2}}, + {3101, {wxStyledTextCtrl, clearRegisteredImages, 0}}, + {3102, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}}, + {3103, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}}, + {3104, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}}, + {3105, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}}, + {3106, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}}, + {3107, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}}, + {3108, {wxStyledTextCtrl, setIndent, 1}}, + {3109, {wxStyledTextCtrl, getIndent, 0}}, + {3110, {wxStyledTextCtrl, setUseTabs, 1}}, + {3111, {wxStyledTextCtrl, getUseTabs, 0}}, + {3112, {wxStyledTextCtrl, setLineIndentation, 2}}, + {3113, {wxStyledTextCtrl, getLineIndentation, 1}}, + {3114, {wxStyledTextCtrl, getLineIndentPosition, 1}}, + {3115, {wxStyledTextCtrl, getColumn, 1}}, + {3116, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}}, + {3117, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}}, + {3118, {wxStyledTextCtrl, setIndentationGuides, 1}}, + {3119, {wxStyledTextCtrl, getIndentationGuides, 0}}, + {3120, {wxStyledTextCtrl, setHighlightGuide, 1}}, + {3121, {wxStyledTextCtrl, getHighlightGuide, 0}}, + {3122, {wxStyledTextCtrl, getLineEndPosition, 1}}, + {3123, {wxStyledTextCtrl, getCodePage, 0}}, + {3124, {wxStyledTextCtrl, getCaretForeground, 0}}, + {3125, {wxStyledTextCtrl, getReadOnly, 0}}, + {3126, {wxStyledTextCtrl, setCurrentPos, 1}}, + {3127, {wxStyledTextCtrl, setSelectionStart, 1}}, + {3128, {wxStyledTextCtrl, getSelectionStart, 0}}, + {3129, {wxStyledTextCtrl, setSelectionEnd, 1}}, + {3130, {wxStyledTextCtrl, getSelectionEnd, 0}}, + {3131, {wxStyledTextCtrl, setPrintMagnification, 1}}, + {3132, {wxStyledTextCtrl, getPrintMagnification, 0}}, + {3133, {wxStyledTextCtrl, setPrintColourMode, 1}}, + {3134, {wxStyledTextCtrl, getPrintColourMode, 0}}, + {3135, {wxStyledTextCtrl, findText, 4}}, + {3136, {wxStyledTextCtrl, formatRange, 7}}, + {3137, {wxStyledTextCtrl, getFirstVisibleLine, 0}}, + {3138, {wxStyledTextCtrl, getLine, 1}}, + {3139, {wxStyledTextCtrl, getLineCount, 0}}, + {3140, {wxStyledTextCtrl, setMarginLeft, 1}}, + {3141, {wxStyledTextCtrl, getMarginLeft, 0}}, + {3142, {wxStyledTextCtrl, setMarginRight, 1}}, + {3143, {wxStyledTextCtrl, getMarginRight, 0}}, + {3144, {wxStyledTextCtrl, getModify, 0}}, + {3145, {wxStyledTextCtrl, setSelection, 2}}, + {3146, {wxStyledTextCtrl, getSelectedText, 0}}, + {3147, {wxStyledTextCtrl, getTextRange, 2}}, + {3148, {wxStyledTextCtrl, hideSelection, 1}}, + {3149, {wxStyledTextCtrl, lineFromPosition, 1}}, + {3150, {wxStyledTextCtrl, positionFromLine, 1}}, + {3151, {wxStyledTextCtrl, lineScroll, 2}}, + {3152, {wxStyledTextCtrl, ensureCaretVisible, 0}}, + {3153, {wxStyledTextCtrl, replaceSelection, 1}}, + {3154, {wxStyledTextCtrl, setReadOnly, 1}}, + {3155, {wxStyledTextCtrl, canPaste, 0}}, + {3156, {wxStyledTextCtrl, canUndo, 0}}, + {3157, {wxStyledTextCtrl, emptyUndoBuffer, 0}}, + {3158, {wxStyledTextCtrl, undo, 0}}, + {3159, {wxStyledTextCtrl, cut, 0}}, + {3160, {wxStyledTextCtrl, copy, 0}}, + {3161, {wxStyledTextCtrl, paste, 0}}, + {3162, {wxStyledTextCtrl, clear, 0}}, + {3163, {wxStyledTextCtrl, setText, 1}}, + {3164, {wxStyledTextCtrl, getText, 0}}, + {3165, {wxStyledTextCtrl, getTextLength, 0}}, + {3166, {wxStyledTextCtrl, getOvertype, 0}}, + {3167, {wxStyledTextCtrl, setCaretWidth, 1}}, + {3168, {wxStyledTextCtrl, getCaretWidth, 0}}, + {3169, {wxStyledTextCtrl, setTargetStart, 1}}, + {3170, {wxStyledTextCtrl, getTargetStart, 0}}, + {3171, {wxStyledTextCtrl, setTargetEnd, 1}}, + {3172, {wxStyledTextCtrl, getTargetEnd, 0}}, + {3173, {wxStyledTextCtrl, replaceTarget, 1}}, + {3174, {wxStyledTextCtrl, searchInTarget, 1}}, + {3175, {wxStyledTextCtrl, setSearchFlags, 1}}, + {3176, {wxStyledTextCtrl, getSearchFlags, 0}}, + {3177, {wxStyledTextCtrl, callTipShow, 2}}, + {3178, {wxStyledTextCtrl, callTipCancel, 0}}, + {3179, {wxStyledTextCtrl, callTipActive, 0}}, + {3180, {wxStyledTextCtrl, callTipPosAtStart, 0}}, + {3181, {wxStyledTextCtrl, callTipSetHighlight, 2}}, + {3182, {wxStyledTextCtrl, callTipSetBackground, 1}}, + {3183, {wxStyledTextCtrl, callTipSetForeground, 1}}, + {3184, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}}, + {3185, {wxStyledTextCtrl, callTipUseStyle, 1}}, + {3186, {wxStyledTextCtrl, visibleFromDocLine, 1}}, + {3187, {wxStyledTextCtrl, docLineFromVisible, 1}}, + {3188, {wxStyledTextCtrl, wrapCount, 1}}, + {3189, {wxStyledTextCtrl, setFoldLevel, 2}}, + {3190, {wxStyledTextCtrl, getFoldLevel, 1}}, + {3191, {wxStyledTextCtrl, getLastChild, 2}}, + {3192, {wxStyledTextCtrl, getFoldParent, 1}}, + {3193, {wxStyledTextCtrl, showLines, 2}}, + {3194, {wxStyledTextCtrl, hideLines, 2}}, + {3195, {wxStyledTextCtrl, getLineVisible, 1}}, + {3196, {wxStyledTextCtrl, setFoldExpanded, 2}}, + {3197, {wxStyledTextCtrl, getFoldExpanded, 1}}, + {3198, {wxStyledTextCtrl, toggleFold, 1}}, + {3199, {wxStyledTextCtrl, ensureVisible, 1}}, + {3200, {wxStyledTextCtrl, setFoldFlags, 1}}, + {3201, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}}, + {3202, {wxStyledTextCtrl, setTabIndents, 1}}, + {3203, {wxStyledTextCtrl, getTabIndents, 0}}, + {3204, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}}, + {3205, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}}, + {3206, {wxStyledTextCtrl, setMouseDwellTime, 1}}, + {3207, {wxStyledTextCtrl, getMouseDwellTime, 0}}, + {3208, {wxStyledTextCtrl, wordStartPosition, 2}}, + {3209, {wxStyledTextCtrl, wordEndPosition, 2}}, + {3210, {wxStyledTextCtrl, setWrapMode, 1}}, + {3211, {wxStyledTextCtrl, getWrapMode, 0}}, + {3212, {wxStyledTextCtrl, setWrapVisualFlags, 1}}, + {3213, {wxStyledTextCtrl, getWrapVisualFlags, 0}}, + {3214, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}}, + {3215, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}}, + {3216, {wxStyledTextCtrl, setWrapStartIndent, 1}}, + {3217, {wxStyledTextCtrl, getWrapStartIndent, 0}}, + {3218, {wxStyledTextCtrl, setLayoutCache, 1}}, + {3219, {wxStyledTextCtrl, getLayoutCache, 0}}, + {3220, {wxStyledTextCtrl, setScrollWidth, 1}}, + {3221, {wxStyledTextCtrl, getScrollWidth, 0}}, + {3222, {wxStyledTextCtrl, textWidth, 2}}, + {3223, {wxStyledTextCtrl, getEndAtLastLine, 0}}, + {3224, {wxStyledTextCtrl, textHeight, 1}}, + {3225, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}}, + {3226, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}}, + {3227, {wxStyledTextCtrl, appendText, 1}}, + {3228, {wxStyledTextCtrl, getTwoPhaseDraw, 0}}, + {3229, {wxStyledTextCtrl, setTwoPhaseDraw, 1}}, + {3230, {wxStyledTextCtrl, targetFromSelection, 0}}, + {3231, {wxStyledTextCtrl, linesJoin, 0}}, + {3232, {wxStyledTextCtrl, linesSplit, 1}}, + {3233, {wxStyledTextCtrl, setFoldMarginColour, 2}}, + {3234, {wxStyledTextCtrl, setFoldMarginHiColour, 2}}, + {3235, {wxStyledTextCtrl, lineDown, 0}}, + {3236, {wxStyledTextCtrl, lineDownExtend, 0}}, + {3237, {wxStyledTextCtrl, lineUp, 0}}, + {3238, {wxStyledTextCtrl, lineUpExtend, 0}}, + {3239, {wxStyledTextCtrl, charLeft, 0}}, + {3240, {wxStyledTextCtrl, charLeftExtend, 0}}, + {3241, {wxStyledTextCtrl, charRight, 0}}, + {3242, {wxStyledTextCtrl, charRightExtend, 0}}, + {3243, {wxStyledTextCtrl, wordLeft, 0}}, + {3244, {wxStyledTextCtrl, wordLeftExtend, 0}}, + {3245, {wxStyledTextCtrl, wordRight, 0}}, + {3246, {wxStyledTextCtrl, wordRightExtend, 0}}, + {3247, {wxStyledTextCtrl, home, 0}}, + {3248, {wxStyledTextCtrl, homeExtend, 0}}, + {3249, {wxStyledTextCtrl, lineEnd, 0}}, + {3250, {wxStyledTextCtrl, lineEndExtend, 0}}, + {3251, {wxStyledTextCtrl, documentStart, 0}}, + {3252, {wxStyledTextCtrl, documentStartExtend, 0}}, + {3253, {wxStyledTextCtrl, documentEnd, 0}}, + {3254, {wxStyledTextCtrl, documentEndExtend, 0}}, + {3255, {wxStyledTextCtrl, pageUp, 0}}, + {3256, {wxStyledTextCtrl, pageUpExtend, 0}}, + {3257, {wxStyledTextCtrl, pageDown, 0}}, + {3258, {wxStyledTextCtrl, pageDownExtend, 0}}, + {3259, {wxStyledTextCtrl, editToggleOvertype, 0}}, + {3260, {wxStyledTextCtrl, cancel, 0}}, + {3261, {wxStyledTextCtrl, deleteBack, 0}}, + {3262, {wxStyledTextCtrl, tab, 0}}, + {3263, {wxStyledTextCtrl, backTab, 0}}, + {3264, {wxStyledTextCtrl, newLine, 0}}, + {3265, {wxStyledTextCtrl, formFeed, 0}}, + {3266, {wxStyledTextCtrl, vCHome, 0}}, + {3267, {wxStyledTextCtrl, vCHomeExtend, 0}}, + {3268, {wxStyledTextCtrl, zoomIn, 0}}, + {3269, {wxStyledTextCtrl, zoomOut, 0}}, + {3270, {wxStyledTextCtrl, delWordLeft, 0}}, + {3271, {wxStyledTextCtrl, delWordRight, 0}}, + {3272, {wxStyledTextCtrl, lineCut, 0}}, + {3273, {wxStyledTextCtrl, lineDelete, 0}}, + {3274, {wxStyledTextCtrl, lineTranspose, 0}}, + {3275, {wxStyledTextCtrl, lineDuplicate, 0}}, + {3276, {wxStyledTextCtrl, lowerCase, 0}}, + {3277, {wxStyledTextCtrl, upperCase, 0}}, + {3278, {wxStyledTextCtrl, lineScrollDown, 0}}, + {3279, {wxStyledTextCtrl, lineScrollUp, 0}}, + {3280, {wxStyledTextCtrl, deleteBackNotLine, 0}}, + {3281, {wxStyledTextCtrl, homeDisplay, 0}}, + {3282, {wxStyledTextCtrl, homeDisplayExtend, 0}}, + {3283, {wxStyledTextCtrl, lineEndDisplay, 0}}, + {3284, {wxStyledTextCtrl, lineEndDisplayExtend, 0}}, + {3285, {wxStyledTextCtrl, homeWrapExtend, 0}}, + {3286, {wxStyledTextCtrl, lineEndWrap, 0}}, + {3287, {wxStyledTextCtrl, lineEndWrapExtend, 0}}, + {3288, {wxStyledTextCtrl, vCHomeWrap, 0}}, + {3289, {wxStyledTextCtrl, vCHomeWrapExtend, 0}}, + {3290, {wxStyledTextCtrl, lineCopy, 0}}, + {3291, {wxStyledTextCtrl, moveCaretInsideView, 0}}, + {3292, {wxStyledTextCtrl, lineLength, 1}}, + {3293, {wxStyledTextCtrl, braceHighlight, 2}}, + {3294, {wxStyledTextCtrl, braceBadLight, 1}}, + {3295, {wxStyledTextCtrl, braceMatch, 1}}, + {3296, {wxStyledTextCtrl, getViewEOL, 0}}, + {3297, {wxStyledTextCtrl, setViewEOL, 1}}, + {3298, {wxStyledTextCtrl, setModEventMask, 1}}, + {3299, {wxStyledTextCtrl, getEdgeColumn, 0}}, + {3300, {wxStyledTextCtrl, setEdgeColumn, 1}}, + {3301, {wxStyledTextCtrl, setEdgeMode, 1}}, + {3302, {wxStyledTextCtrl, getEdgeMode, 0}}, + {3303, {wxStyledTextCtrl, getEdgeColour, 0}}, + {3304, {wxStyledTextCtrl, setEdgeColour, 1}}, + {3305, {wxStyledTextCtrl, searchAnchor, 0}}, + {3306, {wxStyledTextCtrl, searchNext, 2}}, + {3307, {wxStyledTextCtrl, searchPrev, 2}}, + {3308, {wxStyledTextCtrl, linesOnScreen, 0}}, + {3309, {wxStyledTextCtrl, usePopUp, 1}}, + {3310, {wxStyledTextCtrl, selectionIsRectangle, 0}}, + {3311, {wxStyledTextCtrl, setZoom, 1}}, + {3312, {wxStyledTextCtrl, getZoom, 0}}, + {3313, {wxStyledTextCtrl, getModEventMask, 0}}, + {3314, {wxStyledTextCtrl, setSTCFocus, 1}}, + {3315, {wxStyledTextCtrl, getSTCFocus, 0}}, + {3316, {wxStyledTextCtrl, setStatus, 1}}, + {3317, {wxStyledTextCtrl, getStatus, 0}}, + {3318, {wxStyledTextCtrl, setMouseDownCaptures, 1}}, + {3319, {wxStyledTextCtrl, getMouseDownCaptures, 0}}, + {3320, {wxStyledTextCtrl, setSTCCursor, 1}}, + {3321, {wxStyledTextCtrl, getSTCCursor, 0}}, + {3322, {wxStyledTextCtrl, setControlCharSymbol, 1}}, + {3323, {wxStyledTextCtrl, getControlCharSymbol, 0}}, + {3324, {wxStyledTextCtrl, wordPartLeft, 0}}, + {3325, {wxStyledTextCtrl, wordPartLeftExtend, 0}}, + {3326, {wxStyledTextCtrl, wordPartRight, 0}}, + {3327, {wxStyledTextCtrl, wordPartRightExtend, 0}}, + {3328, {wxStyledTextCtrl, setVisiblePolicy, 2}}, + {3329, {wxStyledTextCtrl, delLineLeft, 0}}, + {3330, {wxStyledTextCtrl, delLineRight, 0}}, + {3331, {wxStyledTextCtrl, getXOffset, 0}}, + {3332, {wxStyledTextCtrl, chooseCaretX, 0}}, + {3333, {wxStyledTextCtrl, setXCaretPolicy, 2}}, + {3334, {wxStyledTextCtrl, setYCaretPolicy, 2}}, + {3335, {wxStyledTextCtrl, getPrintWrapMode, 0}}, + {3336, {wxStyledTextCtrl, setHotspotActiveForeground, 2}}, + {3337, {wxStyledTextCtrl, setHotspotActiveBackground, 2}}, + {3338, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}}, + {3339, {wxStyledTextCtrl, setHotspotSingleLine, 1}}, + {3340, {wxStyledTextCtrl, paraDownExtend, 0}}, + {3341, {wxStyledTextCtrl, paraUp, 0}}, + {3342, {wxStyledTextCtrl, paraUpExtend, 0}}, + {3343, {wxStyledTextCtrl, positionBefore, 1}}, + {3344, {wxStyledTextCtrl, positionAfter, 1}}, + {3345, {wxStyledTextCtrl, copyRange, 2}}, + {3346, {wxStyledTextCtrl, copyText, 2}}, + {3347, {wxStyledTextCtrl, setSelectionMode, 1}}, + {3348, {wxStyledTextCtrl, getSelectionMode, 0}}, + {3349, {wxStyledTextCtrl, lineDownRectExtend, 0}}, + {3350, {wxStyledTextCtrl, lineUpRectExtend, 0}}, + {3351, {wxStyledTextCtrl, charLeftRectExtend, 0}}, + {3352, {wxStyledTextCtrl, charRightRectExtend, 0}}, + {3353, {wxStyledTextCtrl, homeRectExtend, 0}}, + {3354, {wxStyledTextCtrl, vCHomeRectExtend, 0}}, + {3355, {wxStyledTextCtrl, lineEndRectExtend, 0}}, + {3356, {wxStyledTextCtrl, pageUpRectExtend, 0}}, + {3357, {wxStyledTextCtrl, pageDownRectExtend, 0}}, + {3358, {wxStyledTextCtrl, stutteredPageUp, 0}}, + {3359, {wxStyledTextCtrl, stutteredPageUpExtend, 0}}, + {3360, {wxStyledTextCtrl, stutteredPageDown, 0}}, + {3361, {wxStyledTextCtrl, stutteredPageDownExtend, 0}}, + {3362, {wxStyledTextCtrl, wordLeftEnd, 0}}, + {3363, {wxStyledTextCtrl, wordLeftEndExtend, 0}}, + {3364, {wxStyledTextCtrl, wordRightEnd, 0}}, + {3365, {wxStyledTextCtrl, wordRightEndExtend, 0}}, + {3366, {wxStyledTextCtrl, setWhitespaceChars, 1}}, + {3367, {wxStyledTextCtrl, setCharsDefault, 0}}, + {3368, {wxStyledTextCtrl, autoCompGetCurrent, 0}}, + {3369, {wxStyledTextCtrl, allocate, 1}}, + {3370, {wxStyledTextCtrl, findColumn, 2}}, + {3371, {wxStyledTextCtrl, getCaretSticky, 0}}, + {3372, {wxStyledTextCtrl, setCaretSticky, 1}}, + {3373, {wxStyledTextCtrl, toggleCaretSticky, 0}}, + {3374, {wxStyledTextCtrl, setPasteConvertEndings, 1}}, + {3375, {wxStyledTextCtrl, getPasteConvertEndings, 0}}, + {3376, {wxStyledTextCtrl, selectionDuplicate, 0}}, + {3377, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}}, + {3378, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}}, + {3379, {wxStyledTextCtrl, startRecord, 0}}, + {3380, {wxStyledTextCtrl, stopRecord, 0}}, + {3381, {wxStyledTextCtrl, setLexer, 1}}, + {3382, {wxStyledTextCtrl, getLexer, 0}}, + {3383, {wxStyledTextCtrl, colourise, 2}}, + {3384, {wxStyledTextCtrl, setProperty, 2}}, + {3385, {wxStyledTextCtrl, setKeyWords, 2}}, + {3386, {wxStyledTextCtrl, setLexerLanguage, 1}}, + {3387, {wxStyledTextCtrl, getProperty, 1}}, + {3388, {wxStyledTextCtrl, getStyleBitsNeeded, 0}}, + {3389, {wxStyledTextCtrl, getCurrentLine, 0}}, + {3390, {wxStyledTextCtrl, styleSetSpec, 2}}, + {3391, {wxStyledTextCtrl, styleSetFont, 2}}, + {3392, {wxStyledTextCtrl, styleSetFontAttr, 7}}, + {3393, {wxStyledTextCtrl, styleSetCharacterSet, 2}}, + {3394, {wxStyledTextCtrl, styleSetFontEncoding, 2}}, + {3395, {wxStyledTextCtrl, cmdKeyExecute, 1}}, + {3396, {wxStyledTextCtrl, setMargins, 2}}, + {3397, {wxStyledTextCtrl, getSelection, 2}}, + {3398, {wxStyledTextCtrl, pointFromPosition, 1}}, + {3399, {wxStyledTextCtrl, scrollToLine, 1}}, + {3400, {wxStyledTextCtrl, scrollToColumn, 1}}, + {3401, {wxStyledTextCtrl, setVScrollBar, 1}}, + {3402, {wxStyledTextCtrl, setHScrollBar, 1}}, + {3403, {wxStyledTextCtrl, getLastKeydownProcessed, 0}}, + {3404, {wxStyledTextCtrl, setLastKeydownProcessed, 1}}, + {3405, {wxStyledTextCtrl, saveFile, 1}}, + {3406, {wxStyledTextCtrl, loadFile, 1}}, + {3407, {wxStyledTextCtrl, doDragOver, 3}}, + {3408, {wxStyledTextCtrl, doDropText, 3}}, + {3409, {wxStyledTextCtrl, getUseAntiAliasing, 0}}, + {3410, {wxStyledTextCtrl, addTextRaw, 1}}, + {3411, {wxStyledTextCtrl, insertTextRaw, 2}}, + {3412, {wxStyledTextCtrl, getCurLineRaw, 1}}, + {3413, {wxStyledTextCtrl, getLineRaw, 1}}, + {3414, {wxStyledTextCtrl, getSelectedTextRaw, 0}}, + {3415, {wxStyledTextCtrl, getTextRangeRaw, 2}}, + {3416, {wxStyledTextCtrl, setTextRaw, 1}}, + {3417, {wxStyledTextCtrl, getTextRaw, 0}}, + {3418, {wxStyledTextCtrl, appendTextRaw, 1}}, + {3419, {wxArtProvider, getBitmap, 2}}, + {3420, {wxArtProvider, getIcon, 2}}, + {3421, {wxTreeEvent, getKeyCode, 0}}, + {3422, {wxTreeEvent, getItem, 0}}, + {3423, {wxTreeEvent, getKeyEvent, 0}}, + {3424, {wxTreeEvent, getLabel, 0}}, + {3425, {wxTreeEvent, getOldItem, 0}}, + {3426, {wxTreeEvent, getPoint, 0}}, + {3427, {wxTreeEvent, isEditCancelled, 0}}, + {3428, {wxTreeEvent, setToolTip, 1}}, + {3429, {wxNotebookEvent, getOldSelection, 0}}, + {3430, {wxNotebookEvent, getSelection, 0}}, + {3431, {wxNotebookEvent, setOldSelection, 1}}, + {3432, {wxNotebookEvent, setSelection, 1}}, + {3433, {wxFileDataObject, new, 0}}, + {3434, {wxFileDataObject, addFile, 1}}, + {3435, {wxFileDataObject, getFilenames, 0}}, + {3436, {wxFileDataObject, 'Destroy', undefined}}, + {3437, {wxTextDataObject, new, 1}}, + {3438, {wxTextDataObject, getTextLength, 0}}, + {3439, {wxTextDataObject, getText, 0}}, + {3440, {wxTextDataObject, setText, 1}}, + {3441, {wxTextDataObject, 'Destroy', undefined}}, + {3442, {wxBitmapDataObject, new_1_1, 1}}, + {3443, {wxBitmapDataObject, new_1_0, 1}}, + {3444, {wxBitmapDataObject, getBitmap, 0}}, + {3445, {wxBitmapDataObject, setBitmap, 1}}, + {3446, {wxBitmapDataObject, 'Destroy', undefined}}, + {3448, {wxClipboard, new, 0}}, + {3449, {wxClipboard, destruct, 0}}, + {3450, {wxClipboard, addData, 1}}, + {3451, {wxClipboard, clear, 0}}, + {3452, {wxClipboard, close, 0}}, + {3453, {wxClipboard, flush, 0}}, + {3454, {wxClipboard, getData, 1}}, + {3455, {wxClipboard, isOpened, 0}}, + {3456, {wxClipboard, open, 0}}, + {3457, {wxClipboard, setData, 1}}, + {3459, {wxClipboard, usePrimarySelection, 1}}, + {3460, {wxClipboard, isSupported, 1}}, + {3461, {wxClipboard, get, 0}}, + {3462, {wxSpinEvent, getPosition, 0}}, + {3463, {wxSpinEvent, setPosition, 1}}, + {3464, {wxSplitterWindow, new_0, 0}}, + {3465, {wxSplitterWindow, new_2, 2}}, + {3466, {wxSplitterWindow, destruct, 0}}, + {3467, {wxSplitterWindow, create, 2}}, + {3468, {wxSplitterWindow, getMinimumPaneSize, 0}}, + {3469, {wxSplitterWindow, getSashGravity, 0}}, + {3470, {wxSplitterWindow, getSashPosition, 0}}, + {3471, {wxSplitterWindow, getSplitMode, 0}}, + {3472, {wxSplitterWindow, getWindow1, 0}}, + {3473, {wxSplitterWindow, getWindow2, 0}}, + {3474, {wxSplitterWindow, initialize, 1}}, + {3475, {wxSplitterWindow, isSplit, 0}}, + {3476, {wxSplitterWindow, replaceWindow, 2}}, + {3477, {wxSplitterWindow, setSashGravity, 1}}, + {3478, {wxSplitterWindow, setSashPosition, 2}}, + {3479, {wxSplitterWindow, setSashSize, 1}}, + {3480, {wxSplitterWindow, setMinimumPaneSize, 1}}, + {3481, {wxSplitterWindow, setSplitMode, 1}}, + {3482, {wxSplitterWindow, splitHorizontally, 3}}, + {3483, {wxSplitterWindow, splitVertically, 3}}, + {3484, {wxSplitterWindow, unsplit, 1}}, + {3485, {wxSplitterWindow, updateSize, 0}}, + {3486, {wxSplitterEvent, getSashPosition, 0}}, + {3487, {wxSplitterEvent, getX, 0}}, + {3488, {wxSplitterEvent, getY, 0}}, + {3489, {wxSplitterEvent, getWindowBeingRemoved, 0}}, + {3490, {wxSplitterEvent, setSashPosition, 1}}, + {3491, {wxHtmlWindow, new_0, 0}}, + {3492, {wxHtmlWindow, new_2, 2}}, + {3493, {wxHtmlWindow, appendToPage, 1}}, + {3494, {wxHtmlWindow, getOpenedAnchor, 0}}, + {3495, {wxHtmlWindow, getOpenedPage, 0}}, + {3496, {wxHtmlWindow, getOpenedPageTitle, 0}}, + {3497, {wxHtmlWindow, getRelatedFrame, 0}}, + {3498, {wxHtmlWindow, historyBack, 0}}, + {3499, {wxHtmlWindow, historyCanBack, 0}}, + {3500, {wxHtmlWindow, historyCanForward, 0}}, + {3501, {wxHtmlWindow, historyClear, 0}}, + {3502, {wxHtmlWindow, historyForward, 0}}, + {3503, {wxHtmlWindow, loadFile, 1}}, + {3504, {wxHtmlWindow, loadPage, 1}}, + {3505, {wxHtmlWindow, selectAll, 0}}, + {3506, {wxHtmlWindow, selectionToText, 0}}, + {3507, {wxHtmlWindow, selectLine, 1}}, + {3508, {wxHtmlWindow, selectWord, 1}}, + {3509, {wxHtmlWindow, setBorders, 1}}, + {3510, {wxHtmlWindow, setFonts, 3}}, + {3511, {wxHtmlWindow, setPage, 1}}, + {3512, {wxHtmlWindow, setRelatedFrame, 2}}, + {3513, {wxHtmlWindow, setRelatedStatusBar, 1}}, + {3514, {wxHtmlWindow, toText, 0}}, + {3515, {wxHtmlWindow, 'Destroy', undefined}}, + {3516, {wxHtmlLinkEvent, getLinkInfo, 0}}, + {3517, {wxSystemSettings, getColour, 1}}, + {3518, {wxSystemSettings, getFont, 1}}, + {3519, {wxSystemSettings, getMetric, 2}}, + {3520, {wxSystemSettings, getScreenType, 0}}, + {3521, {wxSystemOptions, getOption, 1}}, + {3522, {wxSystemOptions, getOptionInt, 1}}, + {3523, {wxSystemOptions, hasOption, 1}}, + {3524, {wxSystemOptions, isFalse, 1}}, + {3525, {wxSystemOptions, setOption_2_1, 2}}, + {3526, {wxSystemOptions, setOption_2_0, 2}}, + {3527, {wxAuiNotebookEvent, setSelection, 1}}, + {3528, {wxAuiNotebookEvent, getSelection, 0}}, + {3529, {wxAuiNotebookEvent, setOldSelection, 1}}, + {3530, {wxAuiNotebookEvent, getOldSelection, 0}}, + {3531, {wxAuiNotebookEvent, setDragSource, 1}}, + {3532, {wxAuiNotebookEvent, getDragSource, 0}}, + {3533, {wxAuiManagerEvent, setManager, 1}}, + {3534, {wxAuiManagerEvent, getManager, 0}}, + {3535, {wxAuiManagerEvent, setPane, 1}}, + {3536, {wxAuiManagerEvent, getPane, 0}}, + {3537, {wxAuiManagerEvent, setButton, 1}}, + {3538, {wxAuiManagerEvent, getButton, 0}}, + {3539, {wxAuiManagerEvent, setDC, 1}}, + {3540, {wxAuiManagerEvent, getDC, 0}}, + {3541, {wxAuiManagerEvent, veto, 1}}, + {3542, {wxAuiManagerEvent, getVeto, 0}}, + {3543, {wxAuiManagerEvent, setCanVeto, 1}}, + {3544, {wxAuiManagerEvent, canVeto, 0}}, + {3545, {wxLogNull, new, 0}}, + {3546, {wxLogNull, 'Destroy', undefined}}, + {3547, {wxTaskBarIcon, new, 0}}, + {3548, {wxTaskBarIcon, destruct, 0}}, + {3549, {wxTaskBarIcon, popupMenu, 1}}, + {3550, {wxTaskBarIcon, removeIcon, 0}}, + {3551, {wxTaskBarIcon, setIcon, 2}}, + {3552, {wxLocale, new_0, 0}}, + {3554, {wxLocale, new_2, 2}}, + {3555, {wxLocale, destruct, 0}}, + {3557, {wxLocale, init, 1}}, + {3558, {wxLocale, addCatalog_1, 1}}, + {3559, {wxLocale, addCatalog_3, 3}}, + {3560, {wxLocale, addCatalogLookupPathPrefix, 1}}, + {3561, {wxLocale, getCanonicalName, 0}}, + {3562, {wxLocale, getLanguage, 0}}, + {3563, {wxLocale, getLanguageName, 1}}, + {3564, {wxLocale, getLocale, 0}}, + {3565, {wxLocale, getName, 0}}, + {3566, {wxLocale, getString_2, 2}}, + {3567, {wxLocale, getString_4, 4}}, + {3568, {wxLocale, getHeaderValue, 2}}, + {3569, {wxLocale, getSysName, 0}}, + {3570, {wxLocale, getSystemEncoding, 0}}, + {3571, {wxLocale, getSystemEncodingName, 0}}, + {3572, {wxLocale, getSystemLanguage, 0}}, + {3573, {wxLocale, isLoaded, 1}}, + {3574, {wxLocale, isOk, 0}}, + {3575, {wxActivateEvent, getActive, 0}}, + {3577, {wxPopupWindow, new_2, 2}}, + {3578, {wxPopupWindow, new_0, 0}}, + {3580, {wxPopupWindow, destruct, 0}}, + {3581, {wxPopupWindow, create, 2}}, + {3582, {wxPopupWindow, position, 2}}, + {3583, {wxPopupTransientWindow, new_0, 0}}, + {3584, {wxPopupTransientWindow, new_2, 2}}, + {3585, {wxPopupTransientWindow, destruct, 0}}, + {3586, {wxPopupTransientWindow, popup, 1}}, + {3587, {wxPopupTransientWindow, dismiss, 0}}, + {3588, {wxOverlay, new, 0}}, + {3589, {wxOverlay, destruct, 0}}, + {3590, {wxOverlay, reset, 0}}, + {3591, {wxDCOverlay, new_6, 6}}, + {3592, {wxDCOverlay, new_2, 2}}, + {3593, {wxDCOverlay, destruct, 0}}, + {3594, {wxDCOverlay, clear, 0}}, {-1, {mod, func, -1}} ]. diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl index 3a34cd494d..35688f3869 100644 --- a/lib/wx/src/gen/wxe_funcs.hrl +++ b/lib/wx/src/gen/wxe_funcs.hrl @@ -860,2510 +860,2512 @@ -define(wxToolBar_AddTool_6, 981). -define(wxToolBar_AddCheckTool, 982). -define(wxToolBar_AddRadioTool, 983). --define(wxToolBar_DeleteTool, 984). --define(wxToolBar_DeleteToolByPos, 985). --define(wxToolBar_EnableTool, 986). --define(wxToolBar_FindById, 987). --define(wxToolBar_FindControl, 988). --define(wxToolBar_FindToolForPosition, 989). --define(wxToolBar_GetToolSize, 990). --define(wxToolBar_GetToolBitmapSize, 991). --define(wxToolBar_GetMargins, 992). --define(wxToolBar_GetToolEnabled, 993). --define(wxToolBar_GetToolLongHelp, 994). --define(wxToolBar_GetToolPacking, 995). --define(wxToolBar_GetToolPos, 996). --define(wxToolBar_GetToolSeparation, 997). --define(wxToolBar_GetToolShortHelp, 998). --define(wxToolBar_GetToolState, 999). --define(wxToolBar_InsertControl, 1000). --define(wxToolBar_InsertSeparator, 1001). --define(wxToolBar_InsertTool_5, 1002). --define(wxToolBar_InsertTool_2, 1003). --define(wxToolBar_InsertTool_4, 1004). --define(wxToolBar_Realize, 1005). --define(wxToolBar_RemoveTool, 1006). --define(wxToolBar_SetMargins, 1007). --define(wxToolBar_SetToolBitmapSize, 1008). --define(wxToolBar_SetToolLongHelp, 1009). --define(wxToolBar_SetToolPacking, 1010). --define(wxToolBar_SetToolShortHelp, 1011). --define(wxToolBar_SetToolSeparation, 1012). --define(wxToolBar_ToggleTool, 1013). --define(wxStatusBar_new_0, 1015). --define(wxStatusBar_new_2, 1016). --define(wxStatusBar_destruct, 1018). --define(wxStatusBar_Create, 1019). --define(wxStatusBar_GetFieldRect, 1020). --define(wxStatusBar_GetFieldsCount, 1021). --define(wxStatusBar_GetStatusText, 1022). --define(wxStatusBar_PopStatusText, 1023). --define(wxStatusBar_PushStatusText, 1024). --define(wxStatusBar_SetFieldsCount, 1025). --define(wxStatusBar_SetMinHeight, 1026). --define(wxStatusBar_SetStatusText, 1027). --define(wxStatusBar_SetStatusWidths, 1028). --define(wxStatusBar_SetStatusStyles, 1029). --define(wxBitmap_new_0, 1030). --define(wxBitmap_new_3, 1031). --define(wxBitmap_new_4, 1032). --define(wxBitmap_new_2_0, 1033). --define(wxBitmap_new_2_1, 1034). --define(wxBitmap_destruct, 1035). --define(wxBitmap_ConvertToImage, 1036). --define(wxBitmap_CopyFromIcon, 1037). --define(wxBitmap_Create, 1038). --define(wxBitmap_GetDepth, 1039). --define(wxBitmap_GetHeight, 1040). --define(wxBitmap_GetPalette, 1041). --define(wxBitmap_GetMask, 1042). --define(wxBitmap_GetWidth, 1043). --define(wxBitmap_GetSubBitmap, 1044). --define(wxBitmap_LoadFile, 1045). --define(wxBitmap_Ok, 1046). --define(wxBitmap_SaveFile, 1047). --define(wxBitmap_SetDepth, 1048). --define(wxBitmap_SetHeight, 1049). --define(wxBitmap_SetMask, 1050). --define(wxBitmap_SetPalette, 1051). --define(wxBitmap_SetWidth, 1052). --define(wxIcon_new_0, 1053). --define(wxIcon_new_2, 1054). --define(wxIcon_new_1, 1055). --define(wxIcon_CopyFromBitmap, 1056). --define(wxIcon_destroy, 1057). --define(wxIconBundle_new_0, 1058). --define(wxIconBundle_new_2, 1059). --define(wxIconBundle_new_1_0, 1060). --define(wxIconBundle_new_1_1, 1061). --define(wxIconBundle_destruct, 1062). --define(wxIconBundle_AddIcon_2, 1063). --define(wxIconBundle_AddIcon_1, 1064). --define(wxIconBundle_GetIcon_1_1, 1065). --define(wxIconBundle_GetIcon_1_0, 1066). --define(wxCursor_new_0, 1067). --define(wxCursor_new_1_0, 1068). --define(wxCursor_new_1_1, 1069). --define(wxCursor_new_4, 1070). --define(wxCursor_destruct, 1071). --define(wxCursor_Ok, 1072). --define(wxMask_new_0, 1073). --define(wxMask_new_2_1, 1074). --define(wxMask_new_2_0, 1075). --define(wxMask_new_1, 1076). --define(wxMask_destruct, 1077). --define(wxMask_Create_2_1, 1078). --define(wxMask_Create_2_0, 1079). --define(wxMask_Create_1, 1080). --define(wxImage_new_0, 1081). --define(wxImage_new_3_0, 1082). --define(wxImage_new_4, 1083). --define(wxImage_new_5, 1084). --define(wxImage_new_2, 1085). --define(wxImage_new_3_1, 1086). --define(wxImage_Blur, 1087). --define(wxImage_BlurHorizontal, 1088). --define(wxImage_BlurVertical, 1089). --define(wxImage_ConvertAlphaToMask, 1090). --define(wxImage_ConvertToGreyscale, 1091). --define(wxImage_ConvertToMono, 1092). --define(wxImage_Copy, 1093). --define(wxImage_Create_3, 1094). --define(wxImage_Create_4, 1095). --define(wxImage_Create_5, 1096). --define(wxImage_Destroy, 1097). --define(wxImage_FindFirstUnusedColour, 1098). --define(wxImage_GetImageExtWildcard, 1099). --define(wxImage_GetAlpha_2, 1100). --define(wxImage_GetAlpha_0, 1101). --define(wxImage_GetBlue, 1102). --define(wxImage_GetData, 1103). --define(wxImage_GetGreen, 1104). --define(wxImage_GetImageCount, 1105). --define(wxImage_GetHeight, 1106). --define(wxImage_GetMaskBlue, 1107). --define(wxImage_GetMaskGreen, 1108). --define(wxImage_GetMaskRed, 1109). --define(wxImage_GetOrFindMaskColour, 1110). --define(wxImage_GetPalette, 1111). --define(wxImage_GetRed, 1112). --define(wxImage_GetSubImage, 1113). --define(wxImage_GetWidth, 1114). --define(wxImage_HasAlpha, 1115). --define(wxImage_HasMask, 1116). --define(wxImage_GetOption, 1117). --define(wxImage_GetOptionInt, 1118). --define(wxImage_HasOption, 1119). --define(wxImage_InitAlpha, 1120). --define(wxImage_InitStandardHandlers, 1121). --define(wxImage_IsTransparent, 1122). --define(wxImage_LoadFile_2, 1123). --define(wxImage_LoadFile_3, 1124). --define(wxImage_Ok, 1125). --define(wxImage_RemoveHandler, 1126). --define(wxImage_Mirror, 1127). --define(wxImage_Replace, 1128). --define(wxImage_Rescale, 1129). --define(wxImage_Resize, 1130). --define(wxImage_Rotate, 1131). --define(wxImage_RotateHue, 1132). --define(wxImage_Rotate90, 1133). --define(wxImage_SaveFile_1, 1134). --define(wxImage_SaveFile_2_0, 1135). --define(wxImage_SaveFile_2_1, 1136). --define(wxImage_Scale, 1137). --define(wxImage_Size, 1138). --define(wxImage_SetAlpha_3, 1139). --define(wxImage_SetAlpha_2, 1140). --define(wxImage_SetData_2, 1141). --define(wxImage_SetData_4, 1142). --define(wxImage_SetMask, 1143). --define(wxImage_SetMaskColour, 1144). --define(wxImage_SetMaskFromImage, 1145). --define(wxImage_SetOption_2_1, 1146). --define(wxImage_SetOption_2_0, 1147). --define(wxImage_SetPalette, 1148). --define(wxImage_SetRGB_5, 1149). --define(wxImage_SetRGB_4, 1150). --define(wxImage_destroy, 1151). --define(wxBrush_new_0, 1152). --define(wxBrush_new_2, 1153). --define(wxBrush_new_1, 1154). --define(wxBrush_destruct, 1156). --define(wxBrush_GetColour, 1157). --define(wxBrush_GetStipple, 1158). --define(wxBrush_GetStyle, 1159). --define(wxBrush_IsHatch, 1160). --define(wxBrush_IsOk, 1161). --define(wxBrush_SetColour_1, 1162). --define(wxBrush_SetColour_3, 1163). --define(wxBrush_SetStipple, 1164). --define(wxBrush_SetStyle, 1165). --define(wxPen_new_0, 1166). --define(wxPen_new_2, 1167). --define(wxPen_destruct, 1168). --define(wxPen_GetCap, 1169). --define(wxPen_GetColour, 1170). --define(wxPen_GetJoin, 1171). --define(wxPen_GetStyle, 1172). --define(wxPen_GetWidth, 1173). --define(wxPen_IsOk, 1174). --define(wxPen_SetCap, 1175). --define(wxPen_SetColour_1, 1176). --define(wxPen_SetColour_3, 1177). --define(wxPen_SetJoin, 1178). --define(wxPen_SetStyle, 1179). --define(wxPen_SetWidth, 1180). --define(wxRegion_new_0, 1181). --define(wxRegion_new_4, 1182). --define(wxRegion_new_2, 1183). --define(wxRegion_new_1_1, 1184). --define(wxRegion_new_1_0, 1186). --define(wxRegion_destruct, 1188). --define(wxRegion_Clear, 1189). --define(wxRegion_Contains_2, 1190). --define(wxRegion_Contains_1_0, 1191). --define(wxRegion_Contains_4, 1192). --define(wxRegion_Contains_1_1, 1193). --define(wxRegion_ConvertToBitmap, 1194). --define(wxRegion_GetBox, 1195). --define(wxRegion_Intersect_4, 1196). --define(wxRegion_Intersect_1_1, 1197). --define(wxRegion_Intersect_1_0, 1198). --define(wxRegion_IsEmpty, 1199). --define(wxRegion_Subtract_4, 1200). --define(wxRegion_Subtract_1_1, 1201). --define(wxRegion_Subtract_1_0, 1202). --define(wxRegion_Offset_2, 1203). --define(wxRegion_Offset_1, 1204). --define(wxRegion_Union_4, 1205). --define(wxRegion_Union_1_2, 1206). --define(wxRegion_Union_1_1, 1207). --define(wxRegion_Union_1_0, 1208). --define(wxRegion_Union_3, 1209). --define(wxRegion_Xor_4, 1210). --define(wxRegion_Xor_1_1, 1211). --define(wxRegion_Xor_1_0, 1212). --define(wxAcceleratorTable_new_0, 1213). --define(wxAcceleratorTable_new_2, 1214). --define(wxAcceleratorTable_destruct, 1215). --define(wxAcceleratorTable_Ok, 1216). --define(wxAcceleratorEntry_new_1_0, 1217). --define(wxAcceleratorEntry_new_1_1, 1218). --define(wxAcceleratorEntry_GetCommand, 1219). --define(wxAcceleratorEntry_GetFlags, 1220). --define(wxAcceleratorEntry_GetKeyCode, 1221). --define(wxAcceleratorEntry_Set, 1222). --define(wxAcceleratorEntry_destroy, 1223). --define(wxCaret_new_3, 1228). --define(wxCaret_new_2, 1229). --define(wxCaret_destruct, 1231). --define(wxCaret_Create_3, 1232). --define(wxCaret_Create_2, 1233). --define(wxCaret_GetBlinkTime, 1234). --define(wxCaret_GetPosition, 1236). --define(wxCaret_GetSize, 1238). --define(wxCaret_GetWindow, 1239). --define(wxCaret_Hide, 1240). --define(wxCaret_IsOk, 1241). --define(wxCaret_IsVisible, 1242). --define(wxCaret_Move_2, 1243). --define(wxCaret_Move_1, 1244). --define(wxCaret_SetBlinkTime, 1245). --define(wxCaret_SetSize_2, 1246). --define(wxCaret_SetSize_1, 1247). --define(wxCaret_Show, 1248). --define(wxSizer_Add_2_1, 1249). --define(wxSizer_Add_2_0, 1250). --define(wxSizer_Add_3, 1251). --define(wxSizer_Add_2_3, 1252). --define(wxSizer_Add_2_2, 1253). --define(wxSizer_AddSpacer, 1254). --define(wxSizer_AddStretchSpacer, 1255). --define(wxSizer_CalcMin, 1256). --define(wxSizer_Clear, 1257). --define(wxSizer_Detach_1_2, 1258). --define(wxSizer_Detach_1_1, 1259). --define(wxSizer_Detach_1_0, 1260). --define(wxSizer_Fit, 1261). --define(wxSizer_FitInside, 1262). --define(wxSizer_GetChildren, 1263). --define(wxSizer_GetItem_2_1, 1264). --define(wxSizer_GetItem_2_0, 1265). --define(wxSizer_GetItem_1, 1266). --define(wxSizer_GetSize, 1267). --define(wxSizer_GetPosition, 1268). --define(wxSizer_GetMinSize, 1269). --define(wxSizer_Hide_2_0, 1270). --define(wxSizer_Hide_2_1, 1271). --define(wxSizer_Hide_1, 1272). --define(wxSizer_Insert_3_1, 1273). --define(wxSizer_Insert_3_0, 1274). --define(wxSizer_Insert_4, 1275). --define(wxSizer_Insert_3_3, 1276). --define(wxSizer_Insert_3_2, 1277). --define(wxSizer_Insert_2, 1278). --define(wxSizer_InsertSpacer, 1279). --define(wxSizer_InsertStretchSpacer, 1280). --define(wxSizer_IsShown_1_2, 1281). --define(wxSizer_IsShown_1_1, 1282). --define(wxSizer_IsShown_1_0, 1283). --define(wxSizer_Layout, 1284). --define(wxSizer_Prepend_2_1, 1285). --define(wxSizer_Prepend_2_0, 1286). --define(wxSizer_Prepend_3, 1287). --define(wxSizer_Prepend_2_3, 1288). --define(wxSizer_Prepend_2_2, 1289). --define(wxSizer_Prepend_1, 1290). --define(wxSizer_PrependSpacer, 1291). --define(wxSizer_PrependStretchSpacer, 1292). --define(wxSizer_RecalcSizes, 1293). --define(wxSizer_Remove_1_1, 1294). --define(wxSizer_Remove_1_0, 1295). --define(wxSizer_Replace_3_1, 1296). --define(wxSizer_Replace_3_0, 1297). --define(wxSizer_Replace_2, 1298). --define(wxSizer_SetDimension, 1299). --define(wxSizer_SetMinSize_2, 1300). --define(wxSizer_SetMinSize_1, 1301). --define(wxSizer_SetItemMinSize_3_2, 1302). --define(wxSizer_SetItemMinSize_2_2, 1303). --define(wxSizer_SetItemMinSize_3_1, 1304). --define(wxSizer_SetItemMinSize_2_1, 1305). --define(wxSizer_SetItemMinSize_3_0, 1306). --define(wxSizer_SetItemMinSize_2_0, 1307). --define(wxSizer_SetSizeHints, 1308). --define(wxSizer_SetVirtualSizeHints, 1309). --define(wxSizer_Show_2_2, 1310). --define(wxSizer_Show_2_1, 1311). --define(wxSizer_Show_2_0, 1312). --define(wxSizer_Show_1, 1313). --define(wxSizerFlags_new, 1314). --define(wxSizerFlags_Align, 1315). --define(wxSizerFlags_Border_2, 1316). --define(wxSizerFlags_Border_1, 1317). --define(wxSizerFlags_Center, 1318). --define(wxSizerFlags_Centre, 1319). --define(wxSizerFlags_Expand, 1320). --define(wxSizerFlags_Left, 1321). --define(wxSizerFlags_Proportion, 1322). --define(wxSizerFlags_Right, 1323). --define(wxSizerFlags_destroy, 1324). --define(wxSizerItem_new_5_1, 1325). --define(wxSizerItem_new_2_1, 1326). --define(wxSizerItem_new_5_0, 1327). --define(wxSizerItem_new_2_0, 1328). --define(wxSizerItem_new_6, 1329). --define(wxSizerItem_new_3, 1330). --define(wxSizerItem_new_0, 1331). --define(wxSizerItem_destruct, 1332). --define(wxSizerItem_CalcMin, 1333). --define(wxSizerItem_DeleteWindows, 1334). --define(wxSizerItem_DetachSizer, 1335). --define(wxSizerItem_GetBorder, 1336). --define(wxSizerItem_GetFlag, 1337). --define(wxSizerItem_GetMinSize, 1338). --define(wxSizerItem_GetPosition, 1339). --define(wxSizerItem_GetProportion, 1340). --define(wxSizerItem_GetRatio, 1341). --define(wxSizerItem_GetRect, 1342). --define(wxSizerItem_GetSize, 1343). --define(wxSizerItem_GetSizer, 1344). --define(wxSizerItem_GetSpacer, 1345). --define(wxSizerItem_GetUserData, 1346). --define(wxSizerItem_GetWindow, 1347). --define(wxSizerItem_IsSizer, 1348). --define(wxSizerItem_IsShown, 1349). --define(wxSizerItem_IsSpacer, 1350). --define(wxSizerItem_IsWindow, 1351). --define(wxSizerItem_SetBorder, 1352). --define(wxSizerItem_SetDimension, 1353). --define(wxSizerItem_SetFlag, 1354). --define(wxSizerItem_SetInitSize, 1355). --define(wxSizerItem_SetMinSize_1, 1356). --define(wxSizerItem_SetMinSize_2, 1357). --define(wxSizerItem_SetProportion, 1358). --define(wxSizerItem_SetRatio_2, 1359). --define(wxSizerItem_SetRatio_1_1, 1360). --define(wxSizerItem_SetRatio_1_0, 1361). --define(wxSizerItem_SetSizer, 1362). --define(wxSizerItem_SetSpacer_1, 1363). --define(wxSizerItem_SetSpacer_2, 1364). --define(wxSizerItem_SetWindow, 1365). --define(wxSizerItem_Show, 1366). --define(wxBoxSizer_new, 1367). --define(wxBoxSizer_GetOrientation, 1368). --define(wxBoxSizer_destroy, 1369). --define(wxStaticBoxSizer_new_2, 1370). --define(wxStaticBoxSizer_new_3, 1371). --define(wxStaticBoxSizer_GetStaticBox, 1372). --define(wxStaticBoxSizer_destroy, 1373). --define(wxGridSizer_new_4, 1374). --define(wxGridSizer_new_2, 1375). --define(wxGridSizer_GetCols, 1376). --define(wxGridSizer_GetHGap, 1377). --define(wxGridSizer_GetRows, 1378). --define(wxGridSizer_GetVGap, 1379). --define(wxGridSizer_SetCols, 1380). --define(wxGridSizer_SetHGap, 1381). --define(wxGridSizer_SetRows, 1382). --define(wxGridSizer_SetVGap, 1383). --define(wxGridSizer_destroy, 1384). --define(wxFlexGridSizer_new_4, 1385). --define(wxFlexGridSizer_new_2, 1386). --define(wxFlexGridSizer_AddGrowableCol, 1387). --define(wxFlexGridSizer_AddGrowableRow, 1388). --define(wxFlexGridSizer_GetFlexibleDirection, 1389). --define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1390). --define(wxFlexGridSizer_RemoveGrowableCol, 1391). --define(wxFlexGridSizer_RemoveGrowableRow, 1392). --define(wxFlexGridSizer_SetFlexibleDirection, 1393). --define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1394). --define(wxFlexGridSizer_destroy, 1395). --define(wxGridBagSizer_new, 1396). --define(wxGridBagSizer_Add_3_2, 1397). --define(wxGridBagSizer_Add_3_1, 1398). --define(wxGridBagSizer_Add_4, 1399). --define(wxGridBagSizer_Add_1_0, 1400). --define(wxGridBagSizer_Add_2_1, 1401). --define(wxGridBagSizer_Add_2_0, 1402). --define(wxGridBagSizer_Add_3_0, 1403). --define(wxGridBagSizer_Add_1_1, 1404). --define(wxGridBagSizer_CalcMin, 1405). --define(wxGridBagSizer_CheckForIntersection_2, 1406). --define(wxGridBagSizer_CheckForIntersection_3, 1407). --define(wxGridBagSizer_FindItem_1_1, 1408). --define(wxGridBagSizer_FindItem_1_0, 1409). --define(wxGridBagSizer_FindItemAtPoint, 1410). --define(wxGridBagSizer_FindItemAtPosition, 1411). --define(wxGridBagSizer_FindItemWithData, 1412). --define(wxGridBagSizer_GetCellSize, 1413). --define(wxGridBagSizer_GetEmptyCellSize, 1414). --define(wxGridBagSizer_GetItemPosition_1_2, 1415). --define(wxGridBagSizer_GetItemPosition_1_1, 1416). --define(wxGridBagSizer_GetItemPosition_1_0, 1417). --define(wxGridBagSizer_GetItemSpan_1_2, 1418). --define(wxGridBagSizer_GetItemSpan_1_1, 1419). --define(wxGridBagSizer_GetItemSpan_1_0, 1420). --define(wxGridBagSizer_SetEmptyCellSize, 1421). --define(wxGridBagSizer_SetItemPosition_2_2, 1422). --define(wxGridBagSizer_SetItemPosition_2_1, 1423). --define(wxGridBagSizer_SetItemPosition_2_0, 1424). --define(wxGridBagSizer_SetItemSpan_2_2, 1425). --define(wxGridBagSizer_SetItemSpan_2_1, 1426). --define(wxGridBagSizer_SetItemSpan_2_0, 1427). --define(wxGridBagSizer_destroy, 1428). --define(wxStdDialogButtonSizer_new, 1429). --define(wxStdDialogButtonSizer_AddButton, 1430). --define(wxStdDialogButtonSizer_Realize, 1431). --define(wxStdDialogButtonSizer_SetAffirmativeButton, 1432). --define(wxStdDialogButtonSizer_SetCancelButton, 1433). --define(wxStdDialogButtonSizer_SetNegativeButton, 1434). --define(wxStdDialogButtonSizer_destroy, 1435). --define(wxFont_new_0, 1436). --define(wxFont_new_1, 1437). --define(wxFont_new_5, 1438). --define(wxFont_destruct, 1440). --define(wxFont_IsFixedWidth, 1441). --define(wxFont_GetDefaultEncoding, 1442). --define(wxFont_GetFaceName, 1443). --define(wxFont_GetFamily, 1444). --define(wxFont_GetNativeFontInfoDesc, 1445). --define(wxFont_GetNativeFontInfoUserDesc, 1446). --define(wxFont_GetPointSize, 1447). --define(wxFont_GetStyle, 1448). --define(wxFont_GetUnderlined, 1449). --define(wxFont_GetWeight, 1450). --define(wxFont_Ok, 1451). --define(wxFont_SetDefaultEncoding, 1452). --define(wxFont_SetFaceName, 1453). --define(wxFont_SetFamily, 1454). --define(wxFont_SetPointSize, 1455). --define(wxFont_SetStyle, 1456). --define(wxFont_SetUnderlined, 1457). --define(wxFont_SetWeight, 1458). --define(wxToolTip_Enable, 1459). --define(wxToolTip_SetDelay, 1460). --define(wxToolTip_new, 1461). --define(wxToolTip_SetTip, 1462). --define(wxToolTip_GetTip, 1463). --define(wxToolTip_GetWindow, 1464). --define(wxToolTip_destroy, 1465). --define(wxButton_new_3, 1467). --define(wxButton_new_0, 1468). --define(wxButton_destruct, 1469). --define(wxButton_Create, 1470). --define(wxButton_GetDefaultSize, 1471). --define(wxButton_SetDefault, 1472). --define(wxButton_SetLabel, 1473). --define(wxBitmapButton_new_4, 1475). --define(wxBitmapButton_new_0, 1476). --define(wxBitmapButton_Create, 1477). --define(wxBitmapButton_GetBitmapDisabled, 1478). --define(wxBitmapButton_GetBitmapFocus, 1480). --define(wxBitmapButton_GetBitmapLabel, 1482). --define(wxBitmapButton_GetBitmapSelected, 1484). --define(wxBitmapButton_SetBitmapDisabled, 1486). --define(wxBitmapButton_SetBitmapFocus, 1487). --define(wxBitmapButton_SetBitmapLabel, 1488). --define(wxBitmapButton_SetBitmapSelected, 1489). --define(wxBitmapButton_destroy, 1490). --define(wxToggleButton_new_0, 1491). --define(wxToggleButton_new_4, 1492). --define(wxToggleButton_Create, 1493). --define(wxToggleButton_GetValue, 1494). --define(wxToggleButton_SetValue, 1495). --define(wxToggleButton_destroy, 1496). --define(wxCalendarCtrl_new_0, 1497). --define(wxCalendarCtrl_new_3, 1498). --define(wxCalendarCtrl_Create, 1499). --define(wxCalendarCtrl_destruct, 1500). --define(wxCalendarCtrl_SetDate, 1501). --define(wxCalendarCtrl_GetDate, 1502). --define(wxCalendarCtrl_EnableYearChange, 1503). --define(wxCalendarCtrl_EnableMonthChange, 1504). --define(wxCalendarCtrl_EnableHolidayDisplay, 1505). --define(wxCalendarCtrl_SetHeaderColours, 1506). --define(wxCalendarCtrl_GetHeaderColourFg, 1507). --define(wxCalendarCtrl_GetHeaderColourBg, 1508). --define(wxCalendarCtrl_SetHighlightColours, 1509). --define(wxCalendarCtrl_GetHighlightColourFg, 1510). --define(wxCalendarCtrl_GetHighlightColourBg, 1511). --define(wxCalendarCtrl_SetHolidayColours, 1512). --define(wxCalendarCtrl_GetHolidayColourFg, 1513). --define(wxCalendarCtrl_GetHolidayColourBg, 1514). --define(wxCalendarCtrl_GetAttr, 1515). --define(wxCalendarCtrl_SetAttr, 1516). --define(wxCalendarCtrl_SetHoliday, 1517). --define(wxCalendarCtrl_ResetAttr, 1518). --define(wxCalendarCtrl_HitTest, 1519). --define(wxCalendarDateAttr_new_0, 1520). --define(wxCalendarDateAttr_new_2_1, 1521). --define(wxCalendarDateAttr_new_2_0, 1522). --define(wxCalendarDateAttr_SetTextColour, 1523). --define(wxCalendarDateAttr_SetBackgroundColour, 1524). --define(wxCalendarDateAttr_SetBorderColour, 1525). --define(wxCalendarDateAttr_SetFont, 1526). --define(wxCalendarDateAttr_SetBorder, 1527). --define(wxCalendarDateAttr_SetHoliday, 1528). --define(wxCalendarDateAttr_HasTextColour, 1529). --define(wxCalendarDateAttr_HasBackgroundColour, 1530). --define(wxCalendarDateAttr_HasBorderColour, 1531). --define(wxCalendarDateAttr_HasFont, 1532). --define(wxCalendarDateAttr_HasBorder, 1533). --define(wxCalendarDateAttr_IsHoliday, 1534). --define(wxCalendarDateAttr_GetTextColour, 1535). --define(wxCalendarDateAttr_GetBackgroundColour, 1536). --define(wxCalendarDateAttr_GetBorderColour, 1537). --define(wxCalendarDateAttr_GetFont, 1538). --define(wxCalendarDateAttr_GetBorder, 1539). --define(wxCalendarDateAttr_destroy, 1540). --define(wxCheckBox_new_4, 1542). --define(wxCheckBox_new_0, 1543). --define(wxCheckBox_Create, 1544). --define(wxCheckBox_GetValue, 1545). --define(wxCheckBox_Get3StateValue, 1546). --define(wxCheckBox_Is3rdStateAllowedForUser, 1547). --define(wxCheckBox_Is3State, 1548). --define(wxCheckBox_IsChecked, 1549). --define(wxCheckBox_SetValue, 1550). --define(wxCheckBox_Set3StateValue, 1551). --define(wxCheckBox_destroy, 1552). --define(wxCheckListBox_new_0, 1553). --define(wxCheckListBox_new_3, 1555). --define(wxCheckListBox_Check, 1556). --define(wxCheckListBox_IsChecked, 1557). --define(wxCheckListBox_destroy, 1558). --define(wxChoice_new_3, 1561). --define(wxChoice_new_0, 1562). --define(wxChoice_destruct, 1564). --define(wxChoice_Create, 1566). --define(wxChoice_Delete, 1567). --define(wxChoice_GetColumns, 1568). --define(wxChoice_SetColumns, 1569). --define(wxComboBox_new_0, 1570). --define(wxComboBox_new_3, 1572). --define(wxComboBox_destruct, 1573). --define(wxComboBox_Create, 1575). --define(wxComboBox_CanCopy, 1576). --define(wxComboBox_CanCut, 1577). --define(wxComboBox_CanPaste, 1578). --define(wxComboBox_CanRedo, 1579). --define(wxComboBox_CanUndo, 1580). --define(wxComboBox_Copy, 1581). --define(wxComboBox_Cut, 1582). --define(wxComboBox_GetInsertionPoint, 1583). --define(wxComboBox_GetLastPosition, 1584). --define(wxComboBox_GetValue, 1585). --define(wxComboBox_Paste, 1586). --define(wxComboBox_Redo, 1587). --define(wxComboBox_Replace, 1588). --define(wxComboBox_Remove, 1589). --define(wxComboBox_SetInsertionPoint, 1590). --define(wxComboBox_SetInsertionPointEnd, 1591). --define(wxComboBox_SetSelection_1, 1592). --define(wxComboBox_SetSelection_2, 1593). --define(wxComboBox_SetValue, 1594). --define(wxComboBox_Undo, 1595). --define(wxGauge_new_0, 1596). --define(wxGauge_new_4, 1597). --define(wxGauge_Create, 1598). --define(wxGauge_GetBezelFace, 1599). --define(wxGauge_GetRange, 1600). --define(wxGauge_GetShadowWidth, 1601). --define(wxGauge_GetValue, 1602). --define(wxGauge_IsVertical, 1603). --define(wxGauge_SetBezelFace, 1604). --define(wxGauge_SetRange, 1605). --define(wxGauge_SetShadowWidth, 1606). --define(wxGauge_SetValue, 1607). --define(wxGauge_Pulse, 1608). --define(wxGauge_destroy, 1609). --define(wxGenericDirCtrl_new_0, 1610). --define(wxGenericDirCtrl_new_2, 1611). --define(wxGenericDirCtrl_destruct, 1612). --define(wxGenericDirCtrl_Create, 1613). --define(wxGenericDirCtrl_Init, 1614). --define(wxGenericDirCtrl_CollapseTree, 1615). --define(wxGenericDirCtrl_ExpandPath, 1616). --define(wxGenericDirCtrl_GetDefaultPath, 1617). --define(wxGenericDirCtrl_GetPath, 1618). --define(wxGenericDirCtrl_GetFilePath, 1619). --define(wxGenericDirCtrl_GetFilter, 1620). --define(wxGenericDirCtrl_GetFilterIndex, 1621). --define(wxGenericDirCtrl_GetRootId, 1622). --define(wxGenericDirCtrl_GetTreeCtrl, 1623). --define(wxGenericDirCtrl_ReCreateTree, 1624). --define(wxGenericDirCtrl_SetDefaultPath, 1625). --define(wxGenericDirCtrl_SetFilter, 1626). --define(wxGenericDirCtrl_SetFilterIndex, 1627). --define(wxGenericDirCtrl_SetPath, 1628). --define(wxStaticBox_new_4, 1630). --define(wxStaticBox_new_0, 1631). --define(wxStaticBox_Create, 1632). --define(wxStaticBox_destroy, 1633). --define(wxStaticLine_new_2, 1635). --define(wxStaticLine_new_0, 1636). --define(wxStaticLine_Create, 1637). --define(wxStaticLine_IsVertical, 1638). --define(wxStaticLine_GetDefaultSize, 1639). --define(wxStaticLine_destroy, 1640). --define(wxListBox_new_3, 1643). --define(wxListBox_new_0, 1644). --define(wxListBox_destruct, 1646). --define(wxListBox_Create, 1648). --define(wxListBox_Deselect, 1649). --define(wxListBox_GetSelections, 1650). --define(wxListBox_InsertItems, 1651). --define(wxListBox_IsSelected, 1652). --define(wxListBox_Set, 1653). --define(wxListBox_HitTest, 1654). --define(wxListBox_SetFirstItem_1_0, 1655). --define(wxListBox_SetFirstItem_1_1, 1656). --define(wxListCtrl_new_0, 1657). --define(wxListCtrl_new_2, 1658). --define(wxListCtrl_Arrange, 1659). --define(wxListCtrl_AssignImageList, 1660). --define(wxListCtrl_ClearAll, 1661). --define(wxListCtrl_Create, 1662). --define(wxListCtrl_DeleteAllItems, 1663). --define(wxListCtrl_DeleteColumn, 1664). --define(wxListCtrl_DeleteItem, 1665). --define(wxListCtrl_EditLabel, 1666). --define(wxListCtrl_EnsureVisible, 1667). --define(wxListCtrl_FindItem_3_0, 1668). --define(wxListCtrl_FindItem_3_1, 1669). --define(wxListCtrl_GetColumn, 1670). --define(wxListCtrl_GetColumnCount, 1671). --define(wxListCtrl_GetColumnWidth, 1672). --define(wxListCtrl_GetCountPerPage, 1673). --define(wxListCtrl_GetEditControl, 1674). --define(wxListCtrl_GetImageList, 1675). --define(wxListCtrl_GetItem, 1676). --define(wxListCtrl_GetItemBackgroundColour, 1677). --define(wxListCtrl_GetItemCount, 1678). --define(wxListCtrl_GetItemData, 1679). --define(wxListCtrl_GetItemFont, 1680). --define(wxListCtrl_GetItemPosition, 1681). --define(wxListCtrl_GetItemRect, 1682). --define(wxListCtrl_GetItemSpacing, 1683). --define(wxListCtrl_GetItemState, 1684). --define(wxListCtrl_GetItemText, 1685). --define(wxListCtrl_GetItemTextColour, 1686). --define(wxListCtrl_GetNextItem, 1687). --define(wxListCtrl_GetSelectedItemCount, 1688). --define(wxListCtrl_GetTextColour, 1689). --define(wxListCtrl_GetTopItem, 1690). --define(wxListCtrl_GetViewRect, 1691). --define(wxListCtrl_HitTest, 1692). --define(wxListCtrl_InsertColumn_2, 1693). --define(wxListCtrl_InsertColumn_3, 1694). --define(wxListCtrl_InsertItem_1, 1695). --define(wxListCtrl_InsertItem_2_1, 1696). --define(wxListCtrl_InsertItem_2_0, 1697). --define(wxListCtrl_InsertItem_3, 1698). --define(wxListCtrl_RefreshItem, 1699). --define(wxListCtrl_RefreshItems, 1700). --define(wxListCtrl_ScrollList, 1701). --define(wxListCtrl_SetBackgroundColour, 1702). --define(wxListCtrl_SetColumn, 1703). --define(wxListCtrl_SetColumnWidth, 1704). --define(wxListCtrl_SetImageList, 1705). --define(wxListCtrl_SetItem_1, 1706). --define(wxListCtrl_SetItem_4, 1707). --define(wxListCtrl_SetItemBackgroundColour, 1708). --define(wxListCtrl_SetItemCount, 1709). --define(wxListCtrl_SetItemData, 1710). --define(wxListCtrl_SetItemFont, 1711). --define(wxListCtrl_SetItemImage, 1712). --define(wxListCtrl_SetItemColumnImage, 1713). --define(wxListCtrl_SetItemPosition, 1714). --define(wxListCtrl_SetItemState, 1715). --define(wxListCtrl_SetItemText, 1716). --define(wxListCtrl_SetItemTextColour, 1717). --define(wxListCtrl_SetSingleStyle, 1718). --define(wxListCtrl_SetTextColour, 1719). --define(wxListCtrl_SetWindowStyleFlag, 1720). --define(wxListCtrl_SortItems, 1721). --define(wxListCtrl_destroy, 1722). --define(wxListView_ClearColumnImage, 1723). --define(wxListView_Focus, 1724). --define(wxListView_GetFirstSelected, 1725). --define(wxListView_GetFocusedItem, 1726). --define(wxListView_GetNextSelected, 1727). --define(wxListView_IsSelected, 1728). --define(wxListView_Select, 1729). --define(wxListView_SetColumnImage, 1730). --define(wxListItem_new_0, 1731). --define(wxListItem_new_1, 1732). --define(wxListItem_destruct, 1733). --define(wxListItem_Clear, 1734). --define(wxListItem_GetAlign, 1735). --define(wxListItem_GetBackgroundColour, 1736). --define(wxListItem_GetColumn, 1737). --define(wxListItem_GetFont, 1738). --define(wxListItem_GetId, 1739). --define(wxListItem_GetImage, 1740). --define(wxListItem_GetMask, 1741). --define(wxListItem_GetState, 1742). --define(wxListItem_GetText, 1743). --define(wxListItem_GetTextColour, 1744). --define(wxListItem_GetWidth, 1745). --define(wxListItem_SetAlign, 1746). --define(wxListItem_SetBackgroundColour, 1747). --define(wxListItem_SetColumn, 1748). --define(wxListItem_SetFont, 1749). --define(wxListItem_SetId, 1750). --define(wxListItem_SetImage, 1751). --define(wxListItem_SetMask, 1752). --define(wxListItem_SetState, 1753). --define(wxListItem_SetStateMask, 1754). --define(wxListItem_SetText, 1755). --define(wxListItem_SetTextColour, 1756). --define(wxListItem_SetWidth, 1757). --define(wxListItemAttr_new_0, 1758). --define(wxListItemAttr_new_3, 1759). --define(wxListItemAttr_GetBackgroundColour, 1760). --define(wxListItemAttr_GetFont, 1761). --define(wxListItemAttr_GetTextColour, 1762). --define(wxListItemAttr_HasBackgroundColour, 1763). --define(wxListItemAttr_HasFont, 1764). --define(wxListItemAttr_HasTextColour, 1765). --define(wxListItemAttr_SetBackgroundColour, 1766). --define(wxListItemAttr_SetFont, 1767). --define(wxListItemAttr_SetTextColour, 1768). --define(wxListItemAttr_destroy, 1769). --define(wxImageList_new_0, 1770). --define(wxImageList_new_3, 1771). --define(wxImageList_Add_1, 1772). --define(wxImageList_Add_2_0, 1773). --define(wxImageList_Add_2_1, 1774). --define(wxImageList_Create, 1775). --define(wxImageList_Draw, 1777). --define(wxImageList_GetBitmap, 1778). --define(wxImageList_GetIcon, 1779). --define(wxImageList_GetImageCount, 1780). --define(wxImageList_GetSize, 1781). --define(wxImageList_Remove, 1782). --define(wxImageList_RemoveAll, 1783). --define(wxImageList_Replace_2, 1784). --define(wxImageList_Replace_3, 1785). --define(wxImageList_destroy, 1786). --define(wxTextAttr_new_0, 1787). --define(wxTextAttr_new_2, 1788). --define(wxTextAttr_GetAlignment, 1789). --define(wxTextAttr_GetBackgroundColour, 1790). --define(wxTextAttr_GetFont, 1791). --define(wxTextAttr_GetLeftIndent, 1792). --define(wxTextAttr_GetLeftSubIndent, 1793). --define(wxTextAttr_GetRightIndent, 1794). --define(wxTextAttr_GetTabs, 1795). --define(wxTextAttr_GetTextColour, 1796). --define(wxTextAttr_HasBackgroundColour, 1797). --define(wxTextAttr_HasFont, 1798). --define(wxTextAttr_HasTextColour, 1799). --define(wxTextAttr_GetFlags, 1800). --define(wxTextAttr_IsDefault, 1801). --define(wxTextAttr_SetAlignment, 1802). --define(wxTextAttr_SetBackgroundColour, 1803). --define(wxTextAttr_SetFlags, 1804). --define(wxTextAttr_SetFont, 1805). --define(wxTextAttr_SetLeftIndent, 1806). --define(wxTextAttr_SetRightIndent, 1807). --define(wxTextAttr_SetTabs, 1808). --define(wxTextAttr_SetTextColour, 1809). --define(wxTextAttr_destroy, 1810). --define(wxTextCtrl_new_3, 1812). --define(wxTextCtrl_new_0, 1813). --define(wxTextCtrl_destruct, 1815). --define(wxTextCtrl_AppendText, 1816). --define(wxTextCtrl_CanCopy, 1817). --define(wxTextCtrl_CanCut, 1818). --define(wxTextCtrl_CanPaste, 1819). --define(wxTextCtrl_CanRedo, 1820). --define(wxTextCtrl_CanUndo, 1821). --define(wxTextCtrl_Clear, 1822). --define(wxTextCtrl_Copy, 1823). --define(wxTextCtrl_Create, 1824). --define(wxTextCtrl_Cut, 1825). --define(wxTextCtrl_DiscardEdits, 1826). --define(wxTextCtrl_ChangeValue, 1827). --define(wxTextCtrl_EmulateKeyPress, 1828). --define(wxTextCtrl_GetDefaultStyle, 1829). --define(wxTextCtrl_GetInsertionPoint, 1830). --define(wxTextCtrl_GetLastPosition, 1831). --define(wxTextCtrl_GetLineLength, 1832). --define(wxTextCtrl_GetLineText, 1833). --define(wxTextCtrl_GetNumberOfLines, 1834). --define(wxTextCtrl_GetRange, 1835). --define(wxTextCtrl_GetSelection, 1836). --define(wxTextCtrl_GetStringSelection, 1837). --define(wxTextCtrl_GetStyle, 1838). --define(wxTextCtrl_GetValue, 1839). --define(wxTextCtrl_IsEditable, 1840). --define(wxTextCtrl_IsModified, 1841). --define(wxTextCtrl_IsMultiLine, 1842). --define(wxTextCtrl_IsSingleLine, 1843). --define(wxTextCtrl_LoadFile, 1844). --define(wxTextCtrl_MarkDirty, 1845). --define(wxTextCtrl_Paste, 1846). --define(wxTextCtrl_PositionToXY, 1847). --define(wxTextCtrl_Redo, 1848). --define(wxTextCtrl_Remove, 1849). --define(wxTextCtrl_Replace, 1850). --define(wxTextCtrl_SaveFile, 1851). --define(wxTextCtrl_SetDefaultStyle, 1852). --define(wxTextCtrl_SetEditable, 1853). --define(wxTextCtrl_SetInsertionPoint, 1854). --define(wxTextCtrl_SetInsertionPointEnd, 1855). --define(wxTextCtrl_SetMaxLength, 1857). --define(wxTextCtrl_SetSelection, 1858). --define(wxTextCtrl_SetStyle, 1859). --define(wxTextCtrl_SetValue, 1860). --define(wxTextCtrl_ShowPosition, 1861). --define(wxTextCtrl_Undo, 1862). --define(wxTextCtrl_WriteText, 1863). --define(wxTextCtrl_XYToPosition, 1864). --define(wxNotebook_new_0, 1867). --define(wxNotebook_new_3, 1868). --define(wxNotebook_destruct, 1869). --define(wxNotebook_AddPage, 1870). --define(wxNotebook_AdvanceSelection, 1871). --define(wxNotebook_AssignImageList, 1872). --define(wxNotebook_Create, 1873). --define(wxNotebook_DeleteAllPages, 1874). --define(wxNotebook_DeletePage, 1875). --define(wxNotebook_RemovePage, 1876). --define(wxNotebook_GetCurrentPage, 1877). --define(wxNotebook_GetImageList, 1878). --define(wxNotebook_GetPage, 1880). --define(wxNotebook_GetPageCount, 1881). --define(wxNotebook_GetPageImage, 1882). --define(wxNotebook_GetPageText, 1883). --define(wxNotebook_GetRowCount, 1884). --define(wxNotebook_GetSelection, 1885). --define(wxNotebook_GetThemeBackgroundColour, 1886). --define(wxNotebook_HitTest, 1888). --define(wxNotebook_InsertPage, 1890). --define(wxNotebook_SetImageList, 1891). --define(wxNotebook_SetPadding, 1892). --define(wxNotebook_SetPageSize, 1893). --define(wxNotebook_SetPageImage, 1894). --define(wxNotebook_SetPageText, 1895). --define(wxNotebook_SetSelection, 1896). --define(wxNotebook_ChangeSelection, 1897). --define(wxChoicebook_new_0, 1898). --define(wxChoicebook_new_3, 1899). --define(wxChoicebook_AddPage, 1900). --define(wxChoicebook_AdvanceSelection, 1901). --define(wxChoicebook_AssignImageList, 1902). --define(wxChoicebook_Create, 1903). --define(wxChoicebook_DeleteAllPages, 1904). --define(wxChoicebook_DeletePage, 1905). --define(wxChoicebook_RemovePage, 1906). --define(wxChoicebook_GetCurrentPage, 1907). --define(wxChoicebook_GetImageList, 1908). --define(wxChoicebook_GetPage, 1910). --define(wxChoicebook_GetPageCount, 1911). --define(wxChoicebook_GetPageImage, 1912). --define(wxChoicebook_GetPageText, 1913). --define(wxChoicebook_GetSelection, 1914). --define(wxChoicebook_HitTest, 1915). --define(wxChoicebook_InsertPage, 1916). --define(wxChoicebook_SetImageList, 1917). --define(wxChoicebook_SetPageSize, 1918). --define(wxChoicebook_SetPageImage, 1919). --define(wxChoicebook_SetPageText, 1920). --define(wxChoicebook_SetSelection, 1921). --define(wxChoicebook_ChangeSelection, 1922). --define(wxChoicebook_destroy, 1923). --define(wxToolbook_new_0, 1924). --define(wxToolbook_new_3, 1925). --define(wxToolbook_AddPage, 1926). --define(wxToolbook_AdvanceSelection, 1927). --define(wxToolbook_AssignImageList, 1928). --define(wxToolbook_Create, 1929). --define(wxToolbook_DeleteAllPages, 1930). --define(wxToolbook_DeletePage, 1931). --define(wxToolbook_RemovePage, 1932). --define(wxToolbook_GetCurrentPage, 1933). --define(wxToolbook_GetImageList, 1934). --define(wxToolbook_GetPage, 1936). --define(wxToolbook_GetPageCount, 1937). --define(wxToolbook_GetPageImage, 1938). --define(wxToolbook_GetPageText, 1939). --define(wxToolbook_GetSelection, 1940). --define(wxToolbook_HitTest, 1942). --define(wxToolbook_InsertPage, 1943). --define(wxToolbook_SetImageList, 1944). --define(wxToolbook_SetPageSize, 1945). --define(wxToolbook_SetPageImage, 1946). --define(wxToolbook_SetPageText, 1947). --define(wxToolbook_SetSelection, 1948). --define(wxToolbook_ChangeSelection, 1949). --define(wxToolbook_destroy, 1950). --define(wxListbook_new_0, 1951). --define(wxListbook_new_3, 1952). --define(wxListbook_AddPage, 1953). --define(wxListbook_AdvanceSelection, 1954). --define(wxListbook_AssignImageList, 1955). --define(wxListbook_Create, 1956). --define(wxListbook_DeleteAllPages, 1957). --define(wxListbook_DeletePage, 1958). --define(wxListbook_RemovePage, 1959). --define(wxListbook_GetCurrentPage, 1960). --define(wxListbook_GetImageList, 1961). --define(wxListbook_GetPage, 1963). --define(wxListbook_GetPageCount, 1964). --define(wxListbook_GetPageImage, 1965). --define(wxListbook_GetPageText, 1966). --define(wxListbook_GetSelection, 1967). --define(wxListbook_HitTest, 1969). --define(wxListbook_InsertPage, 1970). --define(wxListbook_SetImageList, 1971). --define(wxListbook_SetPageSize, 1972). --define(wxListbook_SetPageImage, 1973). --define(wxListbook_SetPageText, 1974). --define(wxListbook_SetSelection, 1975). --define(wxListbook_ChangeSelection, 1976). --define(wxListbook_destroy, 1977). --define(wxTreebook_new_0, 1978). --define(wxTreebook_new_3, 1979). --define(wxTreebook_AddPage, 1980). --define(wxTreebook_AdvanceSelection, 1981). --define(wxTreebook_AssignImageList, 1982). --define(wxTreebook_Create, 1983). --define(wxTreebook_DeleteAllPages, 1984). --define(wxTreebook_DeletePage, 1985). --define(wxTreebook_RemovePage, 1986). --define(wxTreebook_GetCurrentPage, 1987). --define(wxTreebook_GetImageList, 1988). --define(wxTreebook_GetPage, 1990). --define(wxTreebook_GetPageCount, 1991). --define(wxTreebook_GetPageImage, 1992). --define(wxTreebook_GetPageText, 1993). --define(wxTreebook_GetSelection, 1994). --define(wxTreebook_ExpandNode, 1995). --define(wxTreebook_IsNodeExpanded, 1996). --define(wxTreebook_HitTest, 1998). --define(wxTreebook_InsertPage, 1999). --define(wxTreebook_InsertSubPage, 2000). --define(wxTreebook_SetImageList, 2001). --define(wxTreebook_SetPageSize, 2002). --define(wxTreebook_SetPageImage, 2003). --define(wxTreebook_SetPageText, 2004). --define(wxTreebook_SetSelection, 2005). --define(wxTreebook_ChangeSelection, 2006). --define(wxTreebook_destroy, 2007). --define(wxTreeCtrl_new_2, 2010). --define(wxTreeCtrl_new_0, 2011). --define(wxTreeCtrl_destruct, 2013). --define(wxTreeCtrl_AddRoot, 2014). --define(wxTreeCtrl_AppendItem, 2015). --define(wxTreeCtrl_AssignImageList, 2016). --define(wxTreeCtrl_AssignStateImageList, 2017). --define(wxTreeCtrl_Collapse, 2018). --define(wxTreeCtrl_CollapseAndReset, 2019). --define(wxTreeCtrl_Create, 2020). --define(wxTreeCtrl_Delete, 2021). --define(wxTreeCtrl_DeleteAllItems, 2022). --define(wxTreeCtrl_DeleteChildren, 2023). --define(wxTreeCtrl_EditLabel, 2024). --define(wxTreeCtrl_EnsureVisible, 2025). --define(wxTreeCtrl_Expand, 2026). --define(wxTreeCtrl_GetBoundingRect, 2027). --define(wxTreeCtrl_GetChildrenCount, 2029). --define(wxTreeCtrl_GetCount, 2030). --define(wxTreeCtrl_GetEditControl, 2031). --define(wxTreeCtrl_GetFirstChild, 2032). --define(wxTreeCtrl_GetNextChild, 2033). --define(wxTreeCtrl_GetFirstVisibleItem, 2034). --define(wxTreeCtrl_GetImageList, 2035). --define(wxTreeCtrl_GetIndent, 2036). --define(wxTreeCtrl_GetItemBackgroundColour, 2037). --define(wxTreeCtrl_GetItemData, 2038). --define(wxTreeCtrl_GetItemFont, 2039). --define(wxTreeCtrl_GetItemImage_1, 2040). --define(wxTreeCtrl_GetItemImage_2, 2041). --define(wxTreeCtrl_GetItemText, 2042). --define(wxTreeCtrl_GetItemTextColour, 2043). --define(wxTreeCtrl_GetLastChild, 2044). --define(wxTreeCtrl_GetNextSibling, 2045). --define(wxTreeCtrl_GetNextVisible, 2046). --define(wxTreeCtrl_GetItemParent, 2047). --define(wxTreeCtrl_GetPrevSibling, 2048). --define(wxTreeCtrl_GetPrevVisible, 2049). --define(wxTreeCtrl_GetRootItem, 2050). --define(wxTreeCtrl_GetSelection, 2051). --define(wxTreeCtrl_GetSelections, 2052). --define(wxTreeCtrl_GetStateImageList, 2053). --define(wxTreeCtrl_HitTest, 2054). --define(wxTreeCtrl_InsertItem, 2056). --define(wxTreeCtrl_IsBold, 2057). --define(wxTreeCtrl_IsExpanded, 2058). --define(wxTreeCtrl_IsSelected, 2059). --define(wxTreeCtrl_IsVisible, 2060). --define(wxTreeCtrl_ItemHasChildren, 2061). --define(wxTreeCtrl_IsTreeItemIdOk, 2062). --define(wxTreeCtrl_PrependItem, 2063). --define(wxTreeCtrl_ScrollTo, 2064). --define(wxTreeCtrl_SelectItem_1, 2065). --define(wxTreeCtrl_SelectItem_2, 2066). --define(wxTreeCtrl_SetIndent, 2067). --define(wxTreeCtrl_SetImageList, 2068). --define(wxTreeCtrl_SetItemBackgroundColour, 2069). --define(wxTreeCtrl_SetItemBold, 2070). --define(wxTreeCtrl_SetItemData, 2071). --define(wxTreeCtrl_SetItemDropHighlight, 2072). --define(wxTreeCtrl_SetItemFont, 2073). --define(wxTreeCtrl_SetItemHasChildren, 2074). --define(wxTreeCtrl_SetItemImage_2, 2075). --define(wxTreeCtrl_SetItemImage_3, 2076). --define(wxTreeCtrl_SetItemText, 2077). --define(wxTreeCtrl_SetItemTextColour, 2078). --define(wxTreeCtrl_SetStateImageList, 2079). --define(wxTreeCtrl_SetWindowStyle, 2080). --define(wxTreeCtrl_SortChildren, 2081). --define(wxTreeCtrl_Toggle, 2082). --define(wxTreeCtrl_ToggleItemSelection, 2083). --define(wxTreeCtrl_Unselect, 2084). --define(wxTreeCtrl_UnselectAll, 2085). --define(wxTreeCtrl_UnselectItem, 2086). --define(wxScrollBar_new_0, 2087). --define(wxScrollBar_new_3, 2088). --define(wxScrollBar_destruct, 2089). --define(wxScrollBar_Create, 2090). --define(wxScrollBar_GetRange, 2091). --define(wxScrollBar_GetPageSize, 2092). --define(wxScrollBar_GetThumbPosition, 2093). --define(wxScrollBar_GetThumbSize, 2094). --define(wxScrollBar_SetThumbPosition, 2095). --define(wxScrollBar_SetScrollbar, 2096). --define(wxSpinButton_new_2, 2098). --define(wxSpinButton_new_0, 2099). --define(wxSpinButton_Create, 2100). --define(wxSpinButton_GetMax, 2101). --define(wxSpinButton_GetMin, 2102). --define(wxSpinButton_GetValue, 2103). --define(wxSpinButton_SetRange, 2104). --define(wxSpinButton_SetValue, 2105). --define(wxSpinButton_destroy, 2106). --define(wxSpinCtrl_new_0, 2107). --define(wxSpinCtrl_new_2, 2108). --define(wxSpinCtrl_Create, 2110). --define(wxSpinCtrl_SetValue_1_1, 2113). --define(wxSpinCtrl_SetValue_1_0, 2114). --define(wxSpinCtrl_GetValue, 2116). --define(wxSpinCtrl_SetRange, 2118). --define(wxSpinCtrl_SetSelection, 2119). --define(wxSpinCtrl_GetMin, 2121). --define(wxSpinCtrl_GetMax, 2123). --define(wxSpinCtrl_destroy, 2124). --define(wxStaticText_new_0, 2125). --define(wxStaticText_new_4, 2126). --define(wxStaticText_Create, 2127). --define(wxStaticText_GetLabel, 2128). --define(wxStaticText_SetLabel, 2129). --define(wxStaticText_Wrap, 2130). --define(wxStaticText_destroy, 2131). --define(wxStaticBitmap_new_0, 2132). --define(wxStaticBitmap_new_4, 2133). --define(wxStaticBitmap_Create, 2134). --define(wxStaticBitmap_GetBitmap, 2135). --define(wxStaticBitmap_SetBitmap, 2136). --define(wxStaticBitmap_destroy, 2137). --define(wxRadioBox_new, 2138). --define(wxRadioBox_destruct, 2140). --define(wxRadioBox_Create, 2141). --define(wxRadioBox_Enable_2, 2142). --define(wxRadioBox_Enable_1, 2143). --define(wxRadioBox_GetSelection, 2144). --define(wxRadioBox_GetString, 2145). --define(wxRadioBox_SetSelection, 2146). --define(wxRadioBox_Show_2, 2147). --define(wxRadioBox_Show_1, 2148). --define(wxRadioBox_GetColumnCount, 2149). --define(wxRadioBox_GetItemHelpText, 2150). --define(wxRadioBox_GetItemToolTip, 2151). --define(wxRadioBox_GetItemFromPoint, 2153). --define(wxRadioBox_GetRowCount, 2154). --define(wxRadioBox_IsItemEnabled, 2155). --define(wxRadioBox_IsItemShown, 2156). --define(wxRadioBox_SetItemHelpText, 2157). --define(wxRadioBox_SetItemToolTip, 2158). --define(wxRadioButton_new_0, 2159). --define(wxRadioButton_new_4, 2160). --define(wxRadioButton_Create, 2161). --define(wxRadioButton_GetValue, 2162). --define(wxRadioButton_SetValue, 2163). --define(wxRadioButton_destroy, 2164). --define(wxSlider_new_6, 2166). --define(wxSlider_new_0, 2167). --define(wxSlider_Create, 2168). --define(wxSlider_GetLineSize, 2169). --define(wxSlider_GetMax, 2170). --define(wxSlider_GetMin, 2171). --define(wxSlider_GetPageSize, 2172). --define(wxSlider_GetThumbLength, 2173). --define(wxSlider_GetValue, 2174). --define(wxSlider_SetLineSize, 2175). --define(wxSlider_SetPageSize, 2176). --define(wxSlider_SetRange, 2177). --define(wxSlider_SetThumbLength, 2178). --define(wxSlider_SetValue, 2179). --define(wxSlider_destroy, 2180). --define(wxDialog_new_4, 2182). --define(wxDialog_new_0, 2183). --define(wxDialog_destruct, 2185). --define(wxDialog_Create, 2186). --define(wxDialog_CreateButtonSizer, 2187). --define(wxDialog_CreateStdDialogButtonSizer, 2188). --define(wxDialog_EndModal, 2189). --define(wxDialog_GetAffirmativeId, 2190). --define(wxDialog_GetReturnCode, 2191). --define(wxDialog_IsModal, 2192). --define(wxDialog_SetAffirmativeId, 2193). --define(wxDialog_SetReturnCode, 2194). --define(wxDialog_Show, 2195). --define(wxDialog_ShowModal, 2196). --define(wxColourDialog_new_0, 2197). --define(wxColourDialog_new_2, 2198). --define(wxColourDialog_destruct, 2199). --define(wxColourDialog_Create, 2200). --define(wxColourDialog_GetColourData, 2201). --define(wxColourData_new_0, 2202). --define(wxColourData_new_1, 2203). --define(wxColourData_destruct, 2204). --define(wxColourData_GetChooseFull, 2205). --define(wxColourData_GetColour, 2206). --define(wxColourData_GetCustomColour, 2208). --define(wxColourData_SetChooseFull, 2209). --define(wxColourData_SetColour, 2210). --define(wxColourData_SetCustomColour, 2211). --define(wxPalette_new_0, 2212). --define(wxPalette_new_4, 2213). --define(wxPalette_destruct, 2215). --define(wxPalette_Create, 2216). --define(wxPalette_GetColoursCount, 2217). --define(wxPalette_GetPixel, 2218). --define(wxPalette_GetRGB, 2219). --define(wxPalette_IsOk, 2220). --define(wxDirDialog_new, 2224). --define(wxDirDialog_destruct, 2225). --define(wxDirDialog_GetPath, 2226). --define(wxDirDialog_GetMessage, 2227). --define(wxDirDialog_SetMessage, 2228). --define(wxDirDialog_SetPath, 2229). --define(wxFileDialog_new, 2233). --define(wxFileDialog_destruct, 2234). --define(wxFileDialog_GetDirectory, 2235). --define(wxFileDialog_GetFilename, 2236). --define(wxFileDialog_GetFilenames, 2237). --define(wxFileDialog_GetFilterIndex, 2238). --define(wxFileDialog_GetMessage, 2239). --define(wxFileDialog_GetPath, 2240). --define(wxFileDialog_GetPaths, 2241). --define(wxFileDialog_GetWildcard, 2242). --define(wxFileDialog_SetDirectory, 2243). --define(wxFileDialog_SetFilename, 2244). --define(wxFileDialog_SetFilterIndex, 2245). --define(wxFileDialog_SetMessage, 2246). --define(wxFileDialog_SetPath, 2247). --define(wxFileDialog_SetWildcard, 2248). --define(wxPickerBase_SetInternalMargin, 2249). --define(wxPickerBase_GetInternalMargin, 2250). --define(wxPickerBase_SetTextCtrlProportion, 2251). --define(wxPickerBase_SetPickerCtrlProportion, 2252). --define(wxPickerBase_GetTextCtrlProportion, 2253). --define(wxPickerBase_GetPickerCtrlProportion, 2254). --define(wxPickerBase_HasTextCtrl, 2255). --define(wxPickerBase_GetTextCtrl, 2256). --define(wxPickerBase_IsTextCtrlGrowable, 2257). --define(wxPickerBase_SetPickerCtrlGrowable, 2258). --define(wxPickerBase_SetTextCtrlGrowable, 2259). --define(wxPickerBase_IsPickerCtrlGrowable, 2260). --define(wxFilePickerCtrl_new_0, 2261). --define(wxFilePickerCtrl_new_3, 2262). --define(wxFilePickerCtrl_Create, 2263). --define(wxFilePickerCtrl_GetPath, 2264). --define(wxFilePickerCtrl_SetPath, 2265). --define(wxFilePickerCtrl_destroy, 2266). --define(wxDirPickerCtrl_new_0, 2267). --define(wxDirPickerCtrl_new_3, 2268). --define(wxDirPickerCtrl_Create, 2269). --define(wxDirPickerCtrl_GetPath, 2270). --define(wxDirPickerCtrl_SetPath, 2271). --define(wxDirPickerCtrl_destroy, 2272). --define(wxColourPickerCtrl_new_0, 2273). --define(wxColourPickerCtrl_new_3, 2274). --define(wxColourPickerCtrl_Create, 2275). --define(wxColourPickerCtrl_GetColour, 2276). --define(wxColourPickerCtrl_SetColour_1_1, 2277). --define(wxColourPickerCtrl_SetColour_1_0, 2278). --define(wxColourPickerCtrl_destroy, 2279). --define(wxDatePickerCtrl_new_0, 2280). --define(wxDatePickerCtrl_new_3, 2281). --define(wxDatePickerCtrl_GetRange, 2282). --define(wxDatePickerCtrl_GetValue, 2283). --define(wxDatePickerCtrl_SetRange, 2284). --define(wxDatePickerCtrl_SetValue, 2285). --define(wxDatePickerCtrl_destroy, 2286). --define(wxFontPickerCtrl_new_0, 2287). --define(wxFontPickerCtrl_new_3, 2288). --define(wxFontPickerCtrl_Create, 2289). --define(wxFontPickerCtrl_GetSelectedFont, 2290). --define(wxFontPickerCtrl_SetSelectedFont, 2291). --define(wxFontPickerCtrl_GetMaxPointSize, 2292). --define(wxFontPickerCtrl_SetMaxPointSize, 2293). --define(wxFontPickerCtrl_destroy, 2294). --define(wxFindReplaceDialog_new_0, 2297). --define(wxFindReplaceDialog_new_4, 2298). --define(wxFindReplaceDialog_destruct, 2299). --define(wxFindReplaceDialog_Create, 2300). --define(wxFindReplaceDialog_GetData, 2301). --define(wxFindReplaceData_new_0, 2302). --define(wxFindReplaceData_new_1, 2303). --define(wxFindReplaceData_GetFindString, 2304). --define(wxFindReplaceData_GetReplaceString, 2305). --define(wxFindReplaceData_GetFlags, 2306). --define(wxFindReplaceData_SetFlags, 2307). --define(wxFindReplaceData_SetFindString, 2308). --define(wxFindReplaceData_SetReplaceString, 2309). --define(wxFindReplaceData_destroy, 2310). --define(wxMultiChoiceDialog_new_0, 2311). --define(wxMultiChoiceDialog_new_5, 2313). --define(wxMultiChoiceDialog_GetSelections, 2314). --define(wxMultiChoiceDialog_SetSelections, 2315). --define(wxMultiChoiceDialog_destroy, 2316). --define(wxSingleChoiceDialog_new_0, 2317). --define(wxSingleChoiceDialog_new_5, 2319). --define(wxSingleChoiceDialog_GetSelection, 2320). --define(wxSingleChoiceDialog_GetStringSelection, 2321). --define(wxSingleChoiceDialog_SetSelection, 2322). --define(wxSingleChoiceDialog_destroy, 2323). --define(wxTextEntryDialog_new, 2324). --define(wxTextEntryDialog_GetValue, 2325). --define(wxTextEntryDialog_SetValue, 2326). --define(wxTextEntryDialog_destroy, 2327). --define(wxPasswordEntryDialog_new, 2328). --define(wxPasswordEntryDialog_destroy, 2329). --define(wxFontData_new_0, 2330). --define(wxFontData_new_1, 2331). --define(wxFontData_destruct, 2332). --define(wxFontData_EnableEffects, 2333). --define(wxFontData_GetAllowSymbols, 2334). --define(wxFontData_GetColour, 2335). --define(wxFontData_GetChosenFont, 2336). --define(wxFontData_GetEnableEffects, 2337). --define(wxFontData_GetInitialFont, 2338). --define(wxFontData_GetShowHelp, 2339). --define(wxFontData_SetAllowSymbols, 2340). --define(wxFontData_SetChosenFont, 2341). --define(wxFontData_SetColour, 2342). --define(wxFontData_SetInitialFont, 2343). --define(wxFontData_SetRange, 2344). --define(wxFontData_SetShowHelp, 2345). --define(wxFontDialog_new_0, 2349). --define(wxFontDialog_new_2, 2351). --define(wxFontDialog_Create, 2353). --define(wxFontDialog_GetFontData, 2354). --define(wxFontDialog_destroy, 2356). --define(wxProgressDialog_new, 2357). --define(wxProgressDialog_destruct, 2358). --define(wxProgressDialog_Resume, 2359). --define(wxProgressDialog_Update_2, 2360). --define(wxProgressDialog_Update_0, 2361). --define(wxMessageDialog_new, 2362). --define(wxMessageDialog_destruct, 2363). --define(wxPageSetupDialog_new, 2364). --define(wxPageSetupDialog_destruct, 2365). --define(wxPageSetupDialog_GetPageSetupData, 2366). --define(wxPageSetupDialog_ShowModal, 2367). --define(wxPageSetupDialogData_new_0, 2368). --define(wxPageSetupDialogData_new_1_0, 2369). --define(wxPageSetupDialogData_new_1_1, 2370). --define(wxPageSetupDialogData_destruct, 2371). --define(wxPageSetupDialogData_EnableHelp, 2372). --define(wxPageSetupDialogData_EnableMargins, 2373). --define(wxPageSetupDialogData_EnableOrientation, 2374). --define(wxPageSetupDialogData_EnablePaper, 2375). --define(wxPageSetupDialogData_EnablePrinter, 2376). --define(wxPageSetupDialogData_GetDefaultMinMargins, 2377). --define(wxPageSetupDialogData_GetEnableMargins, 2378). --define(wxPageSetupDialogData_GetEnableOrientation, 2379). --define(wxPageSetupDialogData_GetEnablePaper, 2380). --define(wxPageSetupDialogData_GetEnablePrinter, 2381). --define(wxPageSetupDialogData_GetEnableHelp, 2382). --define(wxPageSetupDialogData_GetDefaultInfo, 2383). --define(wxPageSetupDialogData_GetMarginTopLeft, 2384). --define(wxPageSetupDialogData_GetMarginBottomRight, 2385). --define(wxPageSetupDialogData_GetMinMarginTopLeft, 2386). --define(wxPageSetupDialogData_GetMinMarginBottomRight, 2387). --define(wxPageSetupDialogData_GetPaperId, 2388). --define(wxPageSetupDialogData_GetPaperSize, 2389). --define(wxPageSetupDialogData_GetPrintData, 2391). --define(wxPageSetupDialogData_IsOk, 2392). --define(wxPageSetupDialogData_SetDefaultInfo, 2393). --define(wxPageSetupDialogData_SetDefaultMinMargins, 2394). --define(wxPageSetupDialogData_SetMarginTopLeft, 2395). --define(wxPageSetupDialogData_SetMarginBottomRight, 2396). --define(wxPageSetupDialogData_SetMinMarginTopLeft, 2397). --define(wxPageSetupDialogData_SetMinMarginBottomRight, 2398). --define(wxPageSetupDialogData_SetPaperId, 2399). --define(wxPageSetupDialogData_SetPaperSize_1_1, 2400). --define(wxPageSetupDialogData_SetPaperSize_1_0, 2401). --define(wxPageSetupDialogData_SetPrintData, 2402). --define(wxPrintDialog_new_2_0, 2403). --define(wxPrintDialog_new_2_1, 2404). --define(wxPrintDialog_destruct, 2405). --define(wxPrintDialog_GetPrintDialogData, 2406). --define(wxPrintDialog_GetPrintDC, 2407). --define(wxPrintDialogData_new_0, 2408). --define(wxPrintDialogData_new_1_1, 2409). --define(wxPrintDialogData_new_1_0, 2410). --define(wxPrintDialogData_destruct, 2411). --define(wxPrintDialogData_EnableHelp, 2412). --define(wxPrintDialogData_EnablePageNumbers, 2413). --define(wxPrintDialogData_EnablePrintToFile, 2414). --define(wxPrintDialogData_EnableSelection, 2415). --define(wxPrintDialogData_GetAllPages, 2416). --define(wxPrintDialogData_GetCollate, 2417). --define(wxPrintDialogData_GetFromPage, 2418). --define(wxPrintDialogData_GetMaxPage, 2419). --define(wxPrintDialogData_GetMinPage, 2420). --define(wxPrintDialogData_GetNoCopies, 2421). --define(wxPrintDialogData_GetPrintData, 2422). --define(wxPrintDialogData_GetPrintToFile, 2423). --define(wxPrintDialogData_GetSelection, 2424). --define(wxPrintDialogData_GetToPage, 2425). --define(wxPrintDialogData_IsOk, 2426). --define(wxPrintDialogData_SetCollate, 2427). --define(wxPrintDialogData_SetFromPage, 2428). --define(wxPrintDialogData_SetMaxPage, 2429). --define(wxPrintDialogData_SetMinPage, 2430). --define(wxPrintDialogData_SetNoCopies, 2431). --define(wxPrintDialogData_SetPrintData, 2432). --define(wxPrintDialogData_SetPrintToFile, 2433). --define(wxPrintDialogData_SetSelection, 2434). --define(wxPrintDialogData_SetToPage, 2435). --define(wxPrintData_new_0, 2436). --define(wxPrintData_new_1, 2437). --define(wxPrintData_destruct, 2438). --define(wxPrintData_GetCollate, 2439). --define(wxPrintData_GetBin, 2440). --define(wxPrintData_GetColour, 2441). --define(wxPrintData_GetDuplex, 2442). --define(wxPrintData_GetNoCopies, 2443). --define(wxPrintData_GetOrientation, 2444). --define(wxPrintData_GetPaperId, 2445). --define(wxPrintData_GetPrinterName, 2446). --define(wxPrintData_GetQuality, 2447). --define(wxPrintData_IsOk, 2448). --define(wxPrintData_SetBin, 2449). --define(wxPrintData_SetCollate, 2450). --define(wxPrintData_SetColour, 2451). --define(wxPrintData_SetDuplex, 2452). --define(wxPrintData_SetNoCopies, 2453). --define(wxPrintData_SetOrientation, 2454). --define(wxPrintData_SetPaperId, 2455). --define(wxPrintData_SetPrinterName, 2456). --define(wxPrintData_SetQuality, 2457). --define(wxPrintPreview_new_2, 2460). --define(wxPrintPreview_new_3, 2461). --define(wxPrintPreview_destruct, 2463). --define(wxPrintPreview_GetCanvas, 2464). --define(wxPrintPreview_GetCurrentPage, 2465). --define(wxPrintPreview_GetFrame, 2466). --define(wxPrintPreview_GetMaxPage, 2467). --define(wxPrintPreview_GetMinPage, 2468). --define(wxPrintPreview_GetPrintout, 2469). --define(wxPrintPreview_GetPrintoutForPrinting, 2470). --define(wxPrintPreview_IsOk, 2471). --define(wxPrintPreview_PaintPage, 2472). --define(wxPrintPreview_Print, 2473). --define(wxPrintPreview_RenderPage, 2474). --define(wxPrintPreview_SetCanvas, 2475). --define(wxPrintPreview_SetCurrentPage, 2476). --define(wxPrintPreview_SetFrame, 2477). --define(wxPrintPreview_SetPrintout, 2478). --define(wxPrintPreview_SetZoom, 2479). --define(wxPreviewFrame_new, 2480). --define(wxPreviewFrame_destruct, 2481). --define(wxPreviewFrame_CreateControlBar, 2482). --define(wxPreviewFrame_CreateCanvas, 2483). --define(wxPreviewFrame_Initialize, 2484). --define(wxPreviewFrame_OnCloseWindow, 2485). --define(wxPreviewControlBar_new, 2486). --define(wxPreviewControlBar_destruct, 2487). --define(wxPreviewControlBar_CreateButtons, 2488). --define(wxPreviewControlBar_GetPrintPreview, 2489). --define(wxPreviewControlBar_GetZoomControl, 2490). --define(wxPreviewControlBar_SetZoomControl, 2491). --define(wxPrinter_new, 2493). --define(wxPrinter_CreateAbortWindow, 2494). --define(wxPrinter_GetAbort, 2495). --define(wxPrinter_GetLastError, 2496). --define(wxPrinter_GetPrintDialogData, 2497). --define(wxPrinter_Print, 2498). --define(wxPrinter_PrintDialog, 2499). --define(wxPrinter_ReportError, 2500). --define(wxPrinter_Setup, 2501). --define(wxPrinter_destroy, 2502). --define(wxXmlResource_new_1, 2503). --define(wxXmlResource_new_2, 2504). --define(wxXmlResource_destruct, 2505). --define(wxXmlResource_AttachUnknownControl, 2506). --define(wxXmlResource_ClearHandlers, 2507). --define(wxXmlResource_CompareVersion, 2508). --define(wxXmlResource_Get, 2509). --define(wxXmlResource_GetFlags, 2510). --define(wxXmlResource_GetVersion, 2511). --define(wxXmlResource_GetXRCID, 2512). --define(wxXmlResource_InitAllHandlers, 2513). --define(wxXmlResource_Load, 2514). --define(wxXmlResource_LoadBitmap, 2515). --define(wxXmlResource_LoadDialog_2, 2516). --define(wxXmlResource_LoadDialog_3, 2517). --define(wxXmlResource_LoadFrame_2, 2518). --define(wxXmlResource_LoadFrame_3, 2519). --define(wxXmlResource_LoadIcon, 2520). --define(wxXmlResource_LoadMenu, 2521). --define(wxXmlResource_LoadMenuBar_2, 2522). --define(wxXmlResource_LoadMenuBar_1, 2523). --define(wxXmlResource_LoadPanel_2, 2524). --define(wxXmlResource_LoadPanel_3, 2525). --define(wxXmlResource_LoadToolBar, 2526). --define(wxXmlResource_Set, 2527). --define(wxXmlResource_SetFlags, 2528). --define(wxXmlResource_Unload, 2529). --define(wxXmlResource_xrcctrl, 2530). --define(wxHtmlEasyPrinting_new, 2531). --define(wxHtmlEasyPrinting_destruct, 2532). --define(wxHtmlEasyPrinting_GetPrintData, 2533). --define(wxHtmlEasyPrinting_GetPageSetupData, 2534). --define(wxHtmlEasyPrinting_PreviewFile, 2535). --define(wxHtmlEasyPrinting_PreviewText, 2536). --define(wxHtmlEasyPrinting_PrintFile, 2537). --define(wxHtmlEasyPrinting_PrintText, 2538). --define(wxHtmlEasyPrinting_PageSetup, 2539). --define(wxHtmlEasyPrinting_SetFonts, 2540). --define(wxHtmlEasyPrinting_SetHeader, 2541). --define(wxHtmlEasyPrinting_SetFooter, 2542). --define(wxGLCanvas_new_2, 2544). --define(wxGLCanvas_new_3_1, 2545). --define(wxGLCanvas_new_3_0, 2546). --define(wxGLCanvas_GetContext, 2547). --define(wxGLCanvas_SetCurrent, 2549). --define(wxGLCanvas_SwapBuffers, 2550). --define(wxGLCanvas_destroy, 2551). --define(wxAuiManager_new, 2552). --define(wxAuiManager_destruct, 2553). --define(wxAuiManager_AddPane_2_1, 2554). --define(wxAuiManager_AddPane_3, 2555). --define(wxAuiManager_AddPane_2_0, 2556). --define(wxAuiManager_DetachPane, 2557). --define(wxAuiManager_GetAllPanes, 2558). --define(wxAuiManager_GetArtProvider, 2559). --define(wxAuiManager_GetDockSizeConstraint, 2560). --define(wxAuiManager_GetFlags, 2561). --define(wxAuiManager_GetManagedWindow, 2562). --define(wxAuiManager_GetManager, 2563). --define(wxAuiManager_GetPane_1_1, 2564). --define(wxAuiManager_GetPane_1_0, 2565). --define(wxAuiManager_HideHint, 2566). --define(wxAuiManager_InsertPane, 2567). --define(wxAuiManager_LoadPaneInfo, 2568). --define(wxAuiManager_LoadPerspective, 2569). --define(wxAuiManager_SavePaneInfo, 2570). --define(wxAuiManager_SavePerspective, 2571). --define(wxAuiManager_SetArtProvider, 2572). --define(wxAuiManager_SetDockSizeConstraint, 2573). --define(wxAuiManager_SetFlags, 2574). --define(wxAuiManager_SetManagedWindow, 2575). --define(wxAuiManager_ShowHint, 2576). --define(wxAuiManager_UnInit, 2577). --define(wxAuiManager_Update, 2578). --define(wxAuiPaneInfo_new_0, 2579). --define(wxAuiPaneInfo_new_1, 2580). --define(wxAuiPaneInfo_destruct, 2581). --define(wxAuiPaneInfo_BestSize_1, 2582). --define(wxAuiPaneInfo_BestSize_2, 2583). --define(wxAuiPaneInfo_Bottom, 2584). --define(wxAuiPaneInfo_BottomDockable, 2585). --define(wxAuiPaneInfo_Caption, 2586). --define(wxAuiPaneInfo_CaptionVisible, 2587). --define(wxAuiPaneInfo_Centre, 2588). --define(wxAuiPaneInfo_CentrePane, 2589). --define(wxAuiPaneInfo_CloseButton, 2590). --define(wxAuiPaneInfo_DefaultPane, 2591). --define(wxAuiPaneInfo_DestroyOnClose, 2592). --define(wxAuiPaneInfo_Direction, 2593). --define(wxAuiPaneInfo_Dock, 2594). --define(wxAuiPaneInfo_Dockable, 2595). --define(wxAuiPaneInfo_Fixed, 2596). --define(wxAuiPaneInfo_Float, 2597). --define(wxAuiPaneInfo_Floatable, 2598). --define(wxAuiPaneInfo_FloatingPosition_1, 2599). --define(wxAuiPaneInfo_FloatingPosition_2, 2600). --define(wxAuiPaneInfo_FloatingSize_1, 2601). --define(wxAuiPaneInfo_FloatingSize_2, 2602). --define(wxAuiPaneInfo_Gripper, 2603). --define(wxAuiPaneInfo_GripperTop, 2604). --define(wxAuiPaneInfo_HasBorder, 2605). --define(wxAuiPaneInfo_HasCaption, 2606). --define(wxAuiPaneInfo_HasCloseButton, 2607). --define(wxAuiPaneInfo_HasFlag, 2608). --define(wxAuiPaneInfo_HasGripper, 2609). --define(wxAuiPaneInfo_HasGripperTop, 2610). --define(wxAuiPaneInfo_HasMaximizeButton, 2611). --define(wxAuiPaneInfo_HasMinimizeButton, 2612). --define(wxAuiPaneInfo_HasPinButton, 2613). --define(wxAuiPaneInfo_Hide, 2614). --define(wxAuiPaneInfo_IsBottomDockable, 2615). --define(wxAuiPaneInfo_IsDocked, 2616). --define(wxAuiPaneInfo_IsFixed, 2617). --define(wxAuiPaneInfo_IsFloatable, 2618). --define(wxAuiPaneInfo_IsFloating, 2619). --define(wxAuiPaneInfo_IsLeftDockable, 2620). --define(wxAuiPaneInfo_IsMovable, 2621). --define(wxAuiPaneInfo_IsOk, 2622). --define(wxAuiPaneInfo_IsResizable, 2623). --define(wxAuiPaneInfo_IsRightDockable, 2624). --define(wxAuiPaneInfo_IsShown, 2625). --define(wxAuiPaneInfo_IsToolbar, 2626). --define(wxAuiPaneInfo_IsTopDockable, 2627). --define(wxAuiPaneInfo_Layer, 2628). --define(wxAuiPaneInfo_Left, 2629). --define(wxAuiPaneInfo_LeftDockable, 2630). --define(wxAuiPaneInfo_MaxSize_1, 2631). --define(wxAuiPaneInfo_MaxSize_2, 2632). --define(wxAuiPaneInfo_MaximizeButton, 2633). --define(wxAuiPaneInfo_MinSize_1, 2634). --define(wxAuiPaneInfo_MinSize_2, 2635). --define(wxAuiPaneInfo_MinimizeButton, 2636). --define(wxAuiPaneInfo_Movable, 2637). --define(wxAuiPaneInfo_Name, 2638). --define(wxAuiPaneInfo_PaneBorder, 2639). --define(wxAuiPaneInfo_PinButton, 2640). --define(wxAuiPaneInfo_Position, 2641). --define(wxAuiPaneInfo_Resizable, 2642). --define(wxAuiPaneInfo_Right, 2643). --define(wxAuiPaneInfo_RightDockable, 2644). --define(wxAuiPaneInfo_Row, 2645). --define(wxAuiPaneInfo_SafeSet, 2646). --define(wxAuiPaneInfo_SetFlag, 2647). --define(wxAuiPaneInfo_Show, 2648). --define(wxAuiPaneInfo_ToolbarPane, 2649). --define(wxAuiPaneInfo_Top, 2650). --define(wxAuiPaneInfo_TopDockable, 2651). --define(wxAuiPaneInfo_Window, 2652). --define(wxAuiPaneInfo_GetWindow, 2653). --define(wxAuiPaneInfo_GetFrame, 2654). --define(wxAuiPaneInfo_GetDirection, 2655). --define(wxAuiPaneInfo_GetLayer, 2656). --define(wxAuiPaneInfo_GetRow, 2657). --define(wxAuiPaneInfo_GetPosition, 2658). --define(wxAuiPaneInfo_GetFloatingPosition, 2659). --define(wxAuiPaneInfo_GetFloatingSize, 2660). --define(wxAuiNotebook_new_0, 2661). --define(wxAuiNotebook_new_2, 2662). --define(wxAuiNotebook_AddPage, 2663). --define(wxAuiNotebook_Create, 2664). --define(wxAuiNotebook_DeletePage, 2665). --define(wxAuiNotebook_GetArtProvider, 2666). --define(wxAuiNotebook_GetPage, 2667). --define(wxAuiNotebook_GetPageBitmap, 2668). --define(wxAuiNotebook_GetPageCount, 2669). --define(wxAuiNotebook_GetPageIndex, 2670). --define(wxAuiNotebook_GetPageText, 2671). --define(wxAuiNotebook_GetSelection, 2672). --define(wxAuiNotebook_InsertPage, 2673). --define(wxAuiNotebook_RemovePage, 2674). --define(wxAuiNotebook_SetArtProvider, 2675). --define(wxAuiNotebook_SetFont, 2676). --define(wxAuiNotebook_SetPageBitmap, 2677). --define(wxAuiNotebook_SetPageText, 2678). --define(wxAuiNotebook_SetSelection, 2679). --define(wxAuiNotebook_SetTabCtrlHeight, 2680). --define(wxAuiNotebook_SetUniformBitmapSize, 2681). --define(wxAuiNotebook_destroy, 2682). --define(wxAuiTabArt_SetFlags, 2683). --define(wxAuiTabArt_SetMeasuringFont, 2684). --define(wxAuiTabArt_SetNormalFont, 2685). --define(wxAuiTabArt_SetSelectedFont, 2686). --define(wxAuiTabArt_SetColour, 2687). --define(wxAuiTabArt_SetActiveColour, 2688). --define(wxAuiDockArt_GetColour, 2689). --define(wxAuiDockArt_GetFont, 2690). --define(wxAuiDockArt_GetMetric, 2691). --define(wxAuiDockArt_SetColour, 2692). --define(wxAuiDockArt_SetFont, 2693). --define(wxAuiDockArt_SetMetric, 2694). --define(wxAuiSimpleTabArt_new, 2695). --define(wxAuiSimpleTabArt_destroy, 2696). --define(wxMDIParentFrame_new_0, 2697). --define(wxMDIParentFrame_new_4, 2698). --define(wxMDIParentFrame_destruct, 2699). --define(wxMDIParentFrame_ActivateNext, 2700). --define(wxMDIParentFrame_ActivatePrevious, 2701). --define(wxMDIParentFrame_ArrangeIcons, 2702). --define(wxMDIParentFrame_Cascade, 2703). --define(wxMDIParentFrame_Create, 2704). --define(wxMDIParentFrame_GetActiveChild, 2705). --define(wxMDIParentFrame_GetClientWindow, 2706). --define(wxMDIParentFrame_Tile, 2707). --define(wxMDIChildFrame_new_0, 2708). --define(wxMDIChildFrame_new_4, 2709). --define(wxMDIChildFrame_destruct, 2710). --define(wxMDIChildFrame_Activate, 2711). --define(wxMDIChildFrame_Create, 2712). --define(wxMDIChildFrame_Maximize, 2713). --define(wxMDIChildFrame_Restore, 2714). --define(wxMDIClientWindow_new_0, 2715). --define(wxMDIClientWindow_new_2, 2716). --define(wxMDIClientWindow_destruct, 2717). --define(wxMDIClientWindow_CreateClient, 2718). --define(wxLayoutAlgorithm_new, 2719). --define(wxLayoutAlgorithm_LayoutFrame, 2720). --define(wxLayoutAlgorithm_LayoutMDIFrame, 2721). --define(wxLayoutAlgorithm_LayoutWindow, 2722). --define(wxLayoutAlgorithm_destroy, 2723). --define(wxEvent_GetId, 2724). --define(wxEvent_GetSkipped, 2725). --define(wxEvent_GetTimestamp, 2726). --define(wxEvent_IsCommandEvent, 2727). --define(wxEvent_ResumePropagation, 2728). --define(wxEvent_ShouldPropagate, 2729). --define(wxEvent_Skip, 2730). --define(wxEvent_StopPropagation, 2731). --define(wxCommandEvent_getClientData, 2732). --define(wxCommandEvent_GetExtraLong, 2733). --define(wxCommandEvent_GetInt, 2734). --define(wxCommandEvent_GetSelection, 2735). --define(wxCommandEvent_GetString, 2736). --define(wxCommandEvent_IsChecked, 2737). --define(wxCommandEvent_IsSelection, 2738). --define(wxCommandEvent_SetInt, 2739). --define(wxCommandEvent_SetString, 2740). --define(wxScrollEvent_GetOrientation, 2741). --define(wxScrollEvent_GetPosition, 2742). --define(wxScrollWinEvent_GetOrientation, 2743). --define(wxScrollWinEvent_GetPosition, 2744). --define(wxMouseEvent_AltDown, 2745). --define(wxMouseEvent_Button, 2746). --define(wxMouseEvent_ButtonDClick, 2747). --define(wxMouseEvent_ButtonDown, 2748). --define(wxMouseEvent_ButtonUp, 2749). --define(wxMouseEvent_CmdDown, 2750). --define(wxMouseEvent_ControlDown, 2751). --define(wxMouseEvent_Dragging, 2752). --define(wxMouseEvent_Entering, 2753). --define(wxMouseEvent_GetButton, 2754). --define(wxMouseEvent_GetPosition, 2757). --define(wxMouseEvent_GetLogicalPosition, 2758). --define(wxMouseEvent_GetLinesPerAction, 2759). --define(wxMouseEvent_GetWheelRotation, 2760). --define(wxMouseEvent_GetWheelDelta, 2761). --define(wxMouseEvent_GetX, 2762). --define(wxMouseEvent_GetY, 2763). --define(wxMouseEvent_IsButton, 2764). --define(wxMouseEvent_IsPageScroll, 2765). --define(wxMouseEvent_Leaving, 2766). --define(wxMouseEvent_LeftDClick, 2767). --define(wxMouseEvent_LeftDown, 2768). --define(wxMouseEvent_LeftIsDown, 2769). --define(wxMouseEvent_LeftUp, 2770). --define(wxMouseEvent_MetaDown, 2771). --define(wxMouseEvent_MiddleDClick, 2772). --define(wxMouseEvent_MiddleDown, 2773). --define(wxMouseEvent_MiddleIsDown, 2774). --define(wxMouseEvent_MiddleUp, 2775). --define(wxMouseEvent_Moving, 2776). --define(wxMouseEvent_RightDClick, 2777). --define(wxMouseEvent_RightDown, 2778). --define(wxMouseEvent_RightIsDown, 2779). --define(wxMouseEvent_RightUp, 2780). --define(wxMouseEvent_ShiftDown, 2781). --define(wxSetCursorEvent_GetCursor, 2782). --define(wxSetCursorEvent_GetX, 2783). --define(wxSetCursorEvent_GetY, 2784). --define(wxSetCursorEvent_HasCursor, 2785). --define(wxSetCursorEvent_SetCursor, 2786). --define(wxKeyEvent_AltDown, 2787). --define(wxKeyEvent_CmdDown, 2788). --define(wxKeyEvent_ControlDown, 2789). --define(wxKeyEvent_GetKeyCode, 2790). --define(wxKeyEvent_GetModifiers, 2791). --define(wxKeyEvent_GetPosition, 2794). --define(wxKeyEvent_GetRawKeyCode, 2795). --define(wxKeyEvent_GetRawKeyFlags, 2796). --define(wxKeyEvent_GetUnicodeKey, 2797). --define(wxKeyEvent_GetX, 2798). --define(wxKeyEvent_GetY, 2799). --define(wxKeyEvent_HasModifiers, 2800). --define(wxKeyEvent_MetaDown, 2801). --define(wxKeyEvent_ShiftDown, 2802). --define(wxSizeEvent_GetSize, 2803). --define(wxMoveEvent_GetPosition, 2804). --define(wxEraseEvent_GetDC, 2805). --define(wxFocusEvent_GetWindow, 2806). --define(wxChildFocusEvent_GetWindow, 2807). --define(wxMenuEvent_GetMenu, 2808). --define(wxMenuEvent_GetMenuId, 2809). --define(wxMenuEvent_IsPopup, 2810). --define(wxCloseEvent_CanVeto, 2811). --define(wxCloseEvent_GetLoggingOff, 2812). --define(wxCloseEvent_SetCanVeto, 2813). --define(wxCloseEvent_SetLoggingOff, 2814). --define(wxCloseEvent_Veto, 2815). --define(wxShowEvent_SetShow, 2816). --define(wxShowEvent_GetShow, 2817). --define(wxIconizeEvent_Iconized, 2818). --define(wxJoystickEvent_ButtonDown, 2819). --define(wxJoystickEvent_ButtonIsDown, 2820). --define(wxJoystickEvent_ButtonUp, 2821). --define(wxJoystickEvent_GetButtonChange, 2822). --define(wxJoystickEvent_GetButtonState, 2823). --define(wxJoystickEvent_GetJoystick, 2824). --define(wxJoystickEvent_GetPosition, 2825). --define(wxJoystickEvent_GetZPosition, 2826). --define(wxJoystickEvent_IsButton, 2827). --define(wxJoystickEvent_IsMove, 2828). --define(wxJoystickEvent_IsZMove, 2829). --define(wxUpdateUIEvent_CanUpdate, 2830). --define(wxUpdateUIEvent_Check, 2831). --define(wxUpdateUIEvent_Enable, 2832). --define(wxUpdateUIEvent_Show, 2833). --define(wxUpdateUIEvent_GetChecked, 2834). --define(wxUpdateUIEvent_GetEnabled, 2835). --define(wxUpdateUIEvent_GetShown, 2836). --define(wxUpdateUIEvent_GetSetChecked, 2837). --define(wxUpdateUIEvent_GetSetEnabled, 2838). --define(wxUpdateUIEvent_GetSetShown, 2839). --define(wxUpdateUIEvent_GetSetText, 2840). --define(wxUpdateUIEvent_GetText, 2841). --define(wxUpdateUIEvent_GetMode, 2842). --define(wxUpdateUIEvent_GetUpdateInterval, 2843). --define(wxUpdateUIEvent_ResetUpdateTime, 2844). --define(wxUpdateUIEvent_SetMode, 2845). --define(wxUpdateUIEvent_SetText, 2846). --define(wxUpdateUIEvent_SetUpdateInterval, 2847). --define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2848). --define(wxPaletteChangedEvent_SetChangedWindow, 2849). --define(wxPaletteChangedEvent_GetChangedWindow, 2850). --define(wxQueryNewPaletteEvent_SetPaletteRealized, 2851). --define(wxQueryNewPaletteEvent_GetPaletteRealized, 2852). --define(wxNavigationKeyEvent_GetDirection, 2853). --define(wxNavigationKeyEvent_SetDirection, 2854). --define(wxNavigationKeyEvent_IsWindowChange, 2855). --define(wxNavigationKeyEvent_SetWindowChange, 2856). --define(wxNavigationKeyEvent_IsFromTab, 2857). --define(wxNavigationKeyEvent_SetFromTab, 2858). --define(wxNavigationKeyEvent_GetCurrentFocus, 2859). --define(wxNavigationKeyEvent_SetCurrentFocus, 2860). --define(wxHelpEvent_GetOrigin, 2861). --define(wxHelpEvent_GetPosition, 2862). --define(wxHelpEvent_SetOrigin, 2863). --define(wxHelpEvent_SetPosition, 2864). --define(wxContextMenuEvent_GetPosition, 2865). --define(wxContextMenuEvent_SetPosition, 2866). --define(wxIdleEvent_CanSend, 2867). --define(wxIdleEvent_GetMode, 2868). --define(wxIdleEvent_RequestMore, 2869). --define(wxIdleEvent_MoreRequested, 2870). --define(wxIdleEvent_SetMode, 2871). --define(wxGridEvent_AltDown, 2872). --define(wxGridEvent_ControlDown, 2873). --define(wxGridEvent_GetCol, 2874). --define(wxGridEvent_GetPosition, 2875). --define(wxGridEvent_GetRow, 2876). --define(wxGridEvent_MetaDown, 2877). --define(wxGridEvent_Selecting, 2878). --define(wxGridEvent_ShiftDown, 2879). --define(wxNotifyEvent_Allow, 2880). --define(wxNotifyEvent_IsAllowed, 2881). --define(wxNotifyEvent_Veto, 2882). --define(wxSashEvent_GetEdge, 2883). --define(wxSashEvent_GetDragRect, 2884). --define(wxSashEvent_GetDragStatus, 2885). --define(wxListEvent_GetCacheFrom, 2886). --define(wxListEvent_GetCacheTo, 2887). --define(wxListEvent_GetKeyCode, 2888). --define(wxListEvent_GetIndex, 2889). --define(wxListEvent_GetColumn, 2890). --define(wxListEvent_GetPoint, 2891). --define(wxListEvent_GetLabel, 2892). --define(wxListEvent_GetText, 2893). --define(wxListEvent_GetImage, 2894). --define(wxListEvent_GetData, 2895). --define(wxListEvent_GetMask, 2896). --define(wxListEvent_GetItem, 2897). --define(wxListEvent_IsEditCancelled, 2898). --define(wxDateEvent_GetDate, 2899). --define(wxCalendarEvent_GetWeekDay, 2900). --define(wxFileDirPickerEvent_GetPath, 2901). --define(wxColourPickerEvent_GetColour, 2902). --define(wxFontPickerEvent_GetFont, 2903). --define(wxStyledTextEvent_GetPosition, 2904). --define(wxStyledTextEvent_GetKey, 2905). --define(wxStyledTextEvent_GetModifiers, 2906). --define(wxStyledTextEvent_GetModificationType, 2907). --define(wxStyledTextEvent_GetText, 2908). --define(wxStyledTextEvent_GetLength, 2909). --define(wxStyledTextEvent_GetLinesAdded, 2910). --define(wxStyledTextEvent_GetLine, 2911). --define(wxStyledTextEvent_GetFoldLevelNow, 2912). --define(wxStyledTextEvent_GetFoldLevelPrev, 2913). --define(wxStyledTextEvent_GetMargin, 2914). --define(wxStyledTextEvent_GetMessage, 2915). --define(wxStyledTextEvent_GetWParam, 2916). --define(wxStyledTextEvent_GetLParam, 2917). --define(wxStyledTextEvent_GetListType, 2918). --define(wxStyledTextEvent_GetX, 2919). --define(wxStyledTextEvent_GetY, 2920). --define(wxStyledTextEvent_GetDragText, 2921). --define(wxStyledTextEvent_GetDragAllowMove, 2922). --define(wxStyledTextEvent_GetDragResult, 2923). --define(wxStyledTextEvent_GetShift, 2924). --define(wxStyledTextEvent_GetControl, 2925). --define(wxStyledTextEvent_GetAlt, 2926). --define(utils_wxGetKeyState, 2927). --define(utils_wxGetMousePosition, 2928). --define(utils_wxGetMouseState, 2929). --define(utils_wxSetDetectableAutoRepeat, 2930). --define(utils_wxBell, 2931). --define(utils_wxFindMenuItemId, 2932). --define(utils_wxGenericFindWindowAtPoint, 2933). --define(utils_wxFindWindowAtPoint, 2934). --define(utils_wxBeginBusyCursor, 2935). --define(utils_wxEndBusyCursor, 2936). --define(utils_wxIsBusy, 2937). --define(utils_wxShutdown, 2938). --define(utils_wxShell, 2939). --define(utils_wxLaunchDefaultBrowser, 2940). --define(utils_wxGetEmailAddress, 2941). --define(utils_wxGetUserId, 2942). --define(utils_wxGetHomeDir, 2943). --define(utils_wxNewId, 2944). --define(utils_wxRegisterId, 2945). --define(utils_wxGetCurrentId, 2946). --define(utils_wxGetOsDescription, 2947). --define(utils_wxIsPlatformLittleEndian, 2948). --define(utils_wxIsPlatform64Bit, 2949). --define(gdicmn_wxDisplaySize, 2950). --define(gdicmn_wxSetCursor, 2951). --define(wxPrintout_new, 2952). --define(wxPrintout_destruct, 2953). --define(wxPrintout_GetDC, 2954). --define(wxPrintout_GetPageSizeMM, 2955). --define(wxPrintout_GetPageSizePixels, 2956). --define(wxPrintout_GetPaperRectPixels, 2957). --define(wxPrintout_GetPPIPrinter, 2958). --define(wxPrintout_GetPPIScreen, 2959). --define(wxPrintout_GetTitle, 2960). --define(wxPrintout_IsPreview, 2961). --define(wxPrintout_FitThisSizeToPaper, 2962). --define(wxPrintout_FitThisSizeToPage, 2963). --define(wxPrintout_FitThisSizeToPageMargins, 2964). --define(wxPrintout_MapScreenSizeToPaper, 2965). --define(wxPrintout_MapScreenSizeToPage, 2966). --define(wxPrintout_MapScreenSizeToPageMargins, 2967). --define(wxPrintout_MapScreenSizeToDevice, 2968). --define(wxPrintout_GetLogicalPaperRect, 2969). --define(wxPrintout_GetLogicalPageRect, 2970). --define(wxPrintout_GetLogicalPageMarginsRect, 2971). --define(wxPrintout_SetLogicalOrigin, 2972). --define(wxPrintout_OffsetLogicalOrigin, 2973). --define(wxStyledTextCtrl_new_2, 2974). --define(wxStyledTextCtrl_new_0, 2975). --define(wxStyledTextCtrl_destruct, 2976). --define(wxStyledTextCtrl_Create, 2977). --define(wxStyledTextCtrl_AddText, 2978). --define(wxStyledTextCtrl_AddStyledText, 2979). --define(wxStyledTextCtrl_InsertText, 2980). --define(wxStyledTextCtrl_ClearAll, 2981). --define(wxStyledTextCtrl_ClearDocumentStyle, 2982). --define(wxStyledTextCtrl_GetLength, 2983). --define(wxStyledTextCtrl_GetCharAt, 2984). --define(wxStyledTextCtrl_GetCurrentPos, 2985). --define(wxStyledTextCtrl_GetAnchor, 2986). --define(wxStyledTextCtrl_GetStyleAt, 2987). --define(wxStyledTextCtrl_Redo, 2988). --define(wxStyledTextCtrl_SetUndoCollection, 2989). --define(wxStyledTextCtrl_SelectAll, 2990). --define(wxStyledTextCtrl_SetSavePoint, 2991). --define(wxStyledTextCtrl_GetStyledText, 2992). --define(wxStyledTextCtrl_CanRedo, 2993). --define(wxStyledTextCtrl_MarkerLineFromHandle, 2994). --define(wxStyledTextCtrl_MarkerDeleteHandle, 2995). --define(wxStyledTextCtrl_GetUndoCollection, 2996). --define(wxStyledTextCtrl_GetViewWhiteSpace, 2997). --define(wxStyledTextCtrl_SetViewWhiteSpace, 2998). --define(wxStyledTextCtrl_PositionFromPoint, 2999). --define(wxStyledTextCtrl_PositionFromPointClose, 3000). --define(wxStyledTextCtrl_GotoLine, 3001). --define(wxStyledTextCtrl_GotoPos, 3002). --define(wxStyledTextCtrl_SetAnchor, 3003). --define(wxStyledTextCtrl_GetCurLine, 3004). --define(wxStyledTextCtrl_GetEndStyled, 3005). --define(wxStyledTextCtrl_ConvertEOLs, 3006). --define(wxStyledTextCtrl_GetEOLMode, 3007). --define(wxStyledTextCtrl_SetEOLMode, 3008). --define(wxStyledTextCtrl_StartStyling, 3009). --define(wxStyledTextCtrl_SetStyling, 3010). --define(wxStyledTextCtrl_GetBufferedDraw, 3011). --define(wxStyledTextCtrl_SetBufferedDraw, 3012). --define(wxStyledTextCtrl_SetTabWidth, 3013). --define(wxStyledTextCtrl_GetTabWidth, 3014). --define(wxStyledTextCtrl_SetCodePage, 3015). --define(wxStyledTextCtrl_MarkerDefine, 3016). --define(wxStyledTextCtrl_MarkerSetForeground, 3017). --define(wxStyledTextCtrl_MarkerSetBackground, 3018). --define(wxStyledTextCtrl_MarkerAdd, 3019). --define(wxStyledTextCtrl_MarkerDelete, 3020). --define(wxStyledTextCtrl_MarkerDeleteAll, 3021). --define(wxStyledTextCtrl_MarkerGet, 3022). --define(wxStyledTextCtrl_MarkerNext, 3023). --define(wxStyledTextCtrl_MarkerPrevious, 3024). --define(wxStyledTextCtrl_MarkerDefineBitmap, 3025). --define(wxStyledTextCtrl_MarkerAddSet, 3026). --define(wxStyledTextCtrl_MarkerSetAlpha, 3027). --define(wxStyledTextCtrl_SetMarginType, 3028). --define(wxStyledTextCtrl_GetMarginType, 3029). --define(wxStyledTextCtrl_SetMarginWidth, 3030). --define(wxStyledTextCtrl_GetMarginWidth, 3031). --define(wxStyledTextCtrl_SetMarginMask, 3032). --define(wxStyledTextCtrl_GetMarginMask, 3033). --define(wxStyledTextCtrl_SetMarginSensitive, 3034). --define(wxStyledTextCtrl_GetMarginSensitive, 3035). --define(wxStyledTextCtrl_StyleClearAll, 3036). --define(wxStyledTextCtrl_StyleSetForeground, 3037). --define(wxStyledTextCtrl_StyleSetBackground, 3038). --define(wxStyledTextCtrl_StyleSetBold, 3039). --define(wxStyledTextCtrl_StyleSetItalic, 3040). --define(wxStyledTextCtrl_StyleSetSize, 3041). --define(wxStyledTextCtrl_StyleSetFaceName, 3042). --define(wxStyledTextCtrl_StyleSetEOLFilled, 3043). --define(wxStyledTextCtrl_StyleResetDefault, 3044). --define(wxStyledTextCtrl_StyleSetUnderline, 3045). --define(wxStyledTextCtrl_StyleSetCase, 3046). --define(wxStyledTextCtrl_StyleSetHotSpot, 3047). --define(wxStyledTextCtrl_SetSelForeground, 3048). --define(wxStyledTextCtrl_SetSelBackground, 3049). --define(wxStyledTextCtrl_GetSelAlpha, 3050). --define(wxStyledTextCtrl_SetSelAlpha, 3051). --define(wxStyledTextCtrl_SetCaretForeground, 3052). --define(wxStyledTextCtrl_CmdKeyAssign, 3053). --define(wxStyledTextCtrl_CmdKeyClear, 3054). --define(wxStyledTextCtrl_CmdKeyClearAll, 3055). --define(wxStyledTextCtrl_SetStyleBytes, 3056). --define(wxStyledTextCtrl_StyleSetVisible, 3057). --define(wxStyledTextCtrl_GetCaretPeriod, 3058). --define(wxStyledTextCtrl_SetCaretPeriod, 3059). --define(wxStyledTextCtrl_SetWordChars, 3060). --define(wxStyledTextCtrl_BeginUndoAction, 3061). --define(wxStyledTextCtrl_EndUndoAction, 3062). --define(wxStyledTextCtrl_IndicatorSetStyle, 3063). --define(wxStyledTextCtrl_IndicatorGetStyle, 3064). --define(wxStyledTextCtrl_IndicatorSetForeground, 3065). --define(wxStyledTextCtrl_IndicatorGetForeground, 3066). --define(wxStyledTextCtrl_SetWhitespaceForeground, 3067). --define(wxStyledTextCtrl_SetWhitespaceBackground, 3068). --define(wxStyledTextCtrl_GetStyleBits, 3069). --define(wxStyledTextCtrl_SetLineState, 3070). --define(wxStyledTextCtrl_GetLineState, 3071). --define(wxStyledTextCtrl_GetMaxLineState, 3072). --define(wxStyledTextCtrl_GetCaretLineVisible, 3073). --define(wxStyledTextCtrl_SetCaretLineVisible, 3074). --define(wxStyledTextCtrl_GetCaretLineBackground, 3075). --define(wxStyledTextCtrl_SetCaretLineBackground, 3076). --define(wxStyledTextCtrl_AutoCompShow, 3077). --define(wxStyledTextCtrl_AutoCompCancel, 3078). --define(wxStyledTextCtrl_AutoCompActive, 3079). --define(wxStyledTextCtrl_AutoCompPosStart, 3080). --define(wxStyledTextCtrl_AutoCompComplete, 3081). --define(wxStyledTextCtrl_AutoCompStops, 3082). --define(wxStyledTextCtrl_AutoCompSetSeparator, 3083). --define(wxStyledTextCtrl_AutoCompGetSeparator, 3084). --define(wxStyledTextCtrl_AutoCompSelect, 3085). --define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3086). --define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3087). --define(wxStyledTextCtrl_AutoCompSetFillUps, 3088). --define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3089). --define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3090). --define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3091). --define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3092). --define(wxStyledTextCtrl_UserListShow, 3093). --define(wxStyledTextCtrl_AutoCompSetAutoHide, 3094). --define(wxStyledTextCtrl_AutoCompGetAutoHide, 3095). --define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3096). --define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3097). --define(wxStyledTextCtrl_RegisterImage, 3098). --define(wxStyledTextCtrl_ClearRegisteredImages, 3099). --define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3100). --define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3101). --define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3102). --define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3103). --define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3104). --define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3105). --define(wxStyledTextCtrl_SetIndent, 3106). --define(wxStyledTextCtrl_GetIndent, 3107). --define(wxStyledTextCtrl_SetUseTabs, 3108). --define(wxStyledTextCtrl_GetUseTabs, 3109). --define(wxStyledTextCtrl_SetLineIndentation, 3110). --define(wxStyledTextCtrl_GetLineIndentation, 3111). --define(wxStyledTextCtrl_GetLineIndentPosition, 3112). --define(wxStyledTextCtrl_GetColumn, 3113). --define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3114). --define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3115). --define(wxStyledTextCtrl_SetIndentationGuides, 3116). --define(wxStyledTextCtrl_GetIndentationGuides, 3117). --define(wxStyledTextCtrl_SetHighlightGuide, 3118). --define(wxStyledTextCtrl_GetHighlightGuide, 3119). --define(wxStyledTextCtrl_GetLineEndPosition, 3120). --define(wxStyledTextCtrl_GetCodePage, 3121). --define(wxStyledTextCtrl_GetCaretForeground, 3122). --define(wxStyledTextCtrl_GetReadOnly, 3123). --define(wxStyledTextCtrl_SetCurrentPos, 3124). --define(wxStyledTextCtrl_SetSelectionStart, 3125). --define(wxStyledTextCtrl_GetSelectionStart, 3126). --define(wxStyledTextCtrl_SetSelectionEnd, 3127). --define(wxStyledTextCtrl_GetSelectionEnd, 3128). --define(wxStyledTextCtrl_SetPrintMagnification, 3129). --define(wxStyledTextCtrl_GetPrintMagnification, 3130). --define(wxStyledTextCtrl_SetPrintColourMode, 3131). --define(wxStyledTextCtrl_GetPrintColourMode, 3132). --define(wxStyledTextCtrl_FindText, 3133). --define(wxStyledTextCtrl_FormatRange, 3134). --define(wxStyledTextCtrl_GetFirstVisibleLine, 3135). --define(wxStyledTextCtrl_GetLine, 3136). --define(wxStyledTextCtrl_GetLineCount, 3137). --define(wxStyledTextCtrl_SetMarginLeft, 3138). --define(wxStyledTextCtrl_GetMarginLeft, 3139). --define(wxStyledTextCtrl_SetMarginRight, 3140). --define(wxStyledTextCtrl_GetMarginRight, 3141). --define(wxStyledTextCtrl_GetModify, 3142). --define(wxStyledTextCtrl_SetSelection, 3143). --define(wxStyledTextCtrl_GetSelectedText, 3144). --define(wxStyledTextCtrl_GetTextRange, 3145). --define(wxStyledTextCtrl_HideSelection, 3146). --define(wxStyledTextCtrl_LineFromPosition, 3147). --define(wxStyledTextCtrl_PositionFromLine, 3148). --define(wxStyledTextCtrl_LineScroll, 3149). --define(wxStyledTextCtrl_EnsureCaretVisible, 3150). --define(wxStyledTextCtrl_ReplaceSelection, 3151). --define(wxStyledTextCtrl_SetReadOnly, 3152). --define(wxStyledTextCtrl_CanPaste, 3153). --define(wxStyledTextCtrl_CanUndo, 3154). --define(wxStyledTextCtrl_EmptyUndoBuffer, 3155). --define(wxStyledTextCtrl_Undo, 3156). --define(wxStyledTextCtrl_Cut, 3157). --define(wxStyledTextCtrl_Copy, 3158). --define(wxStyledTextCtrl_Paste, 3159). --define(wxStyledTextCtrl_Clear, 3160). --define(wxStyledTextCtrl_SetText, 3161). --define(wxStyledTextCtrl_GetText, 3162). --define(wxStyledTextCtrl_GetTextLength, 3163). --define(wxStyledTextCtrl_GetOvertype, 3164). --define(wxStyledTextCtrl_SetCaretWidth, 3165). --define(wxStyledTextCtrl_GetCaretWidth, 3166). --define(wxStyledTextCtrl_SetTargetStart, 3167). --define(wxStyledTextCtrl_GetTargetStart, 3168). --define(wxStyledTextCtrl_SetTargetEnd, 3169). --define(wxStyledTextCtrl_GetTargetEnd, 3170). --define(wxStyledTextCtrl_ReplaceTarget, 3171). --define(wxStyledTextCtrl_SearchInTarget, 3172). --define(wxStyledTextCtrl_SetSearchFlags, 3173). --define(wxStyledTextCtrl_GetSearchFlags, 3174). --define(wxStyledTextCtrl_CallTipShow, 3175). --define(wxStyledTextCtrl_CallTipCancel, 3176). --define(wxStyledTextCtrl_CallTipActive, 3177). --define(wxStyledTextCtrl_CallTipPosAtStart, 3178). --define(wxStyledTextCtrl_CallTipSetHighlight, 3179). --define(wxStyledTextCtrl_CallTipSetBackground, 3180). --define(wxStyledTextCtrl_CallTipSetForeground, 3181). --define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3182). --define(wxStyledTextCtrl_CallTipUseStyle, 3183). --define(wxStyledTextCtrl_VisibleFromDocLine, 3184). --define(wxStyledTextCtrl_DocLineFromVisible, 3185). --define(wxStyledTextCtrl_WrapCount, 3186). --define(wxStyledTextCtrl_SetFoldLevel, 3187). --define(wxStyledTextCtrl_GetFoldLevel, 3188). --define(wxStyledTextCtrl_GetLastChild, 3189). --define(wxStyledTextCtrl_GetFoldParent, 3190). --define(wxStyledTextCtrl_ShowLines, 3191). --define(wxStyledTextCtrl_HideLines, 3192). --define(wxStyledTextCtrl_GetLineVisible, 3193). --define(wxStyledTextCtrl_SetFoldExpanded, 3194). --define(wxStyledTextCtrl_GetFoldExpanded, 3195). --define(wxStyledTextCtrl_ToggleFold, 3196). --define(wxStyledTextCtrl_EnsureVisible, 3197). --define(wxStyledTextCtrl_SetFoldFlags, 3198). --define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3199). --define(wxStyledTextCtrl_SetTabIndents, 3200). --define(wxStyledTextCtrl_GetTabIndents, 3201). --define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3202). --define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3203). --define(wxStyledTextCtrl_SetMouseDwellTime, 3204). --define(wxStyledTextCtrl_GetMouseDwellTime, 3205). --define(wxStyledTextCtrl_WordStartPosition, 3206). --define(wxStyledTextCtrl_WordEndPosition, 3207). --define(wxStyledTextCtrl_SetWrapMode, 3208). --define(wxStyledTextCtrl_GetWrapMode, 3209). --define(wxStyledTextCtrl_SetWrapVisualFlags, 3210). --define(wxStyledTextCtrl_GetWrapVisualFlags, 3211). --define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3212). --define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3213). --define(wxStyledTextCtrl_SetWrapStartIndent, 3214). --define(wxStyledTextCtrl_GetWrapStartIndent, 3215). --define(wxStyledTextCtrl_SetLayoutCache, 3216). --define(wxStyledTextCtrl_GetLayoutCache, 3217). --define(wxStyledTextCtrl_SetScrollWidth, 3218). --define(wxStyledTextCtrl_GetScrollWidth, 3219). --define(wxStyledTextCtrl_TextWidth, 3220). --define(wxStyledTextCtrl_GetEndAtLastLine, 3221). --define(wxStyledTextCtrl_TextHeight, 3222). --define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3223). --define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3224). --define(wxStyledTextCtrl_AppendText, 3225). --define(wxStyledTextCtrl_GetTwoPhaseDraw, 3226). --define(wxStyledTextCtrl_SetTwoPhaseDraw, 3227). --define(wxStyledTextCtrl_TargetFromSelection, 3228). --define(wxStyledTextCtrl_LinesJoin, 3229). --define(wxStyledTextCtrl_LinesSplit, 3230). --define(wxStyledTextCtrl_SetFoldMarginColour, 3231). --define(wxStyledTextCtrl_SetFoldMarginHiColour, 3232). --define(wxStyledTextCtrl_LineDown, 3233). --define(wxStyledTextCtrl_LineDownExtend, 3234). --define(wxStyledTextCtrl_LineUp, 3235). --define(wxStyledTextCtrl_LineUpExtend, 3236). --define(wxStyledTextCtrl_CharLeft, 3237). --define(wxStyledTextCtrl_CharLeftExtend, 3238). --define(wxStyledTextCtrl_CharRight, 3239). --define(wxStyledTextCtrl_CharRightExtend, 3240). --define(wxStyledTextCtrl_WordLeft, 3241). --define(wxStyledTextCtrl_WordLeftExtend, 3242). --define(wxStyledTextCtrl_WordRight, 3243). --define(wxStyledTextCtrl_WordRightExtend, 3244). --define(wxStyledTextCtrl_Home, 3245). --define(wxStyledTextCtrl_HomeExtend, 3246). --define(wxStyledTextCtrl_LineEnd, 3247). --define(wxStyledTextCtrl_LineEndExtend, 3248). --define(wxStyledTextCtrl_DocumentStart, 3249). --define(wxStyledTextCtrl_DocumentStartExtend, 3250). --define(wxStyledTextCtrl_DocumentEnd, 3251). --define(wxStyledTextCtrl_DocumentEndExtend, 3252). --define(wxStyledTextCtrl_PageUp, 3253). --define(wxStyledTextCtrl_PageUpExtend, 3254). --define(wxStyledTextCtrl_PageDown, 3255). --define(wxStyledTextCtrl_PageDownExtend, 3256). --define(wxStyledTextCtrl_EditToggleOvertype, 3257). --define(wxStyledTextCtrl_Cancel, 3258). --define(wxStyledTextCtrl_DeleteBack, 3259). --define(wxStyledTextCtrl_Tab, 3260). --define(wxStyledTextCtrl_BackTab, 3261). --define(wxStyledTextCtrl_NewLine, 3262). --define(wxStyledTextCtrl_FormFeed, 3263). --define(wxStyledTextCtrl_VCHome, 3264). --define(wxStyledTextCtrl_VCHomeExtend, 3265). --define(wxStyledTextCtrl_ZoomIn, 3266). --define(wxStyledTextCtrl_ZoomOut, 3267). --define(wxStyledTextCtrl_DelWordLeft, 3268). --define(wxStyledTextCtrl_DelWordRight, 3269). --define(wxStyledTextCtrl_LineCut, 3270). --define(wxStyledTextCtrl_LineDelete, 3271). --define(wxStyledTextCtrl_LineTranspose, 3272). --define(wxStyledTextCtrl_LineDuplicate, 3273). --define(wxStyledTextCtrl_LowerCase, 3274). --define(wxStyledTextCtrl_UpperCase, 3275). --define(wxStyledTextCtrl_LineScrollDown, 3276). --define(wxStyledTextCtrl_LineScrollUp, 3277). --define(wxStyledTextCtrl_DeleteBackNotLine, 3278). --define(wxStyledTextCtrl_HomeDisplay, 3279). --define(wxStyledTextCtrl_HomeDisplayExtend, 3280). --define(wxStyledTextCtrl_LineEndDisplay, 3281). --define(wxStyledTextCtrl_LineEndDisplayExtend, 3282). --define(wxStyledTextCtrl_HomeWrapExtend, 3283). --define(wxStyledTextCtrl_LineEndWrap, 3284). --define(wxStyledTextCtrl_LineEndWrapExtend, 3285). --define(wxStyledTextCtrl_VCHomeWrap, 3286). --define(wxStyledTextCtrl_VCHomeWrapExtend, 3287). --define(wxStyledTextCtrl_LineCopy, 3288). --define(wxStyledTextCtrl_MoveCaretInsideView, 3289). --define(wxStyledTextCtrl_LineLength, 3290). --define(wxStyledTextCtrl_BraceHighlight, 3291). --define(wxStyledTextCtrl_BraceBadLight, 3292). --define(wxStyledTextCtrl_BraceMatch, 3293). --define(wxStyledTextCtrl_GetViewEOL, 3294). --define(wxStyledTextCtrl_SetViewEOL, 3295). --define(wxStyledTextCtrl_SetModEventMask, 3296). --define(wxStyledTextCtrl_GetEdgeColumn, 3297). --define(wxStyledTextCtrl_SetEdgeColumn, 3298). --define(wxStyledTextCtrl_SetEdgeMode, 3299). --define(wxStyledTextCtrl_GetEdgeMode, 3300). --define(wxStyledTextCtrl_GetEdgeColour, 3301). --define(wxStyledTextCtrl_SetEdgeColour, 3302). --define(wxStyledTextCtrl_SearchAnchor, 3303). --define(wxStyledTextCtrl_SearchNext, 3304). --define(wxStyledTextCtrl_SearchPrev, 3305). --define(wxStyledTextCtrl_LinesOnScreen, 3306). --define(wxStyledTextCtrl_UsePopUp, 3307). --define(wxStyledTextCtrl_SelectionIsRectangle, 3308). --define(wxStyledTextCtrl_SetZoom, 3309). --define(wxStyledTextCtrl_GetZoom, 3310). --define(wxStyledTextCtrl_GetModEventMask, 3311). --define(wxStyledTextCtrl_SetSTCFocus, 3312). --define(wxStyledTextCtrl_GetSTCFocus, 3313). --define(wxStyledTextCtrl_SetStatus, 3314). --define(wxStyledTextCtrl_GetStatus, 3315). --define(wxStyledTextCtrl_SetMouseDownCaptures, 3316). --define(wxStyledTextCtrl_GetMouseDownCaptures, 3317). --define(wxStyledTextCtrl_SetSTCCursor, 3318). --define(wxStyledTextCtrl_GetSTCCursor, 3319). --define(wxStyledTextCtrl_SetControlCharSymbol, 3320). --define(wxStyledTextCtrl_GetControlCharSymbol, 3321). --define(wxStyledTextCtrl_WordPartLeft, 3322). --define(wxStyledTextCtrl_WordPartLeftExtend, 3323). --define(wxStyledTextCtrl_WordPartRight, 3324). --define(wxStyledTextCtrl_WordPartRightExtend, 3325). --define(wxStyledTextCtrl_SetVisiblePolicy, 3326). --define(wxStyledTextCtrl_DelLineLeft, 3327). --define(wxStyledTextCtrl_DelLineRight, 3328). --define(wxStyledTextCtrl_GetXOffset, 3329). --define(wxStyledTextCtrl_ChooseCaretX, 3330). --define(wxStyledTextCtrl_SetXCaretPolicy, 3331). --define(wxStyledTextCtrl_SetYCaretPolicy, 3332). --define(wxStyledTextCtrl_GetPrintWrapMode, 3333). --define(wxStyledTextCtrl_SetHotspotActiveForeground, 3334). --define(wxStyledTextCtrl_SetHotspotActiveBackground, 3335). --define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3336). --define(wxStyledTextCtrl_SetHotspotSingleLine, 3337). --define(wxStyledTextCtrl_ParaDownExtend, 3338). --define(wxStyledTextCtrl_ParaUp, 3339). --define(wxStyledTextCtrl_ParaUpExtend, 3340). --define(wxStyledTextCtrl_PositionBefore, 3341). --define(wxStyledTextCtrl_PositionAfter, 3342). --define(wxStyledTextCtrl_CopyRange, 3343). --define(wxStyledTextCtrl_CopyText, 3344). --define(wxStyledTextCtrl_SetSelectionMode, 3345). --define(wxStyledTextCtrl_GetSelectionMode, 3346). --define(wxStyledTextCtrl_LineDownRectExtend, 3347). --define(wxStyledTextCtrl_LineUpRectExtend, 3348). --define(wxStyledTextCtrl_CharLeftRectExtend, 3349). --define(wxStyledTextCtrl_CharRightRectExtend, 3350). --define(wxStyledTextCtrl_HomeRectExtend, 3351). --define(wxStyledTextCtrl_VCHomeRectExtend, 3352). --define(wxStyledTextCtrl_LineEndRectExtend, 3353). --define(wxStyledTextCtrl_PageUpRectExtend, 3354). --define(wxStyledTextCtrl_PageDownRectExtend, 3355). --define(wxStyledTextCtrl_StutteredPageUp, 3356). --define(wxStyledTextCtrl_StutteredPageUpExtend, 3357). --define(wxStyledTextCtrl_StutteredPageDown, 3358). --define(wxStyledTextCtrl_StutteredPageDownExtend, 3359). --define(wxStyledTextCtrl_WordLeftEnd, 3360). --define(wxStyledTextCtrl_WordLeftEndExtend, 3361). --define(wxStyledTextCtrl_WordRightEnd, 3362). --define(wxStyledTextCtrl_WordRightEndExtend, 3363). --define(wxStyledTextCtrl_SetWhitespaceChars, 3364). --define(wxStyledTextCtrl_SetCharsDefault, 3365). --define(wxStyledTextCtrl_AutoCompGetCurrent, 3366). --define(wxStyledTextCtrl_Allocate, 3367). --define(wxStyledTextCtrl_FindColumn, 3368). --define(wxStyledTextCtrl_GetCaretSticky, 3369). --define(wxStyledTextCtrl_SetCaretSticky, 3370). --define(wxStyledTextCtrl_ToggleCaretSticky, 3371). --define(wxStyledTextCtrl_SetPasteConvertEndings, 3372). --define(wxStyledTextCtrl_GetPasteConvertEndings, 3373). --define(wxStyledTextCtrl_SelectionDuplicate, 3374). --define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3375). --define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3376). --define(wxStyledTextCtrl_StartRecord, 3377). --define(wxStyledTextCtrl_StopRecord, 3378). --define(wxStyledTextCtrl_SetLexer, 3379). --define(wxStyledTextCtrl_GetLexer, 3380). --define(wxStyledTextCtrl_Colourise, 3381). --define(wxStyledTextCtrl_SetProperty, 3382). --define(wxStyledTextCtrl_SetKeyWords, 3383). --define(wxStyledTextCtrl_SetLexerLanguage, 3384). --define(wxStyledTextCtrl_GetProperty, 3385). --define(wxStyledTextCtrl_GetStyleBitsNeeded, 3386). --define(wxStyledTextCtrl_GetCurrentLine, 3387). --define(wxStyledTextCtrl_StyleSetSpec, 3388). --define(wxStyledTextCtrl_StyleSetFont, 3389). --define(wxStyledTextCtrl_StyleSetFontAttr, 3390). --define(wxStyledTextCtrl_StyleSetCharacterSet, 3391). --define(wxStyledTextCtrl_StyleSetFontEncoding, 3392). --define(wxStyledTextCtrl_CmdKeyExecute, 3393). --define(wxStyledTextCtrl_SetMargins, 3394). --define(wxStyledTextCtrl_GetSelection, 3395). --define(wxStyledTextCtrl_PointFromPosition, 3396). --define(wxStyledTextCtrl_ScrollToLine, 3397). --define(wxStyledTextCtrl_ScrollToColumn, 3398). --define(wxStyledTextCtrl_SetVScrollBar, 3399). --define(wxStyledTextCtrl_SetHScrollBar, 3400). --define(wxStyledTextCtrl_GetLastKeydownProcessed, 3401). --define(wxStyledTextCtrl_SetLastKeydownProcessed, 3402). --define(wxStyledTextCtrl_SaveFile, 3403). --define(wxStyledTextCtrl_LoadFile, 3404). --define(wxStyledTextCtrl_DoDragOver, 3405). --define(wxStyledTextCtrl_DoDropText, 3406). --define(wxStyledTextCtrl_GetUseAntiAliasing, 3407). --define(wxStyledTextCtrl_AddTextRaw, 3408). --define(wxStyledTextCtrl_InsertTextRaw, 3409). --define(wxStyledTextCtrl_GetCurLineRaw, 3410). --define(wxStyledTextCtrl_GetLineRaw, 3411). --define(wxStyledTextCtrl_GetSelectedTextRaw, 3412). --define(wxStyledTextCtrl_GetTextRangeRaw, 3413). --define(wxStyledTextCtrl_SetTextRaw, 3414). --define(wxStyledTextCtrl_GetTextRaw, 3415). --define(wxStyledTextCtrl_AppendTextRaw, 3416). --define(wxArtProvider_GetBitmap, 3417). --define(wxArtProvider_GetIcon, 3418). --define(wxTreeEvent_GetKeyCode, 3419). --define(wxTreeEvent_GetItem, 3420). --define(wxTreeEvent_GetKeyEvent, 3421). --define(wxTreeEvent_GetLabel, 3422). --define(wxTreeEvent_GetOldItem, 3423). --define(wxTreeEvent_GetPoint, 3424). --define(wxTreeEvent_IsEditCancelled, 3425). --define(wxTreeEvent_SetToolTip, 3426). --define(wxNotebookEvent_GetOldSelection, 3427). --define(wxNotebookEvent_GetSelection, 3428). --define(wxNotebookEvent_SetOldSelection, 3429). --define(wxNotebookEvent_SetSelection, 3430). --define(wxFileDataObject_new, 3431). --define(wxFileDataObject_AddFile, 3432). --define(wxFileDataObject_GetFilenames, 3433). --define(wxFileDataObject_destroy, 3434). --define(wxTextDataObject_new, 3435). --define(wxTextDataObject_GetTextLength, 3436). --define(wxTextDataObject_GetText, 3437). --define(wxTextDataObject_SetText, 3438). --define(wxTextDataObject_destroy, 3439). --define(wxBitmapDataObject_new_1_1, 3440). --define(wxBitmapDataObject_new_1_0, 3441). --define(wxBitmapDataObject_GetBitmap, 3442). --define(wxBitmapDataObject_SetBitmap, 3443). --define(wxBitmapDataObject_destroy, 3444). --define(wxClipboard_new, 3446). --define(wxClipboard_destruct, 3447). --define(wxClipboard_AddData, 3448). --define(wxClipboard_Clear, 3449). --define(wxClipboard_Close, 3450). --define(wxClipboard_Flush, 3451). --define(wxClipboard_GetData, 3452). --define(wxClipboard_IsOpened, 3453). --define(wxClipboard_Open, 3454). --define(wxClipboard_SetData, 3455). --define(wxClipboard_UsePrimarySelection, 3457). --define(wxClipboard_IsSupported, 3458). --define(wxClipboard_Get, 3459). --define(wxSpinEvent_GetPosition, 3460). --define(wxSpinEvent_SetPosition, 3461). --define(wxSplitterWindow_new_0, 3462). --define(wxSplitterWindow_new_2, 3463). --define(wxSplitterWindow_destruct, 3464). --define(wxSplitterWindow_Create, 3465). --define(wxSplitterWindow_GetMinimumPaneSize, 3466). --define(wxSplitterWindow_GetSashGravity, 3467). --define(wxSplitterWindow_GetSashPosition, 3468). --define(wxSplitterWindow_GetSplitMode, 3469). --define(wxSplitterWindow_GetWindow1, 3470). --define(wxSplitterWindow_GetWindow2, 3471). --define(wxSplitterWindow_Initialize, 3472). --define(wxSplitterWindow_IsSplit, 3473). --define(wxSplitterWindow_ReplaceWindow, 3474). --define(wxSplitterWindow_SetSashGravity, 3475). --define(wxSplitterWindow_SetSashPosition, 3476). --define(wxSplitterWindow_SetSashSize, 3477). --define(wxSplitterWindow_SetMinimumPaneSize, 3478). --define(wxSplitterWindow_SetSplitMode, 3479). --define(wxSplitterWindow_SplitHorizontally, 3480). --define(wxSplitterWindow_SplitVertically, 3481). --define(wxSplitterWindow_Unsplit, 3482). --define(wxSplitterWindow_UpdateSize, 3483). --define(wxSplitterEvent_GetSashPosition, 3484). --define(wxSplitterEvent_GetX, 3485). --define(wxSplitterEvent_GetY, 3486). --define(wxSplitterEvent_GetWindowBeingRemoved, 3487). --define(wxSplitterEvent_SetSashPosition, 3488). --define(wxHtmlWindow_new_0, 3489). --define(wxHtmlWindow_new_2, 3490). --define(wxHtmlWindow_AppendToPage, 3491). --define(wxHtmlWindow_GetOpenedAnchor, 3492). --define(wxHtmlWindow_GetOpenedPage, 3493). --define(wxHtmlWindow_GetOpenedPageTitle, 3494). --define(wxHtmlWindow_GetRelatedFrame, 3495). --define(wxHtmlWindow_HistoryBack, 3496). --define(wxHtmlWindow_HistoryCanBack, 3497). --define(wxHtmlWindow_HistoryCanForward, 3498). --define(wxHtmlWindow_HistoryClear, 3499). --define(wxHtmlWindow_HistoryForward, 3500). --define(wxHtmlWindow_LoadFile, 3501). --define(wxHtmlWindow_LoadPage, 3502). --define(wxHtmlWindow_SelectAll, 3503). --define(wxHtmlWindow_SelectionToText, 3504). --define(wxHtmlWindow_SelectLine, 3505). --define(wxHtmlWindow_SelectWord, 3506). --define(wxHtmlWindow_SetBorders, 3507). --define(wxHtmlWindow_SetFonts, 3508). --define(wxHtmlWindow_SetPage, 3509). --define(wxHtmlWindow_SetRelatedFrame, 3510). --define(wxHtmlWindow_SetRelatedStatusBar, 3511). --define(wxHtmlWindow_ToText, 3512). --define(wxHtmlWindow_destroy, 3513). --define(wxHtmlLinkEvent_GetLinkInfo, 3514). --define(wxSystemSettings_GetColour, 3515). --define(wxSystemSettings_GetFont, 3516). --define(wxSystemSettings_GetMetric, 3517). --define(wxSystemSettings_GetScreenType, 3518). --define(wxSystemOptions_GetOption, 3519). --define(wxSystemOptions_GetOptionInt, 3520). --define(wxSystemOptions_HasOption, 3521). --define(wxSystemOptions_IsFalse, 3522). --define(wxSystemOptions_SetOption_2_1, 3523). --define(wxSystemOptions_SetOption_2_0, 3524). --define(wxAuiNotebookEvent_SetSelection, 3525). --define(wxAuiNotebookEvent_GetSelection, 3526). --define(wxAuiNotebookEvent_SetOldSelection, 3527). --define(wxAuiNotebookEvent_GetOldSelection, 3528). --define(wxAuiNotebookEvent_SetDragSource, 3529). --define(wxAuiNotebookEvent_GetDragSource, 3530). --define(wxAuiManagerEvent_SetManager, 3531). --define(wxAuiManagerEvent_GetManager, 3532). --define(wxAuiManagerEvent_SetPane, 3533). --define(wxAuiManagerEvent_GetPane, 3534). --define(wxAuiManagerEvent_SetButton, 3535). --define(wxAuiManagerEvent_GetButton, 3536). --define(wxAuiManagerEvent_SetDC, 3537). --define(wxAuiManagerEvent_GetDC, 3538). --define(wxAuiManagerEvent_Veto, 3539). --define(wxAuiManagerEvent_GetVeto, 3540). --define(wxAuiManagerEvent_SetCanVeto, 3541). --define(wxAuiManagerEvent_CanVeto, 3542). --define(wxLogNull_new, 3543). --define(wxLogNull_destroy, 3544). --define(wxTaskBarIcon_new, 3545). --define(wxTaskBarIcon_destruct, 3546). --define(wxTaskBarIcon_PopupMenu, 3547). --define(wxTaskBarIcon_RemoveIcon, 3548). --define(wxTaskBarIcon_SetIcon, 3549). --define(wxLocale_new_0, 3550). --define(wxLocale_new_2, 3552). --define(wxLocale_destruct, 3553). --define(wxLocale_Init, 3555). --define(wxLocale_AddCatalog_1, 3556). --define(wxLocale_AddCatalog_3, 3557). --define(wxLocale_AddCatalogLookupPathPrefix, 3558). --define(wxLocale_GetCanonicalName, 3559). --define(wxLocale_GetLanguage, 3560). --define(wxLocale_GetLanguageName, 3561). --define(wxLocale_GetLocale, 3562). --define(wxLocale_GetName, 3563). --define(wxLocale_GetString_2, 3564). --define(wxLocale_GetString_4, 3565). --define(wxLocale_GetHeaderValue, 3566). --define(wxLocale_GetSysName, 3567). --define(wxLocale_GetSystemEncoding, 3568). --define(wxLocale_GetSystemEncodingName, 3569). --define(wxLocale_GetSystemLanguage, 3570). --define(wxLocale_IsLoaded, 3571). --define(wxLocale_IsOk, 3572). --define(wxActivateEvent_GetActive, 3573). --define(wxPopupWindow_new_2, 3575). --define(wxPopupWindow_new_0, 3576). --define(wxPopupWindow_destruct, 3578). --define(wxPopupWindow_Create, 3579). --define(wxPopupWindow_Position, 3580). --define(wxPopupTransientWindow_new_0, 3581). --define(wxPopupTransientWindow_new_2, 3582). --define(wxPopupTransientWindow_destruct, 3583). --define(wxPopupTransientWindow_Popup, 3584). --define(wxPopupTransientWindow_Dismiss, 3585). --define(wxOverlay_new, 3586). --define(wxOverlay_destruct, 3587). --define(wxOverlay_Reset, 3588). --define(wxDCOverlay_new_6, 3589). --define(wxDCOverlay_new_2, 3590). --define(wxDCOverlay_destruct, 3591). --define(wxDCOverlay_Clear, 3592). +-define(wxToolBar_AddStretchableSpace, 984). +-define(wxToolBar_InsertStretchableSpace, 985). +-define(wxToolBar_DeleteTool, 986). +-define(wxToolBar_DeleteToolByPos, 987). +-define(wxToolBar_EnableTool, 988). +-define(wxToolBar_FindById, 989). +-define(wxToolBar_FindControl, 990). +-define(wxToolBar_FindToolForPosition, 991). +-define(wxToolBar_GetToolSize, 992). +-define(wxToolBar_GetToolBitmapSize, 993). +-define(wxToolBar_GetMargins, 994). +-define(wxToolBar_GetToolEnabled, 995). +-define(wxToolBar_GetToolLongHelp, 996). +-define(wxToolBar_GetToolPacking, 997). +-define(wxToolBar_GetToolPos, 998). +-define(wxToolBar_GetToolSeparation, 999). +-define(wxToolBar_GetToolShortHelp, 1000). +-define(wxToolBar_GetToolState, 1001). +-define(wxToolBar_InsertControl, 1002). +-define(wxToolBar_InsertSeparator, 1003). +-define(wxToolBar_InsertTool_5, 1004). +-define(wxToolBar_InsertTool_2, 1005). +-define(wxToolBar_InsertTool_4, 1006). +-define(wxToolBar_Realize, 1007). +-define(wxToolBar_RemoveTool, 1008). +-define(wxToolBar_SetMargins, 1009). +-define(wxToolBar_SetToolBitmapSize, 1010). +-define(wxToolBar_SetToolLongHelp, 1011). +-define(wxToolBar_SetToolPacking, 1012). +-define(wxToolBar_SetToolShortHelp, 1013). +-define(wxToolBar_SetToolSeparation, 1014). +-define(wxToolBar_ToggleTool, 1015). +-define(wxStatusBar_new_0, 1017). +-define(wxStatusBar_new_2, 1018). +-define(wxStatusBar_destruct, 1020). +-define(wxStatusBar_Create, 1021). +-define(wxStatusBar_GetFieldRect, 1022). +-define(wxStatusBar_GetFieldsCount, 1023). +-define(wxStatusBar_GetStatusText, 1024). +-define(wxStatusBar_PopStatusText, 1025). +-define(wxStatusBar_PushStatusText, 1026). +-define(wxStatusBar_SetFieldsCount, 1027). +-define(wxStatusBar_SetMinHeight, 1028). +-define(wxStatusBar_SetStatusText, 1029). +-define(wxStatusBar_SetStatusWidths, 1030). +-define(wxStatusBar_SetStatusStyles, 1031). +-define(wxBitmap_new_0, 1032). +-define(wxBitmap_new_3, 1033). +-define(wxBitmap_new_4, 1034). +-define(wxBitmap_new_2_0, 1035). +-define(wxBitmap_new_2_1, 1036). +-define(wxBitmap_destruct, 1037). +-define(wxBitmap_ConvertToImage, 1038). +-define(wxBitmap_CopyFromIcon, 1039). +-define(wxBitmap_Create, 1040). +-define(wxBitmap_GetDepth, 1041). +-define(wxBitmap_GetHeight, 1042). +-define(wxBitmap_GetPalette, 1043). +-define(wxBitmap_GetMask, 1044). +-define(wxBitmap_GetWidth, 1045). +-define(wxBitmap_GetSubBitmap, 1046). +-define(wxBitmap_LoadFile, 1047). +-define(wxBitmap_Ok, 1048). +-define(wxBitmap_SaveFile, 1049). +-define(wxBitmap_SetDepth, 1050). +-define(wxBitmap_SetHeight, 1051). +-define(wxBitmap_SetMask, 1052). +-define(wxBitmap_SetPalette, 1053). +-define(wxBitmap_SetWidth, 1054). +-define(wxIcon_new_0, 1055). +-define(wxIcon_new_2, 1056). +-define(wxIcon_new_1, 1057). +-define(wxIcon_CopyFromBitmap, 1058). +-define(wxIcon_destroy, 1059). +-define(wxIconBundle_new_0, 1060). +-define(wxIconBundle_new_2, 1061). +-define(wxIconBundle_new_1_0, 1062). +-define(wxIconBundle_new_1_1, 1063). +-define(wxIconBundle_destruct, 1064). +-define(wxIconBundle_AddIcon_2, 1065). +-define(wxIconBundle_AddIcon_1, 1066). +-define(wxIconBundle_GetIcon_1_1, 1067). +-define(wxIconBundle_GetIcon_1_0, 1068). +-define(wxCursor_new_0, 1069). +-define(wxCursor_new_1_0, 1070). +-define(wxCursor_new_1_1, 1071). +-define(wxCursor_new_4, 1072). +-define(wxCursor_destruct, 1073). +-define(wxCursor_Ok, 1074). +-define(wxMask_new_0, 1075). +-define(wxMask_new_2_1, 1076). +-define(wxMask_new_2_0, 1077). +-define(wxMask_new_1, 1078). +-define(wxMask_destruct, 1079). +-define(wxMask_Create_2_1, 1080). +-define(wxMask_Create_2_0, 1081). +-define(wxMask_Create_1, 1082). +-define(wxImage_new_0, 1083). +-define(wxImage_new_3_0, 1084). +-define(wxImage_new_4, 1085). +-define(wxImage_new_5, 1086). +-define(wxImage_new_2, 1087). +-define(wxImage_new_3_1, 1088). +-define(wxImage_Blur, 1089). +-define(wxImage_BlurHorizontal, 1090). +-define(wxImage_BlurVertical, 1091). +-define(wxImage_ConvertAlphaToMask, 1092). +-define(wxImage_ConvertToGreyscale, 1093). +-define(wxImage_ConvertToMono, 1094). +-define(wxImage_Copy, 1095). +-define(wxImage_Create_3, 1096). +-define(wxImage_Create_4, 1097). +-define(wxImage_Create_5, 1098). +-define(wxImage_Destroy, 1099). +-define(wxImage_FindFirstUnusedColour, 1100). +-define(wxImage_GetImageExtWildcard, 1101). +-define(wxImage_GetAlpha_2, 1102). +-define(wxImage_GetAlpha_0, 1103). +-define(wxImage_GetBlue, 1104). +-define(wxImage_GetData, 1105). +-define(wxImage_GetGreen, 1106). +-define(wxImage_GetImageCount, 1107). +-define(wxImage_GetHeight, 1108). +-define(wxImage_GetMaskBlue, 1109). +-define(wxImage_GetMaskGreen, 1110). +-define(wxImage_GetMaskRed, 1111). +-define(wxImage_GetOrFindMaskColour, 1112). +-define(wxImage_GetPalette, 1113). +-define(wxImage_GetRed, 1114). +-define(wxImage_GetSubImage, 1115). +-define(wxImage_GetWidth, 1116). +-define(wxImage_HasAlpha, 1117). +-define(wxImage_HasMask, 1118). +-define(wxImage_GetOption, 1119). +-define(wxImage_GetOptionInt, 1120). +-define(wxImage_HasOption, 1121). +-define(wxImage_InitAlpha, 1122). +-define(wxImage_InitStandardHandlers, 1123). +-define(wxImage_IsTransparent, 1124). +-define(wxImage_LoadFile_2, 1125). +-define(wxImage_LoadFile_3, 1126). +-define(wxImage_Ok, 1127). +-define(wxImage_RemoveHandler, 1128). +-define(wxImage_Mirror, 1129). +-define(wxImage_Replace, 1130). +-define(wxImage_Rescale, 1131). +-define(wxImage_Resize, 1132). +-define(wxImage_Rotate, 1133). +-define(wxImage_RotateHue, 1134). +-define(wxImage_Rotate90, 1135). +-define(wxImage_SaveFile_1, 1136). +-define(wxImage_SaveFile_2_0, 1137). +-define(wxImage_SaveFile_2_1, 1138). +-define(wxImage_Scale, 1139). +-define(wxImage_Size, 1140). +-define(wxImage_SetAlpha_3, 1141). +-define(wxImage_SetAlpha_2, 1142). +-define(wxImage_SetData_2, 1143). +-define(wxImage_SetData_4, 1144). +-define(wxImage_SetMask, 1145). +-define(wxImage_SetMaskColour, 1146). +-define(wxImage_SetMaskFromImage, 1147). +-define(wxImage_SetOption_2_1, 1148). +-define(wxImage_SetOption_2_0, 1149). +-define(wxImage_SetPalette, 1150). +-define(wxImage_SetRGB_5, 1151). +-define(wxImage_SetRGB_4, 1152). +-define(wxImage_destroy, 1153). +-define(wxBrush_new_0, 1154). +-define(wxBrush_new_2, 1155). +-define(wxBrush_new_1, 1156). +-define(wxBrush_destruct, 1158). +-define(wxBrush_GetColour, 1159). +-define(wxBrush_GetStipple, 1160). +-define(wxBrush_GetStyle, 1161). +-define(wxBrush_IsHatch, 1162). +-define(wxBrush_IsOk, 1163). +-define(wxBrush_SetColour_1, 1164). +-define(wxBrush_SetColour_3, 1165). +-define(wxBrush_SetStipple, 1166). +-define(wxBrush_SetStyle, 1167). +-define(wxPen_new_0, 1168). +-define(wxPen_new_2, 1169). +-define(wxPen_destruct, 1170). +-define(wxPen_GetCap, 1171). +-define(wxPen_GetColour, 1172). +-define(wxPen_GetJoin, 1173). +-define(wxPen_GetStyle, 1174). +-define(wxPen_GetWidth, 1175). +-define(wxPen_IsOk, 1176). +-define(wxPen_SetCap, 1177). +-define(wxPen_SetColour_1, 1178). +-define(wxPen_SetColour_3, 1179). +-define(wxPen_SetJoin, 1180). +-define(wxPen_SetStyle, 1181). +-define(wxPen_SetWidth, 1182). +-define(wxRegion_new_0, 1183). +-define(wxRegion_new_4, 1184). +-define(wxRegion_new_2, 1185). +-define(wxRegion_new_1_1, 1186). +-define(wxRegion_new_1_0, 1188). +-define(wxRegion_destruct, 1190). +-define(wxRegion_Clear, 1191). +-define(wxRegion_Contains_2, 1192). +-define(wxRegion_Contains_1_0, 1193). +-define(wxRegion_Contains_4, 1194). +-define(wxRegion_Contains_1_1, 1195). +-define(wxRegion_ConvertToBitmap, 1196). +-define(wxRegion_GetBox, 1197). +-define(wxRegion_Intersect_4, 1198). +-define(wxRegion_Intersect_1_1, 1199). +-define(wxRegion_Intersect_1_0, 1200). +-define(wxRegion_IsEmpty, 1201). +-define(wxRegion_Subtract_4, 1202). +-define(wxRegion_Subtract_1_1, 1203). +-define(wxRegion_Subtract_1_0, 1204). +-define(wxRegion_Offset_2, 1205). +-define(wxRegion_Offset_1, 1206). +-define(wxRegion_Union_4, 1207). +-define(wxRegion_Union_1_2, 1208). +-define(wxRegion_Union_1_1, 1209). +-define(wxRegion_Union_1_0, 1210). +-define(wxRegion_Union_3, 1211). +-define(wxRegion_Xor_4, 1212). +-define(wxRegion_Xor_1_1, 1213). +-define(wxRegion_Xor_1_0, 1214). +-define(wxAcceleratorTable_new_0, 1215). +-define(wxAcceleratorTable_new_2, 1216). +-define(wxAcceleratorTable_destruct, 1217). +-define(wxAcceleratorTable_Ok, 1218). +-define(wxAcceleratorEntry_new_1_0, 1219). +-define(wxAcceleratorEntry_new_1_1, 1220). +-define(wxAcceleratorEntry_GetCommand, 1221). +-define(wxAcceleratorEntry_GetFlags, 1222). +-define(wxAcceleratorEntry_GetKeyCode, 1223). +-define(wxAcceleratorEntry_Set, 1224). +-define(wxAcceleratorEntry_destroy, 1225). +-define(wxCaret_new_3, 1230). +-define(wxCaret_new_2, 1231). +-define(wxCaret_destruct, 1233). +-define(wxCaret_Create_3, 1234). +-define(wxCaret_Create_2, 1235). +-define(wxCaret_GetBlinkTime, 1236). +-define(wxCaret_GetPosition, 1238). +-define(wxCaret_GetSize, 1240). +-define(wxCaret_GetWindow, 1241). +-define(wxCaret_Hide, 1242). +-define(wxCaret_IsOk, 1243). +-define(wxCaret_IsVisible, 1244). +-define(wxCaret_Move_2, 1245). +-define(wxCaret_Move_1, 1246). +-define(wxCaret_SetBlinkTime, 1247). +-define(wxCaret_SetSize_2, 1248). +-define(wxCaret_SetSize_1, 1249). +-define(wxCaret_Show, 1250). +-define(wxSizer_Add_2_1, 1251). +-define(wxSizer_Add_2_0, 1252). +-define(wxSizer_Add_3, 1253). +-define(wxSizer_Add_2_3, 1254). +-define(wxSizer_Add_2_2, 1255). +-define(wxSizer_AddSpacer, 1256). +-define(wxSizer_AddStretchSpacer, 1257). +-define(wxSizer_CalcMin, 1258). +-define(wxSizer_Clear, 1259). +-define(wxSizer_Detach_1_2, 1260). +-define(wxSizer_Detach_1_1, 1261). +-define(wxSizer_Detach_1_0, 1262). +-define(wxSizer_Fit, 1263). +-define(wxSizer_FitInside, 1264). +-define(wxSizer_GetChildren, 1265). +-define(wxSizer_GetItem_2_1, 1266). +-define(wxSizer_GetItem_2_0, 1267). +-define(wxSizer_GetItem_1, 1268). +-define(wxSizer_GetSize, 1269). +-define(wxSizer_GetPosition, 1270). +-define(wxSizer_GetMinSize, 1271). +-define(wxSizer_Hide_2_0, 1272). +-define(wxSizer_Hide_2_1, 1273). +-define(wxSizer_Hide_1, 1274). +-define(wxSizer_Insert_3_1, 1275). +-define(wxSizer_Insert_3_0, 1276). +-define(wxSizer_Insert_4, 1277). +-define(wxSizer_Insert_3_3, 1278). +-define(wxSizer_Insert_3_2, 1279). +-define(wxSizer_Insert_2, 1280). +-define(wxSizer_InsertSpacer, 1281). +-define(wxSizer_InsertStretchSpacer, 1282). +-define(wxSizer_IsShown_1_2, 1283). +-define(wxSizer_IsShown_1_1, 1284). +-define(wxSizer_IsShown_1_0, 1285). +-define(wxSizer_Layout, 1286). +-define(wxSizer_Prepend_2_1, 1287). +-define(wxSizer_Prepend_2_0, 1288). +-define(wxSizer_Prepend_3, 1289). +-define(wxSizer_Prepend_2_3, 1290). +-define(wxSizer_Prepend_2_2, 1291). +-define(wxSizer_Prepend_1, 1292). +-define(wxSizer_PrependSpacer, 1293). +-define(wxSizer_PrependStretchSpacer, 1294). +-define(wxSizer_RecalcSizes, 1295). +-define(wxSizer_Remove_1_1, 1296). +-define(wxSizer_Remove_1_0, 1297). +-define(wxSizer_Replace_3_1, 1298). +-define(wxSizer_Replace_3_0, 1299). +-define(wxSizer_Replace_2, 1300). +-define(wxSizer_SetDimension, 1301). +-define(wxSizer_SetMinSize_2, 1302). +-define(wxSizer_SetMinSize_1, 1303). +-define(wxSizer_SetItemMinSize_3_2, 1304). +-define(wxSizer_SetItemMinSize_2_2, 1305). +-define(wxSizer_SetItemMinSize_3_1, 1306). +-define(wxSizer_SetItemMinSize_2_1, 1307). +-define(wxSizer_SetItemMinSize_3_0, 1308). +-define(wxSizer_SetItemMinSize_2_0, 1309). +-define(wxSizer_SetSizeHints, 1310). +-define(wxSizer_SetVirtualSizeHints, 1311). +-define(wxSizer_Show_2_2, 1312). +-define(wxSizer_Show_2_1, 1313). +-define(wxSizer_Show_2_0, 1314). +-define(wxSizer_Show_1, 1315). +-define(wxSizerFlags_new, 1316). +-define(wxSizerFlags_Align, 1317). +-define(wxSizerFlags_Border_2, 1318). +-define(wxSizerFlags_Border_1, 1319). +-define(wxSizerFlags_Center, 1320). +-define(wxSizerFlags_Centre, 1321). +-define(wxSizerFlags_Expand, 1322). +-define(wxSizerFlags_Left, 1323). +-define(wxSizerFlags_Proportion, 1324). +-define(wxSizerFlags_Right, 1325). +-define(wxSizerFlags_destroy, 1326). +-define(wxSizerItem_new_5_1, 1327). +-define(wxSizerItem_new_2_1, 1328). +-define(wxSizerItem_new_5_0, 1329). +-define(wxSizerItem_new_2_0, 1330). +-define(wxSizerItem_new_6, 1331). +-define(wxSizerItem_new_3, 1332). +-define(wxSizerItem_new_0, 1333). +-define(wxSizerItem_destruct, 1334). +-define(wxSizerItem_CalcMin, 1335). +-define(wxSizerItem_DeleteWindows, 1336). +-define(wxSizerItem_DetachSizer, 1337). +-define(wxSizerItem_GetBorder, 1338). +-define(wxSizerItem_GetFlag, 1339). +-define(wxSizerItem_GetMinSize, 1340). +-define(wxSizerItem_GetPosition, 1341). +-define(wxSizerItem_GetProportion, 1342). +-define(wxSizerItem_GetRatio, 1343). +-define(wxSizerItem_GetRect, 1344). +-define(wxSizerItem_GetSize, 1345). +-define(wxSizerItem_GetSizer, 1346). +-define(wxSizerItem_GetSpacer, 1347). +-define(wxSizerItem_GetUserData, 1348). +-define(wxSizerItem_GetWindow, 1349). +-define(wxSizerItem_IsSizer, 1350). +-define(wxSizerItem_IsShown, 1351). +-define(wxSizerItem_IsSpacer, 1352). +-define(wxSizerItem_IsWindow, 1353). +-define(wxSizerItem_SetBorder, 1354). +-define(wxSizerItem_SetDimension, 1355). +-define(wxSizerItem_SetFlag, 1356). +-define(wxSizerItem_SetInitSize, 1357). +-define(wxSizerItem_SetMinSize_1, 1358). +-define(wxSizerItem_SetMinSize_2, 1359). +-define(wxSizerItem_SetProportion, 1360). +-define(wxSizerItem_SetRatio_2, 1361). +-define(wxSizerItem_SetRatio_1_1, 1362). +-define(wxSizerItem_SetRatio_1_0, 1363). +-define(wxSizerItem_SetSizer, 1364). +-define(wxSizerItem_SetSpacer_1, 1365). +-define(wxSizerItem_SetSpacer_2, 1366). +-define(wxSizerItem_SetWindow, 1367). +-define(wxSizerItem_Show, 1368). +-define(wxBoxSizer_new, 1369). +-define(wxBoxSizer_GetOrientation, 1370). +-define(wxBoxSizer_destroy, 1371). +-define(wxStaticBoxSizer_new_2, 1372). +-define(wxStaticBoxSizer_new_3, 1373). +-define(wxStaticBoxSizer_GetStaticBox, 1374). +-define(wxStaticBoxSizer_destroy, 1375). +-define(wxGridSizer_new_4, 1376). +-define(wxGridSizer_new_2, 1377). +-define(wxGridSizer_GetCols, 1378). +-define(wxGridSizer_GetHGap, 1379). +-define(wxGridSizer_GetRows, 1380). +-define(wxGridSizer_GetVGap, 1381). +-define(wxGridSizer_SetCols, 1382). +-define(wxGridSizer_SetHGap, 1383). +-define(wxGridSizer_SetRows, 1384). +-define(wxGridSizer_SetVGap, 1385). +-define(wxGridSizer_destroy, 1386). +-define(wxFlexGridSizer_new_4, 1387). +-define(wxFlexGridSizer_new_2, 1388). +-define(wxFlexGridSizer_AddGrowableCol, 1389). +-define(wxFlexGridSizer_AddGrowableRow, 1390). +-define(wxFlexGridSizer_GetFlexibleDirection, 1391). +-define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1392). +-define(wxFlexGridSizer_RemoveGrowableCol, 1393). +-define(wxFlexGridSizer_RemoveGrowableRow, 1394). +-define(wxFlexGridSizer_SetFlexibleDirection, 1395). +-define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1396). +-define(wxFlexGridSizer_destroy, 1397). +-define(wxGridBagSizer_new, 1398). +-define(wxGridBagSizer_Add_3_2, 1399). +-define(wxGridBagSizer_Add_3_1, 1400). +-define(wxGridBagSizer_Add_4, 1401). +-define(wxGridBagSizer_Add_1_0, 1402). +-define(wxGridBagSizer_Add_2_1, 1403). +-define(wxGridBagSizer_Add_2_0, 1404). +-define(wxGridBagSizer_Add_3_0, 1405). +-define(wxGridBagSizer_Add_1_1, 1406). +-define(wxGridBagSizer_CalcMin, 1407). +-define(wxGridBagSizer_CheckForIntersection_2, 1408). +-define(wxGridBagSizer_CheckForIntersection_3, 1409). +-define(wxGridBagSizer_FindItem_1_1, 1410). +-define(wxGridBagSizer_FindItem_1_0, 1411). +-define(wxGridBagSizer_FindItemAtPoint, 1412). +-define(wxGridBagSizer_FindItemAtPosition, 1413). +-define(wxGridBagSizer_FindItemWithData, 1414). +-define(wxGridBagSizer_GetCellSize, 1415). +-define(wxGridBagSizer_GetEmptyCellSize, 1416). +-define(wxGridBagSizer_GetItemPosition_1_2, 1417). +-define(wxGridBagSizer_GetItemPosition_1_1, 1418). +-define(wxGridBagSizer_GetItemPosition_1_0, 1419). +-define(wxGridBagSizer_GetItemSpan_1_2, 1420). +-define(wxGridBagSizer_GetItemSpan_1_1, 1421). +-define(wxGridBagSizer_GetItemSpan_1_0, 1422). +-define(wxGridBagSizer_SetEmptyCellSize, 1423). +-define(wxGridBagSizer_SetItemPosition_2_2, 1424). +-define(wxGridBagSizer_SetItemPosition_2_1, 1425). +-define(wxGridBagSizer_SetItemPosition_2_0, 1426). +-define(wxGridBagSizer_SetItemSpan_2_2, 1427). +-define(wxGridBagSizer_SetItemSpan_2_1, 1428). +-define(wxGridBagSizer_SetItemSpan_2_0, 1429). +-define(wxGridBagSizer_destroy, 1430). +-define(wxStdDialogButtonSizer_new, 1431). +-define(wxStdDialogButtonSizer_AddButton, 1432). +-define(wxStdDialogButtonSizer_Realize, 1433). +-define(wxStdDialogButtonSizer_SetAffirmativeButton, 1434). +-define(wxStdDialogButtonSizer_SetCancelButton, 1435). +-define(wxStdDialogButtonSizer_SetNegativeButton, 1436). +-define(wxStdDialogButtonSizer_destroy, 1437). +-define(wxFont_new_0, 1438). +-define(wxFont_new_1, 1439). +-define(wxFont_new_5, 1440). +-define(wxFont_destruct, 1442). +-define(wxFont_IsFixedWidth, 1443). +-define(wxFont_GetDefaultEncoding, 1444). +-define(wxFont_GetFaceName, 1445). +-define(wxFont_GetFamily, 1446). +-define(wxFont_GetNativeFontInfoDesc, 1447). +-define(wxFont_GetNativeFontInfoUserDesc, 1448). +-define(wxFont_GetPointSize, 1449). +-define(wxFont_GetStyle, 1450). +-define(wxFont_GetUnderlined, 1451). +-define(wxFont_GetWeight, 1452). +-define(wxFont_Ok, 1453). +-define(wxFont_SetDefaultEncoding, 1454). +-define(wxFont_SetFaceName, 1455). +-define(wxFont_SetFamily, 1456). +-define(wxFont_SetPointSize, 1457). +-define(wxFont_SetStyle, 1458). +-define(wxFont_SetUnderlined, 1459). +-define(wxFont_SetWeight, 1460). +-define(wxToolTip_Enable, 1461). +-define(wxToolTip_SetDelay, 1462). +-define(wxToolTip_new, 1463). +-define(wxToolTip_SetTip, 1464). +-define(wxToolTip_GetTip, 1465). +-define(wxToolTip_GetWindow, 1466). +-define(wxToolTip_destroy, 1467). +-define(wxButton_new_3, 1469). +-define(wxButton_new_0, 1470). +-define(wxButton_destruct, 1471). +-define(wxButton_Create, 1472). +-define(wxButton_GetDefaultSize, 1473). +-define(wxButton_SetDefault, 1474). +-define(wxButton_SetLabel, 1475). +-define(wxBitmapButton_new_4, 1477). +-define(wxBitmapButton_new_0, 1478). +-define(wxBitmapButton_Create, 1479). +-define(wxBitmapButton_GetBitmapDisabled, 1480). +-define(wxBitmapButton_GetBitmapFocus, 1482). +-define(wxBitmapButton_GetBitmapLabel, 1484). +-define(wxBitmapButton_GetBitmapSelected, 1486). +-define(wxBitmapButton_SetBitmapDisabled, 1488). +-define(wxBitmapButton_SetBitmapFocus, 1489). +-define(wxBitmapButton_SetBitmapLabel, 1490). +-define(wxBitmapButton_SetBitmapSelected, 1491). +-define(wxBitmapButton_destroy, 1492). +-define(wxToggleButton_new_0, 1493). +-define(wxToggleButton_new_4, 1494). +-define(wxToggleButton_Create, 1495). +-define(wxToggleButton_GetValue, 1496). +-define(wxToggleButton_SetValue, 1497). +-define(wxToggleButton_destroy, 1498). +-define(wxCalendarCtrl_new_0, 1499). +-define(wxCalendarCtrl_new_3, 1500). +-define(wxCalendarCtrl_Create, 1501). +-define(wxCalendarCtrl_destruct, 1502). +-define(wxCalendarCtrl_SetDate, 1503). +-define(wxCalendarCtrl_GetDate, 1504). +-define(wxCalendarCtrl_EnableYearChange, 1505). +-define(wxCalendarCtrl_EnableMonthChange, 1506). +-define(wxCalendarCtrl_EnableHolidayDisplay, 1507). +-define(wxCalendarCtrl_SetHeaderColours, 1508). +-define(wxCalendarCtrl_GetHeaderColourFg, 1509). +-define(wxCalendarCtrl_GetHeaderColourBg, 1510). +-define(wxCalendarCtrl_SetHighlightColours, 1511). +-define(wxCalendarCtrl_GetHighlightColourFg, 1512). +-define(wxCalendarCtrl_GetHighlightColourBg, 1513). +-define(wxCalendarCtrl_SetHolidayColours, 1514). +-define(wxCalendarCtrl_GetHolidayColourFg, 1515). +-define(wxCalendarCtrl_GetHolidayColourBg, 1516). +-define(wxCalendarCtrl_GetAttr, 1517). +-define(wxCalendarCtrl_SetAttr, 1518). +-define(wxCalendarCtrl_SetHoliday, 1519). +-define(wxCalendarCtrl_ResetAttr, 1520). +-define(wxCalendarCtrl_HitTest, 1521). +-define(wxCalendarDateAttr_new_0, 1522). +-define(wxCalendarDateAttr_new_2_1, 1523). +-define(wxCalendarDateAttr_new_2_0, 1524). +-define(wxCalendarDateAttr_SetTextColour, 1525). +-define(wxCalendarDateAttr_SetBackgroundColour, 1526). +-define(wxCalendarDateAttr_SetBorderColour, 1527). +-define(wxCalendarDateAttr_SetFont, 1528). +-define(wxCalendarDateAttr_SetBorder, 1529). +-define(wxCalendarDateAttr_SetHoliday, 1530). +-define(wxCalendarDateAttr_HasTextColour, 1531). +-define(wxCalendarDateAttr_HasBackgroundColour, 1532). +-define(wxCalendarDateAttr_HasBorderColour, 1533). +-define(wxCalendarDateAttr_HasFont, 1534). +-define(wxCalendarDateAttr_HasBorder, 1535). +-define(wxCalendarDateAttr_IsHoliday, 1536). +-define(wxCalendarDateAttr_GetTextColour, 1537). +-define(wxCalendarDateAttr_GetBackgroundColour, 1538). +-define(wxCalendarDateAttr_GetBorderColour, 1539). +-define(wxCalendarDateAttr_GetFont, 1540). +-define(wxCalendarDateAttr_GetBorder, 1541). +-define(wxCalendarDateAttr_destroy, 1542). +-define(wxCheckBox_new_4, 1544). +-define(wxCheckBox_new_0, 1545). +-define(wxCheckBox_Create, 1546). +-define(wxCheckBox_GetValue, 1547). +-define(wxCheckBox_Get3StateValue, 1548). +-define(wxCheckBox_Is3rdStateAllowedForUser, 1549). +-define(wxCheckBox_Is3State, 1550). +-define(wxCheckBox_IsChecked, 1551). +-define(wxCheckBox_SetValue, 1552). +-define(wxCheckBox_Set3StateValue, 1553). +-define(wxCheckBox_destroy, 1554). +-define(wxCheckListBox_new_0, 1555). +-define(wxCheckListBox_new_3, 1557). +-define(wxCheckListBox_Check, 1558). +-define(wxCheckListBox_IsChecked, 1559). +-define(wxCheckListBox_destroy, 1560). +-define(wxChoice_new_3, 1563). +-define(wxChoice_new_0, 1564). +-define(wxChoice_destruct, 1566). +-define(wxChoice_Create, 1568). +-define(wxChoice_Delete, 1569). +-define(wxChoice_GetColumns, 1570). +-define(wxChoice_SetColumns, 1571). +-define(wxComboBox_new_0, 1572). +-define(wxComboBox_new_3, 1574). +-define(wxComboBox_destruct, 1575). +-define(wxComboBox_Create, 1577). +-define(wxComboBox_CanCopy, 1578). +-define(wxComboBox_CanCut, 1579). +-define(wxComboBox_CanPaste, 1580). +-define(wxComboBox_CanRedo, 1581). +-define(wxComboBox_CanUndo, 1582). +-define(wxComboBox_Copy, 1583). +-define(wxComboBox_Cut, 1584). +-define(wxComboBox_GetInsertionPoint, 1585). +-define(wxComboBox_GetLastPosition, 1586). +-define(wxComboBox_GetValue, 1587). +-define(wxComboBox_Paste, 1588). +-define(wxComboBox_Redo, 1589). +-define(wxComboBox_Replace, 1590). +-define(wxComboBox_Remove, 1591). +-define(wxComboBox_SetInsertionPoint, 1592). +-define(wxComboBox_SetInsertionPointEnd, 1593). +-define(wxComboBox_SetSelection_1, 1594). +-define(wxComboBox_SetSelection_2, 1595). +-define(wxComboBox_SetValue, 1596). +-define(wxComboBox_Undo, 1597). +-define(wxGauge_new_0, 1598). +-define(wxGauge_new_4, 1599). +-define(wxGauge_Create, 1600). +-define(wxGauge_GetBezelFace, 1601). +-define(wxGauge_GetRange, 1602). +-define(wxGauge_GetShadowWidth, 1603). +-define(wxGauge_GetValue, 1604). +-define(wxGauge_IsVertical, 1605). +-define(wxGauge_SetBezelFace, 1606). +-define(wxGauge_SetRange, 1607). +-define(wxGauge_SetShadowWidth, 1608). +-define(wxGauge_SetValue, 1609). +-define(wxGauge_Pulse, 1610). +-define(wxGauge_destroy, 1611). +-define(wxGenericDirCtrl_new_0, 1612). +-define(wxGenericDirCtrl_new_2, 1613). +-define(wxGenericDirCtrl_destruct, 1614). +-define(wxGenericDirCtrl_Create, 1615). +-define(wxGenericDirCtrl_Init, 1616). +-define(wxGenericDirCtrl_CollapseTree, 1617). +-define(wxGenericDirCtrl_ExpandPath, 1618). +-define(wxGenericDirCtrl_GetDefaultPath, 1619). +-define(wxGenericDirCtrl_GetPath, 1620). +-define(wxGenericDirCtrl_GetFilePath, 1621). +-define(wxGenericDirCtrl_GetFilter, 1622). +-define(wxGenericDirCtrl_GetFilterIndex, 1623). +-define(wxGenericDirCtrl_GetRootId, 1624). +-define(wxGenericDirCtrl_GetTreeCtrl, 1625). +-define(wxGenericDirCtrl_ReCreateTree, 1626). +-define(wxGenericDirCtrl_SetDefaultPath, 1627). +-define(wxGenericDirCtrl_SetFilter, 1628). +-define(wxGenericDirCtrl_SetFilterIndex, 1629). +-define(wxGenericDirCtrl_SetPath, 1630). +-define(wxStaticBox_new_4, 1632). +-define(wxStaticBox_new_0, 1633). +-define(wxStaticBox_Create, 1634). +-define(wxStaticBox_destroy, 1635). +-define(wxStaticLine_new_2, 1637). +-define(wxStaticLine_new_0, 1638). +-define(wxStaticLine_Create, 1639). +-define(wxStaticLine_IsVertical, 1640). +-define(wxStaticLine_GetDefaultSize, 1641). +-define(wxStaticLine_destroy, 1642). +-define(wxListBox_new_3, 1645). +-define(wxListBox_new_0, 1646). +-define(wxListBox_destruct, 1648). +-define(wxListBox_Create, 1650). +-define(wxListBox_Deselect, 1651). +-define(wxListBox_GetSelections, 1652). +-define(wxListBox_InsertItems, 1653). +-define(wxListBox_IsSelected, 1654). +-define(wxListBox_Set, 1655). +-define(wxListBox_HitTest, 1656). +-define(wxListBox_SetFirstItem_1_0, 1657). +-define(wxListBox_SetFirstItem_1_1, 1658). +-define(wxListCtrl_new_0, 1659). +-define(wxListCtrl_new_2, 1660). +-define(wxListCtrl_Arrange, 1661). +-define(wxListCtrl_AssignImageList, 1662). +-define(wxListCtrl_ClearAll, 1663). +-define(wxListCtrl_Create, 1664). +-define(wxListCtrl_DeleteAllItems, 1665). +-define(wxListCtrl_DeleteColumn, 1666). +-define(wxListCtrl_DeleteItem, 1667). +-define(wxListCtrl_EditLabel, 1668). +-define(wxListCtrl_EnsureVisible, 1669). +-define(wxListCtrl_FindItem_3_0, 1670). +-define(wxListCtrl_FindItem_3_1, 1671). +-define(wxListCtrl_GetColumn, 1672). +-define(wxListCtrl_GetColumnCount, 1673). +-define(wxListCtrl_GetColumnWidth, 1674). +-define(wxListCtrl_GetCountPerPage, 1675). +-define(wxListCtrl_GetEditControl, 1676). +-define(wxListCtrl_GetImageList, 1677). +-define(wxListCtrl_GetItem, 1678). +-define(wxListCtrl_GetItemBackgroundColour, 1679). +-define(wxListCtrl_GetItemCount, 1680). +-define(wxListCtrl_GetItemData, 1681). +-define(wxListCtrl_GetItemFont, 1682). +-define(wxListCtrl_GetItemPosition, 1683). +-define(wxListCtrl_GetItemRect, 1684). +-define(wxListCtrl_GetItemSpacing, 1685). +-define(wxListCtrl_GetItemState, 1686). +-define(wxListCtrl_GetItemText, 1687). +-define(wxListCtrl_GetItemTextColour, 1688). +-define(wxListCtrl_GetNextItem, 1689). +-define(wxListCtrl_GetSelectedItemCount, 1690). +-define(wxListCtrl_GetTextColour, 1691). +-define(wxListCtrl_GetTopItem, 1692). +-define(wxListCtrl_GetViewRect, 1693). +-define(wxListCtrl_HitTest, 1694). +-define(wxListCtrl_InsertColumn_2, 1695). +-define(wxListCtrl_InsertColumn_3, 1696). +-define(wxListCtrl_InsertItem_1, 1697). +-define(wxListCtrl_InsertItem_2_1, 1698). +-define(wxListCtrl_InsertItem_2_0, 1699). +-define(wxListCtrl_InsertItem_3, 1700). +-define(wxListCtrl_RefreshItem, 1701). +-define(wxListCtrl_RefreshItems, 1702). +-define(wxListCtrl_ScrollList, 1703). +-define(wxListCtrl_SetBackgroundColour, 1704). +-define(wxListCtrl_SetColumn, 1705). +-define(wxListCtrl_SetColumnWidth, 1706). +-define(wxListCtrl_SetImageList, 1707). +-define(wxListCtrl_SetItem_1, 1708). +-define(wxListCtrl_SetItem_4, 1709). +-define(wxListCtrl_SetItemBackgroundColour, 1710). +-define(wxListCtrl_SetItemCount, 1711). +-define(wxListCtrl_SetItemData, 1712). +-define(wxListCtrl_SetItemFont, 1713). +-define(wxListCtrl_SetItemImage, 1714). +-define(wxListCtrl_SetItemColumnImage, 1715). +-define(wxListCtrl_SetItemPosition, 1716). +-define(wxListCtrl_SetItemState, 1717). +-define(wxListCtrl_SetItemText, 1718). +-define(wxListCtrl_SetItemTextColour, 1719). +-define(wxListCtrl_SetSingleStyle, 1720). +-define(wxListCtrl_SetTextColour, 1721). +-define(wxListCtrl_SetWindowStyleFlag, 1722). +-define(wxListCtrl_SortItems, 1723). +-define(wxListCtrl_destroy, 1724). +-define(wxListView_ClearColumnImage, 1725). +-define(wxListView_Focus, 1726). +-define(wxListView_GetFirstSelected, 1727). +-define(wxListView_GetFocusedItem, 1728). +-define(wxListView_GetNextSelected, 1729). +-define(wxListView_IsSelected, 1730). +-define(wxListView_Select, 1731). +-define(wxListView_SetColumnImage, 1732). +-define(wxListItem_new_0, 1733). +-define(wxListItem_new_1, 1734). +-define(wxListItem_destruct, 1735). +-define(wxListItem_Clear, 1736). +-define(wxListItem_GetAlign, 1737). +-define(wxListItem_GetBackgroundColour, 1738). +-define(wxListItem_GetColumn, 1739). +-define(wxListItem_GetFont, 1740). +-define(wxListItem_GetId, 1741). +-define(wxListItem_GetImage, 1742). +-define(wxListItem_GetMask, 1743). +-define(wxListItem_GetState, 1744). +-define(wxListItem_GetText, 1745). +-define(wxListItem_GetTextColour, 1746). +-define(wxListItem_GetWidth, 1747). +-define(wxListItem_SetAlign, 1748). +-define(wxListItem_SetBackgroundColour, 1749). +-define(wxListItem_SetColumn, 1750). +-define(wxListItem_SetFont, 1751). +-define(wxListItem_SetId, 1752). +-define(wxListItem_SetImage, 1753). +-define(wxListItem_SetMask, 1754). +-define(wxListItem_SetState, 1755). +-define(wxListItem_SetStateMask, 1756). +-define(wxListItem_SetText, 1757). +-define(wxListItem_SetTextColour, 1758). +-define(wxListItem_SetWidth, 1759). +-define(wxListItemAttr_new_0, 1760). +-define(wxListItemAttr_new_3, 1761). +-define(wxListItemAttr_GetBackgroundColour, 1762). +-define(wxListItemAttr_GetFont, 1763). +-define(wxListItemAttr_GetTextColour, 1764). +-define(wxListItemAttr_HasBackgroundColour, 1765). +-define(wxListItemAttr_HasFont, 1766). +-define(wxListItemAttr_HasTextColour, 1767). +-define(wxListItemAttr_SetBackgroundColour, 1768). +-define(wxListItemAttr_SetFont, 1769). +-define(wxListItemAttr_SetTextColour, 1770). +-define(wxListItemAttr_destroy, 1771). +-define(wxImageList_new_0, 1772). +-define(wxImageList_new_3, 1773). +-define(wxImageList_Add_1, 1774). +-define(wxImageList_Add_2_0, 1775). +-define(wxImageList_Add_2_1, 1776). +-define(wxImageList_Create, 1777). +-define(wxImageList_Draw, 1779). +-define(wxImageList_GetBitmap, 1780). +-define(wxImageList_GetIcon, 1781). +-define(wxImageList_GetImageCount, 1782). +-define(wxImageList_GetSize, 1783). +-define(wxImageList_Remove, 1784). +-define(wxImageList_RemoveAll, 1785). +-define(wxImageList_Replace_2, 1786). +-define(wxImageList_Replace_3, 1787). +-define(wxImageList_destroy, 1788). +-define(wxTextAttr_new_0, 1789). +-define(wxTextAttr_new_2, 1790). +-define(wxTextAttr_GetAlignment, 1791). +-define(wxTextAttr_GetBackgroundColour, 1792). +-define(wxTextAttr_GetFont, 1793). +-define(wxTextAttr_GetLeftIndent, 1794). +-define(wxTextAttr_GetLeftSubIndent, 1795). +-define(wxTextAttr_GetRightIndent, 1796). +-define(wxTextAttr_GetTabs, 1797). +-define(wxTextAttr_GetTextColour, 1798). +-define(wxTextAttr_HasBackgroundColour, 1799). +-define(wxTextAttr_HasFont, 1800). +-define(wxTextAttr_HasTextColour, 1801). +-define(wxTextAttr_GetFlags, 1802). +-define(wxTextAttr_IsDefault, 1803). +-define(wxTextAttr_SetAlignment, 1804). +-define(wxTextAttr_SetBackgroundColour, 1805). +-define(wxTextAttr_SetFlags, 1806). +-define(wxTextAttr_SetFont, 1807). +-define(wxTextAttr_SetLeftIndent, 1808). +-define(wxTextAttr_SetRightIndent, 1809). +-define(wxTextAttr_SetTabs, 1810). +-define(wxTextAttr_SetTextColour, 1811). +-define(wxTextAttr_destroy, 1812). +-define(wxTextCtrl_new_3, 1814). +-define(wxTextCtrl_new_0, 1815). +-define(wxTextCtrl_destruct, 1817). +-define(wxTextCtrl_AppendText, 1818). +-define(wxTextCtrl_CanCopy, 1819). +-define(wxTextCtrl_CanCut, 1820). +-define(wxTextCtrl_CanPaste, 1821). +-define(wxTextCtrl_CanRedo, 1822). +-define(wxTextCtrl_CanUndo, 1823). +-define(wxTextCtrl_Clear, 1824). +-define(wxTextCtrl_Copy, 1825). +-define(wxTextCtrl_Create, 1826). +-define(wxTextCtrl_Cut, 1827). +-define(wxTextCtrl_DiscardEdits, 1828). +-define(wxTextCtrl_ChangeValue, 1829). +-define(wxTextCtrl_EmulateKeyPress, 1830). +-define(wxTextCtrl_GetDefaultStyle, 1831). +-define(wxTextCtrl_GetInsertionPoint, 1832). +-define(wxTextCtrl_GetLastPosition, 1833). +-define(wxTextCtrl_GetLineLength, 1834). +-define(wxTextCtrl_GetLineText, 1835). +-define(wxTextCtrl_GetNumberOfLines, 1836). +-define(wxTextCtrl_GetRange, 1837). +-define(wxTextCtrl_GetSelection, 1838). +-define(wxTextCtrl_GetStringSelection, 1839). +-define(wxTextCtrl_GetStyle, 1840). +-define(wxTextCtrl_GetValue, 1841). +-define(wxTextCtrl_IsEditable, 1842). +-define(wxTextCtrl_IsModified, 1843). +-define(wxTextCtrl_IsMultiLine, 1844). +-define(wxTextCtrl_IsSingleLine, 1845). +-define(wxTextCtrl_LoadFile, 1846). +-define(wxTextCtrl_MarkDirty, 1847). +-define(wxTextCtrl_Paste, 1848). +-define(wxTextCtrl_PositionToXY, 1849). +-define(wxTextCtrl_Redo, 1850). +-define(wxTextCtrl_Remove, 1851). +-define(wxTextCtrl_Replace, 1852). +-define(wxTextCtrl_SaveFile, 1853). +-define(wxTextCtrl_SetDefaultStyle, 1854). +-define(wxTextCtrl_SetEditable, 1855). +-define(wxTextCtrl_SetInsertionPoint, 1856). +-define(wxTextCtrl_SetInsertionPointEnd, 1857). +-define(wxTextCtrl_SetMaxLength, 1859). +-define(wxTextCtrl_SetSelection, 1860). +-define(wxTextCtrl_SetStyle, 1861). +-define(wxTextCtrl_SetValue, 1862). +-define(wxTextCtrl_ShowPosition, 1863). +-define(wxTextCtrl_Undo, 1864). +-define(wxTextCtrl_WriteText, 1865). +-define(wxTextCtrl_XYToPosition, 1866). +-define(wxNotebook_new_0, 1869). +-define(wxNotebook_new_3, 1870). +-define(wxNotebook_destruct, 1871). +-define(wxNotebook_AddPage, 1872). +-define(wxNotebook_AdvanceSelection, 1873). +-define(wxNotebook_AssignImageList, 1874). +-define(wxNotebook_Create, 1875). +-define(wxNotebook_DeleteAllPages, 1876). +-define(wxNotebook_DeletePage, 1877). +-define(wxNotebook_RemovePage, 1878). +-define(wxNotebook_GetCurrentPage, 1879). +-define(wxNotebook_GetImageList, 1880). +-define(wxNotebook_GetPage, 1882). +-define(wxNotebook_GetPageCount, 1883). +-define(wxNotebook_GetPageImage, 1884). +-define(wxNotebook_GetPageText, 1885). +-define(wxNotebook_GetRowCount, 1886). +-define(wxNotebook_GetSelection, 1887). +-define(wxNotebook_GetThemeBackgroundColour, 1888). +-define(wxNotebook_HitTest, 1890). +-define(wxNotebook_InsertPage, 1892). +-define(wxNotebook_SetImageList, 1893). +-define(wxNotebook_SetPadding, 1894). +-define(wxNotebook_SetPageSize, 1895). +-define(wxNotebook_SetPageImage, 1896). +-define(wxNotebook_SetPageText, 1897). +-define(wxNotebook_SetSelection, 1898). +-define(wxNotebook_ChangeSelection, 1899). +-define(wxChoicebook_new_0, 1900). +-define(wxChoicebook_new_3, 1901). +-define(wxChoicebook_AddPage, 1902). +-define(wxChoicebook_AdvanceSelection, 1903). +-define(wxChoicebook_AssignImageList, 1904). +-define(wxChoicebook_Create, 1905). +-define(wxChoicebook_DeleteAllPages, 1906). +-define(wxChoicebook_DeletePage, 1907). +-define(wxChoicebook_RemovePage, 1908). +-define(wxChoicebook_GetCurrentPage, 1909). +-define(wxChoicebook_GetImageList, 1910). +-define(wxChoicebook_GetPage, 1912). +-define(wxChoicebook_GetPageCount, 1913). +-define(wxChoicebook_GetPageImage, 1914). +-define(wxChoicebook_GetPageText, 1915). +-define(wxChoicebook_GetSelection, 1916). +-define(wxChoicebook_HitTest, 1917). +-define(wxChoicebook_InsertPage, 1918). +-define(wxChoicebook_SetImageList, 1919). +-define(wxChoicebook_SetPageSize, 1920). +-define(wxChoicebook_SetPageImage, 1921). +-define(wxChoicebook_SetPageText, 1922). +-define(wxChoicebook_SetSelection, 1923). +-define(wxChoicebook_ChangeSelection, 1924). +-define(wxChoicebook_destroy, 1925). +-define(wxToolbook_new_0, 1926). +-define(wxToolbook_new_3, 1927). +-define(wxToolbook_AddPage, 1928). +-define(wxToolbook_AdvanceSelection, 1929). +-define(wxToolbook_AssignImageList, 1930). +-define(wxToolbook_Create, 1931). +-define(wxToolbook_DeleteAllPages, 1932). +-define(wxToolbook_DeletePage, 1933). +-define(wxToolbook_RemovePage, 1934). +-define(wxToolbook_GetCurrentPage, 1935). +-define(wxToolbook_GetImageList, 1936). +-define(wxToolbook_GetPage, 1938). +-define(wxToolbook_GetPageCount, 1939). +-define(wxToolbook_GetPageImage, 1940). +-define(wxToolbook_GetPageText, 1941). +-define(wxToolbook_GetSelection, 1942). +-define(wxToolbook_HitTest, 1944). +-define(wxToolbook_InsertPage, 1945). +-define(wxToolbook_SetImageList, 1946). +-define(wxToolbook_SetPageSize, 1947). +-define(wxToolbook_SetPageImage, 1948). +-define(wxToolbook_SetPageText, 1949). +-define(wxToolbook_SetSelection, 1950). +-define(wxToolbook_ChangeSelection, 1951). +-define(wxToolbook_destroy, 1952). +-define(wxListbook_new_0, 1953). +-define(wxListbook_new_3, 1954). +-define(wxListbook_AddPage, 1955). +-define(wxListbook_AdvanceSelection, 1956). +-define(wxListbook_AssignImageList, 1957). +-define(wxListbook_Create, 1958). +-define(wxListbook_DeleteAllPages, 1959). +-define(wxListbook_DeletePage, 1960). +-define(wxListbook_RemovePage, 1961). +-define(wxListbook_GetCurrentPage, 1962). +-define(wxListbook_GetImageList, 1963). +-define(wxListbook_GetPage, 1965). +-define(wxListbook_GetPageCount, 1966). +-define(wxListbook_GetPageImage, 1967). +-define(wxListbook_GetPageText, 1968). +-define(wxListbook_GetSelection, 1969). +-define(wxListbook_HitTest, 1971). +-define(wxListbook_InsertPage, 1972). +-define(wxListbook_SetImageList, 1973). +-define(wxListbook_SetPageSize, 1974). +-define(wxListbook_SetPageImage, 1975). +-define(wxListbook_SetPageText, 1976). +-define(wxListbook_SetSelection, 1977). +-define(wxListbook_ChangeSelection, 1978). +-define(wxListbook_destroy, 1979). +-define(wxTreebook_new_0, 1980). +-define(wxTreebook_new_3, 1981). +-define(wxTreebook_AddPage, 1982). +-define(wxTreebook_AdvanceSelection, 1983). +-define(wxTreebook_AssignImageList, 1984). +-define(wxTreebook_Create, 1985). +-define(wxTreebook_DeleteAllPages, 1986). +-define(wxTreebook_DeletePage, 1987). +-define(wxTreebook_RemovePage, 1988). +-define(wxTreebook_GetCurrentPage, 1989). +-define(wxTreebook_GetImageList, 1990). +-define(wxTreebook_GetPage, 1992). +-define(wxTreebook_GetPageCount, 1993). +-define(wxTreebook_GetPageImage, 1994). +-define(wxTreebook_GetPageText, 1995). +-define(wxTreebook_GetSelection, 1996). +-define(wxTreebook_ExpandNode, 1997). +-define(wxTreebook_IsNodeExpanded, 1998). +-define(wxTreebook_HitTest, 2000). +-define(wxTreebook_InsertPage, 2001). +-define(wxTreebook_InsertSubPage, 2002). +-define(wxTreebook_SetImageList, 2003). +-define(wxTreebook_SetPageSize, 2004). +-define(wxTreebook_SetPageImage, 2005). +-define(wxTreebook_SetPageText, 2006). +-define(wxTreebook_SetSelection, 2007). +-define(wxTreebook_ChangeSelection, 2008). +-define(wxTreebook_destroy, 2009). +-define(wxTreeCtrl_new_2, 2012). +-define(wxTreeCtrl_new_0, 2013). +-define(wxTreeCtrl_destruct, 2015). +-define(wxTreeCtrl_AddRoot, 2016). +-define(wxTreeCtrl_AppendItem, 2017). +-define(wxTreeCtrl_AssignImageList, 2018). +-define(wxTreeCtrl_AssignStateImageList, 2019). +-define(wxTreeCtrl_Collapse, 2020). +-define(wxTreeCtrl_CollapseAndReset, 2021). +-define(wxTreeCtrl_Create, 2022). +-define(wxTreeCtrl_Delete, 2023). +-define(wxTreeCtrl_DeleteAllItems, 2024). +-define(wxTreeCtrl_DeleteChildren, 2025). +-define(wxTreeCtrl_EditLabel, 2026). +-define(wxTreeCtrl_EnsureVisible, 2027). +-define(wxTreeCtrl_Expand, 2028). +-define(wxTreeCtrl_GetBoundingRect, 2029). +-define(wxTreeCtrl_GetChildrenCount, 2031). +-define(wxTreeCtrl_GetCount, 2032). +-define(wxTreeCtrl_GetEditControl, 2033). +-define(wxTreeCtrl_GetFirstChild, 2034). +-define(wxTreeCtrl_GetNextChild, 2035). +-define(wxTreeCtrl_GetFirstVisibleItem, 2036). +-define(wxTreeCtrl_GetImageList, 2037). +-define(wxTreeCtrl_GetIndent, 2038). +-define(wxTreeCtrl_GetItemBackgroundColour, 2039). +-define(wxTreeCtrl_GetItemData, 2040). +-define(wxTreeCtrl_GetItemFont, 2041). +-define(wxTreeCtrl_GetItemImage_1, 2042). +-define(wxTreeCtrl_GetItemImage_2, 2043). +-define(wxTreeCtrl_GetItemText, 2044). +-define(wxTreeCtrl_GetItemTextColour, 2045). +-define(wxTreeCtrl_GetLastChild, 2046). +-define(wxTreeCtrl_GetNextSibling, 2047). +-define(wxTreeCtrl_GetNextVisible, 2048). +-define(wxTreeCtrl_GetItemParent, 2049). +-define(wxTreeCtrl_GetPrevSibling, 2050). +-define(wxTreeCtrl_GetPrevVisible, 2051). +-define(wxTreeCtrl_GetRootItem, 2052). +-define(wxTreeCtrl_GetSelection, 2053). +-define(wxTreeCtrl_GetSelections, 2054). +-define(wxTreeCtrl_GetStateImageList, 2055). +-define(wxTreeCtrl_HitTest, 2056). +-define(wxTreeCtrl_InsertItem, 2058). +-define(wxTreeCtrl_IsBold, 2059). +-define(wxTreeCtrl_IsExpanded, 2060). +-define(wxTreeCtrl_IsSelected, 2061). +-define(wxTreeCtrl_IsVisible, 2062). +-define(wxTreeCtrl_ItemHasChildren, 2063). +-define(wxTreeCtrl_IsTreeItemIdOk, 2064). +-define(wxTreeCtrl_PrependItem, 2065). +-define(wxTreeCtrl_ScrollTo, 2066). +-define(wxTreeCtrl_SelectItem_1, 2067). +-define(wxTreeCtrl_SelectItem_2, 2068). +-define(wxTreeCtrl_SetIndent, 2069). +-define(wxTreeCtrl_SetImageList, 2070). +-define(wxTreeCtrl_SetItemBackgroundColour, 2071). +-define(wxTreeCtrl_SetItemBold, 2072). +-define(wxTreeCtrl_SetItemData, 2073). +-define(wxTreeCtrl_SetItemDropHighlight, 2074). +-define(wxTreeCtrl_SetItemFont, 2075). +-define(wxTreeCtrl_SetItemHasChildren, 2076). +-define(wxTreeCtrl_SetItemImage_2, 2077). +-define(wxTreeCtrl_SetItemImage_3, 2078). +-define(wxTreeCtrl_SetItemText, 2079). +-define(wxTreeCtrl_SetItemTextColour, 2080). +-define(wxTreeCtrl_SetStateImageList, 2081). +-define(wxTreeCtrl_SetWindowStyle, 2082). +-define(wxTreeCtrl_SortChildren, 2083). +-define(wxTreeCtrl_Toggle, 2084). +-define(wxTreeCtrl_ToggleItemSelection, 2085). +-define(wxTreeCtrl_Unselect, 2086). +-define(wxTreeCtrl_UnselectAll, 2087). +-define(wxTreeCtrl_UnselectItem, 2088). +-define(wxScrollBar_new_0, 2089). +-define(wxScrollBar_new_3, 2090). +-define(wxScrollBar_destruct, 2091). +-define(wxScrollBar_Create, 2092). +-define(wxScrollBar_GetRange, 2093). +-define(wxScrollBar_GetPageSize, 2094). +-define(wxScrollBar_GetThumbPosition, 2095). +-define(wxScrollBar_GetThumbSize, 2096). +-define(wxScrollBar_SetThumbPosition, 2097). +-define(wxScrollBar_SetScrollbar, 2098). +-define(wxSpinButton_new_2, 2100). +-define(wxSpinButton_new_0, 2101). +-define(wxSpinButton_Create, 2102). +-define(wxSpinButton_GetMax, 2103). +-define(wxSpinButton_GetMin, 2104). +-define(wxSpinButton_GetValue, 2105). +-define(wxSpinButton_SetRange, 2106). +-define(wxSpinButton_SetValue, 2107). +-define(wxSpinButton_destroy, 2108). +-define(wxSpinCtrl_new_0, 2109). +-define(wxSpinCtrl_new_2, 2110). +-define(wxSpinCtrl_Create, 2112). +-define(wxSpinCtrl_SetValue_1_1, 2115). +-define(wxSpinCtrl_SetValue_1_0, 2116). +-define(wxSpinCtrl_GetValue, 2118). +-define(wxSpinCtrl_SetRange, 2120). +-define(wxSpinCtrl_SetSelection, 2121). +-define(wxSpinCtrl_GetMin, 2123). +-define(wxSpinCtrl_GetMax, 2125). +-define(wxSpinCtrl_destroy, 2126). +-define(wxStaticText_new_0, 2127). +-define(wxStaticText_new_4, 2128). +-define(wxStaticText_Create, 2129). +-define(wxStaticText_GetLabel, 2130). +-define(wxStaticText_SetLabel, 2131). +-define(wxStaticText_Wrap, 2132). +-define(wxStaticText_destroy, 2133). +-define(wxStaticBitmap_new_0, 2134). +-define(wxStaticBitmap_new_4, 2135). +-define(wxStaticBitmap_Create, 2136). +-define(wxStaticBitmap_GetBitmap, 2137). +-define(wxStaticBitmap_SetBitmap, 2138). +-define(wxStaticBitmap_destroy, 2139). +-define(wxRadioBox_new, 2140). +-define(wxRadioBox_destruct, 2142). +-define(wxRadioBox_Create, 2143). +-define(wxRadioBox_Enable_2, 2144). +-define(wxRadioBox_Enable_1, 2145). +-define(wxRadioBox_GetSelection, 2146). +-define(wxRadioBox_GetString, 2147). +-define(wxRadioBox_SetSelection, 2148). +-define(wxRadioBox_Show_2, 2149). +-define(wxRadioBox_Show_1, 2150). +-define(wxRadioBox_GetColumnCount, 2151). +-define(wxRadioBox_GetItemHelpText, 2152). +-define(wxRadioBox_GetItemToolTip, 2153). +-define(wxRadioBox_GetItemFromPoint, 2155). +-define(wxRadioBox_GetRowCount, 2156). +-define(wxRadioBox_IsItemEnabled, 2157). +-define(wxRadioBox_IsItemShown, 2158). +-define(wxRadioBox_SetItemHelpText, 2159). +-define(wxRadioBox_SetItemToolTip, 2160). +-define(wxRadioButton_new_0, 2161). +-define(wxRadioButton_new_4, 2162). +-define(wxRadioButton_Create, 2163). +-define(wxRadioButton_GetValue, 2164). +-define(wxRadioButton_SetValue, 2165). +-define(wxRadioButton_destroy, 2166). +-define(wxSlider_new_6, 2168). +-define(wxSlider_new_0, 2169). +-define(wxSlider_Create, 2170). +-define(wxSlider_GetLineSize, 2171). +-define(wxSlider_GetMax, 2172). +-define(wxSlider_GetMin, 2173). +-define(wxSlider_GetPageSize, 2174). +-define(wxSlider_GetThumbLength, 2175). +-define(wxSlider_GetValue, 2176). +-define(wxSlider_SetLineSize, 2177). +-define(wxSlider_SetPageSize, 2178). +-define(wxSlider_SetRange, 2179). +-define(wxSlider_SetThumbLength, 2180). +-define(wxSlider_SetValue, 2181). +-define(wxSlider_destroy, 2182). +-define(wxDialog_new_4, 2184). +-define(wxDialog_new_0, 2185). +-define(wxDialog_destruct, 2187). +-define(wxDialog_Create, 2188). +-define(wxDialog_CreateButtonSizer, 2189). +-define(wxDialog_CreateStdDialogButtonSizer, 2190). +-define(wxDialog_EndModal, 2191). +-define(wxDialog_GetAffirmativeId, 2192). +-define(wxDialog_GetReturnCode, 2193). +-define(wxDialog_IsModal, 2194). +-define(wxDialog_SetAffirmativeId, 2195). +-define(wxDialog_SetReturnCode, 2196). +-define(wxDialog_Show, 2197). +-define(wxDialog_ShowModal, 2198). +-define(wxColourDialog_new_0, 2199). +-define(wxColourDialog_new_2, 2200). +-define(wxColourDialog_destruct, 2201). +-define(wxColourDialog_Create, 2202). +-define(wxColourDialog_GetColourData, 2203). +-define(wxColourData_new_0, 2204). +-define(wxColourData_new_1, 2205). +-define(wxColourData_destruct, 2206). +-define(wxColourData_GetChooseFull, 2207). +-define(wxColourData_GetColour, 2208). +-define(wxColourData_GetCustomColour, 2210). +-define(wxColourData_SetChooseFull, 2211). +-define(wxColourData_SetColour, 2212). +-define(wxColourData_SetCustomColour, 2213). +-define(wxPalette_new_0, 2214). +-define(wxPalette_new_4, 2215). +-define(wxPalette_destruct, 2217). +-define(wxPalette_Create, 2218). +-define(wxPalette_GetColoursCount, 2219). +-define(wxPalette_GetPixel, 2220). +-define(wxPalette_GetRGB, 2221). +-define(wxPalette_IsOk, 2222). +-define(wxDirDialog_new, 2226). +-define(wxDirDialog_destruct, 2227). +-define(wxDirDialog_GetPath, 2228). +-define(wxDirDialog_GetMessage, 2229). +-define(wxDirDialog_SetMessage, 2230). +-define(wxDirDialog_SetPath, 2231). +-define(wxFileDialog_new, 2235). +-define(wxFileDialog_destruct, 2236). +-define(wxFileDialog_GetDirectory, 2237). +-define(wxFileDialog_GetFilename, 2238). +-define(wxFileDialog_GetFilenames, 2239). +-define(wxFileDialog_GetFilterIndex, 2240). +-define(wxFileDialog_GetMessage, 2241). +-define(wxFileDialog_GetPath, 2242). +-define(wxFileDialog_GetPaths, 2243). +-define(wxFileDialog_GetWildcard, 2244). +-define(wxFileDialog_SetDirectory, 2245). +-define(wxFileDialog_SetFilename, 2246). +-define(wxFileDialog_SetFilterIndex, 2247). +-define(wxFileDialog_SetMessage, 2248). +-define(wxFileDialog_SetPath, 2249). +-define(wxFileDialog_SetWildcard, 2250). +-define(wxPickerBase_SetInternalMargin, 2251). +-define(wxPickerBase_GetInternalMargin, 2252). +-define(wxPickerBase_SetTextCtrlProportion, 2253). +-define(wxPickerBase_SetPickerCtrlProportion, 2254). +-define(wxPickerBase_GetTextCtrlProportion, 2255). +-define(wxPickerBase_GetPickerCtrlProportion, 2256). +-define(wxPickerBase_HasTextCtrl, 2257). +-define(wxPickerBase_GetTextCtrl, 2258). +-define(wxPickerBase_IsTextCtrlGrowable, 2259). +-define(wxPickerBase_SetPickerCtrlGrowable, 2260). +-define(wxPickerBase_SetTextCtrlGrowable, 2261). +-define(wxPickerBase_IsPickerCtrlGrowable, 2262). +-define(wxFilePickerCtrl_new_0, 2263). +-define(wxFilePickerCtrl_new_3, 2264). +-define(wxFilePickerCtrl_Create, 2265). +-define(wxFilePickerCtrl_GetPath, 2266). +-define(wxFilePickerCtrl_SetPath, 2267). +-define(wxFilePickerCtrl_destroy, 2268). +-define(wxDirPickerCtrl_new_0, 2269). +-define(wxDirPickerCtrl_new_3, 2270). +-define(wxDirPickerCtrl_Create, 2271). +-define(wxDirPickerCtrl_GetPath, 2272). +-define(wxDirPickerCtrl_SetPath, 2273). +-define(wxDirPickerCtrl_destroy, 2274). +-define(wxColourPickerCtrl_new_0, 2275). +-define(wxColourPickerCtrl_new_3, 2276). +-define(wxColourPickerCtrl_Create, 2277). +-define(wxColourPickerCtrl_GetColour, 2278). +-define(wxColourPickerCtrl_SetColour_1_1, 2279). +-define(wxColourPickerCtrl_SetColour_1_0, 2280). +-define(wxColourPickerCtrl_destroy, 2281). +-define(wxDatePickerCtrl_new_0, 2282). +-define(wxDatePickerCtrl_new_3, 2283). +-define(wxDatePickerCtrl_GetRange, 2284). +-define(wxDatePickerCtrl_GetValue, 2285). +-define(wxDatePickerCtrl_SetRange, 2286). +-define(wxDatePickerCtrl_SetValue, 2287). +-define(wxDatePickerCtrl_destroy, 2288). +-define(wxFontPickerCtrl_new_0, 2289). +-define(wxFontPickerCtrl_new_3, 2290). +-define(wxFontPickerCtrl_Create, 2291). +-define(wxFontPickerCtrl_GetSelectedFont, 2292). +-define(wxFontPickerCtrl_SetSelectedFont, 2293). +-define(wxFontPickerCtrl_GetMaxPointSize, 2294). +-define(wxFontPickerCtrl_SetMaxPointSize, 2295). +-define(wxFontPickerCtrl_destroy, 2296). +-define(wxFindReplaceDialog_new_0, 2299). +-define(wxFindReplaceDialog_new_4, 2300). +-define(wxFindReplaceDialog_destruct, 2301). +-define(wxFindReplaceDialog_Create, 2302). +-define(wxFindReplaceDialog_GetData, 2303). +-define(wxFindReplaceData_new_0, 2304). +-define(wxFindReplaceData_new_1, 2305). +-define(wxFindReplaceData_GetFindString, 2306). +-define(wxFindReplaceData_GetReplaceString, 2307). +-define(wxFindReplaceData_GetFlags, 2308). +-define(wxFindReplaceData_SetFlags, 2309). +-define(wxFindReplaceData_SetFindString, 2310). +-define(wxFindReplaceData_SetReplaceString, 2311). +-define(wxFindReplaceData_destroy, 2312). +-define(wxMultiChoiceDialog_new_0, 2313). +-define(wxMultiChoiceDialog_new_5, 2315). +-define(wxMultiChoiceDialog_GetSelections, 2316). +-define(wxMultiChoiceDialog_SetSelections, 2317). +-define(wxMultiChoiceDialog_destroy, 2318). +-define(wxSingleChoiceDialog_new_0, 2319). +-define(wxSingleChoiceDialog_new_5, 2321). +-define(wxSingleChoiceDialog_GetSelection, 2322). +-define(wxSingleChoiceDialog_GetStringSelection, 2323). +-define(wxSingleChoiceDialog_SetSelection, 2324). +-define(wxSingleChoiceDialog_destroy, 2325). +-define(wxTextEntryDialog_new, 2326). +-define(wxTextEntryDialog_GetValue, 2327). +-define(wxTextEntryDialog_SetValue, 2328). +-define(wxTextEntryDialog_destroy, 2329). +-define(wxPasswordEntryDialog_new, 2330). +-define(wxPasswordEntryDialog_destroy, 2331). +-define(wxFontData_new_0, 2332). +-define(wxFontData_new_1, 2333). +-define(wxFontData_destruct, 2334). +-define(wxFontData_EnableEffects, 2335). +-define(wxFontData_GetAllowSymbols, 2336). +-define(wxFontData_GetColour, 2337). +-define(wxFontData_GetChosenFont, 2338). +-define(wxFontData_GetEnableEffects, 2339). +-define(wxFontData_GetInitialFont, 2340). +-define(wxFontData_GetShowHelp, 2341). +-define(wxFontData_SetAllowSymbols, 2342). +-define(wxFontData_SetChosenFont, 2343). +-define(wxFontData_SetColour, 2344). +-define(wxFontData_SetInitialFont, 2345). +-define(wxFontData_SetRange, 2346). +-define(wxFontData_SetShowHelp, 2347). +-define(wxFontDialog_new_0, 2351). +-define(wxFontDialog_new_2, 2353). +-define(wxFontDialog_Create, 2355). +-define(wxFontDialog_GetFontData, 2356). +-define(wxFontDialog_destroy, 2358). +-define(wxProgressDialog_new, 2359). +-define(wxProgressDialog_destruct, 2360). +-define(wxProgressDialog_Resume, 2361). +-define(wxProgressDialog_Update_2, 2362). +-define(wxProgressDialog_Update_0, 2363). +-define(wxMessageDialog_new, 2364). +-define(wxMessageDialog_destruct, 2365). +-define(wxPageSetupDialog_new, 2366). +-define(wxPageSetupDialog_destruct, 2367). +-define(wxPageSetupDialog_GetPageSetupData, 2368). +-define(wxPageSetupDialog_ShowModal, 2369). +-define(wxPageSetupDialogData_new_0, 2370). +-define(wxPageSetupDialogData_new_1_0, 2371). +-define(wxPageSetupDialogData_new_1_1, 2372). +-define(wxPageSetupDialogData_destruct, 2373). +-define(wxPageSetupDialogData_EnableHelp, 2374). +-define(wxPageSetupDialogData_EnableMargins, 2375). +-define(wxPageSetupDialogData_EnableOrientation, 2376). +-define(wxPageSetupDialogData_EnablePaper, 2377). +-define(wxPageSetupDialogData_EnablePrinter, 2378). +-define(wxPageSetupDialogData_GetDefaultMinMargins, 2379). +-define(wxPageSetupDialogData_GetEnableMargins, 2380). +-define(wxPageSetupDialogData_GetEnableOrientation, 2381). +-define(wxPageSetupDialogData_GetEnablePaper, 2382). +-define(wxPageSetupDialogData_GetEnablePrinter, 2383). +-define(wxPageSetupDialogData_GetEnableHelp, 2384). +-define(wxPageSetupDialogData_GetDefaultInfo, 2385). +-define(wxPageSetupDialogData_GetMarginTopLeft, 2386). +-define(wxPageSetupDialogData_GetMarginBottomRight, 2387). +-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2388). +-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2389). +-define(wxPageSetupDialogData_GetPaperId, 2390). +-define(wxPageSetupDialogData_GetPaperSize, 2391). +-define(wxPageSetupDialogData_GetPrintData, 2393). +-define(wxPageSetupDialogData_IsOk, 2394). +-define(wxPageSetupDialogData_SetDefaultInfo, 2395). +-define(wxPageSetupDialogData_SetDefaultMinMargins, 2396). +-define(wxPageSetupDialogData_SetMarginTopLeft, 2397). +-define(wxPageSetupDialogData_SetMarginBottomRight, 2398). +-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2399). +-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2400). +-define(wxPageSetupDialogData_SetPaperId, 2401). +-define(wxPageSetupDialogData_SetPaperSize_1_1, 2402). +-define(wxPageSetupDialogData_SetPaperSize_1_0, 2403). +-define(wxPageSetupDialogData_SetPrintData, 2404). +-define(wxPrintDialog_new_2_0, 2405). +-define(wxPrintDialog_new_2_1, 2406). +-define(wxPrintDialog_destruct, 2407). +-define(wxPrintDialog_GetPrintDialogData, 2408). +-define(wxPrintDialog_GetPrintDC, 2409). +-define(wxPrintDialogData_new_0, 2410). +-define(wxPrintDialogData_new_1_1, 2411). +-define(wxPrintDialogData_new_1_0, 2412). +-define(wxPrintDialogData_destruct, 2413). +-define(wxPrintDialogData_EnableHelp, 2414). +-define(wxPrintDialogData_EnablePageNumbers, 2415). +-define(wxPrintDialogData_EnablePrintToFile, 2416). +-define(wxPrintDialogData_EnableSelection, 2417). +-define(wxPrintDialogData_GetAllPages, 2418). +-define(wxPrintDialogData_GetCollate, 2419). +-define(wxPrintDialogData_GetFromPage, 2420). +-define(wxPrintDialogData_GetMaxPage, 2421). +-define(wxPrintDialogData_GetMinPage, 2422). +-define(wxPrintDialogData_GetNoCopies, 2423). +-define(wxPrintDialogData_GetPrintData, 2424). +-define(wxPrintDialogData_GetPrintToFile, 2425). +-define(wxPrintDialogData_GetSelection, 2426). +-define(wxPrintDialogData_GetToPage, 2427). +-define(wxPrintDialogData_IsOk, 2428). +-define(wxPrintDialogData_SetCollate, 2429). +-define(wxPrintDialogData_SetFromPage, 2430). +-define(wxPrintDialogData_SetMaxPage, 2431). +-define(wxPrintDialogData_SetMinPage, 2432). +-define(wxPrintDialogData_SetNoCopies, 2433). +-define(wxPrintDialogData_SetPrintData, 2434). +-define(wxPrintDialogData_SetPrintToFile, 2435). +-define(wxPrintDialogData_SetSelection, 2436). +-define(wxPrintDialogData_SetToPage, 2437). +-define(wxPrintData_new_0, 2438). +-define(wxPrintData_new_1, 2439). +-define(wxPrintData_destruct, 2440). +-define(wxPrintData_GetCollate, 2441). +-define(wxPrintData_GetBin, 2442). +-define(wxPrintData_GetColour, 2443). +-define(wxPrintData_GetDuplex, 2444). +-define(wxPrintData_GetNoCopies, 2445). +-define(wxPrintData_GetOrientation, 2446). +-define(wxPrintData_GetPaperId, 2447). +-define(wxPrintData_GetPrinterName, 2448). +-define(wxPrintData_GetQuality, 2449). +-define(wxPrintData_IsOk, 2450). +-define(wxPrintData_SetBin, 2451). +-define(wxPrintData_SetCollate, 2452). +-define(wxPrintData_SetColour, 2453). +-define(wxPrintData_SetDuplex, 2454). +-define(wxPrintData_SetNoCopies, 2455). +-define(wxPrintData_SetOrientation, 2456). +-define(wxPrintData_SetPaperId, 2457). +-define(wxPrintData_SetPrinterName, 2458). +-define(wxPrintData_SetQuality, 2459). +-define(wxPrintPreview_new_2, 2462). +-define(wxPrintPreview_new_3, 2463). +-define(wxPrintPreview_destruct, 2465). +-define(wxPrintPreview_GetCanvas, 2466). +-define(wxPrintPreview_GetCurrentPage, 2467). +-define(wxPrintPreview_GetFrame, 2468). +-define(wxPrintPreview_GetMaxPage, 2469). +-define(wxPrintPreview_GetMinPage, 2470). +-define(wxPrintPreview_GetPrintout, 2471). +-define(wxPrintPreview_GetPrintoutForPrinting, 2472). +-define(wxPrintPreview_IsOk, 2473). +-define(wxPrintPreview_PaintPage, 2474). +-define(wxPrintPreview_Print, 2475). +-define(wxPrintPreview_RenderPage, 2476). +-define(wxPrintPreview_SetCanvas, 2477). +-define(wxPrintPreview_SetCurrentPage, 2478). +-define(wxPrintPreview_SetFrame, 2479). +-define(wxPrintPreview_SetPrintout, 2480). +-define(wxPrintPreview_SetZoom, 2481). +-define(wxPreviewFrame_new, 2482). +-define(wxPreviewFrame_destruct, 2483). +-define(wxPreviewFrame_CreateControlBar, 2484). +-define(wxPreviewFrame_CreateCanvas, 2485). +-define(wxPreviewFrame_Initialize, 2486). +-define(wxPreviewFrame_OnCloseWindow, 2487). +-define(wxPreviewControlBar_new, 2488). +-define(wxPreviewControlBar_destruct, 2489). +-define(wxPreviewControlBar_CreateButtons, 2490). +-define(wxPreviewControlBar_GetPrintPreview, 2491). +-define(wxPreviewControlBar_GetZoomControl, 2492). +-define(wxPreviewControlBar_SetZoomControl, 2493). +-define(wxPrinter_new, 2495). +-define(wxPrinter_CreateAbortWindow, 2496). +-define(wxPrinter_GetAbort, 2497). +-define(wxPrinter_GetLastError, 2498). +-define(wxPrinter_GetPrintDialogData, 2499). +-define(wxPrinter_Print, 2500). +-define(wxPrinter_PrintDialog, 2501). +-define(wxPrinter_ReportError, 2502). +-define(wxPrinter_Setup, 2503). +-define(wxPrinter_destroy, 2504). +-define(wxXmlResource_new_1, 2505). +-define(wxXmlResource_new_2, 2506). +-define(wxXmlResource_destruct, 2507). +-define(wxXmlResource_AttachUnknownControl, 2508). +-define(wxXmlResource_ClearHandlers, 2509). +-define(wxXmlResource_CompareVersion, 2510). +-define(wxXmlResource_Get, 2511). +-define(wxXmlResource_GetFlags, 2512). +-define(wxXmlResource_GetVersion, 2513). +-define(wxXmlResource_GetXRCID, 2514). +-define(wxXmlResource_InitAllHandlers, 2515). +-define(wxXmlResource_Load, 2516). +-define(wxXmlResource_LoadBitmap, 2517). +-define(wxXmlResource_LoadDialog_2, 2518). +-define(wxXmlResource_LoadDialog_3, 2519). +-define(wxXmlResource_LoadFrame_2, 2520). +-define(wxXmlResource_LoadFrame_3, 2521). +-define(wxXmlResource_LoadIcon, 2522). +-define(wxXmlResource_LoadMenu, 2523). +-define(wxXmlResource_LoadMenuBar_2, 2524). +-define(wxXmlResource_LoadMenuBar_1, 2525). +-define(wxXmlResource_LoadPanel_2, 2526). +-define(wxXmlResource_LoadPanel_3, 2527). +-define(wxXmlResource_LoadToolBar, 2528). +-define(wxXmlResource_Set, 2529). +-define(wxXmlResource_SetFlags, 2530). +-define(wxXmlResource_Unload, 2531). +-define(wxXmlResource_xrcctrl, 2532). +-define(wxHtmlEasyPrinting_new, 2533). +-define(wxHtmlEasyPrinting_destruct, 2534). +-define(wxHtmlEasyPrinting_GetPrintData, 2535). +-define(wxHtmlEasyPrinting_GetPageSetupData, 2536). +-define(wxHtmlEasyPrinting_PreviewFile, 2537). +-define(wxHtmlEasyPrinting_PreviewText, 2538). +-define(wxHtmlEasyPrinting_PrintFile, 2539). +-define(wxHtmlEasyPrinting_PrintText, 2540). +-define(wxHtmlEasyPrinting_PageSetup, 2541). +-define(wxHtmlEasyPrinting_SetFonts, 2542). +-define(wxHtmlEasyPrinting_SetHeader, 2543). +-define(wxHtmlEasyPrinting_SetFooter, 2544). +-define(wxGLCanvas_new_2, 2546). +-define(wxGLCanvas_new_3_1, 2547). +-define(wxGLCanvas_new_3_0, 2548). +-define(wxGLCanvas_GetContext, 2549). +-define(wxGLCanvas_SetCurrent, 2551). +-define(wxGLCanvas_SwapBuffers, 2552). +-define(wxGLCanvas_destroy, 2553). +-define(wxAuiManager_new, 2554). +-define(wxAuiManager_destruct, 2555). +-define(wxAuiManager_AddPane_2_1, 2556). +-define(wxAuiManager_AddPane_3, 2557). +-define(wxAuiManager_AddPane_2_0, 2558). +-define(wxAuiManager_DetachPane, 2559). +-define(wxAuiManager_GetAllPanes, 2560). +-define(wxAuiManager_GetArtProvider, 2561). +-define(wxAuiManager_GetDockSizeConstraint, 2562). +-define(wxAuiManager_GetFlags, 2563). +-define(wxAuiManager_GetManagedWindow, 2564). +-define(wxAuiManager_GetManager, 2565). +-define(wxAuiManager_GetPane_1_1, 2566). +-define(wxAuiManager_GetPane_1_0, 2567). +-define(wxAuiManager_HideHint, 2568). +-define(wxAuiManager_InsertPane, 2569). +-define(wxAuiManager_LoadPaneInfo, 2570). +-define(wxAuiManager_LoadPerspective, 2571). +-define(wxAuiManager_SavePaneInfo, 2572). +-define(wxAuiManager_SavePerspective, 2573). +-define(wxAuiManager_SetArtProvider, 2574). +-define(wxAuiManager_SetDockSizeConstraint, 2575). +-define(wxAuiManager_SetFlags, 2576). +-define(wxAuiManager_SetManagedWindow, 2577). +-define(wxAuiManager_ShowHint, 2578). +-define(wxAuiManager_UnInit, 2579). +-define(wxAuiManager_Update, 2580). +-define(wxAuiPaneInfo_new_0, 2581). +-define(wxAuiPaneInfo_new_1, 2582). +-define(wxAuiPaneInfo_destruct, 2583). +-define(wxAuiPaneInfo_BestSize_1, 2584). +-define(wxAuiPaneInfo_BestSize_2, 2585). +-define(wxAuiPaneInfo_Bottom, 2586). +-define(wxAuiPaneInfo_BottomDockable, 2587). +-define(wxAuiPaneInfo_Caption, 2588). +-define(wxAuiPaneInfo_CaptionVisible, 2589). +-define(wxAuiPaneInfo_Centre, 2590). +-define(wxAuiPaneInfo_CentrePane, 2591). +-define(wxAuiPaneInfo_CloseButton, 2592). +-define(wxAuiPaneInfo_DefaultPane, 2593). +-define(wxAuiPaneInfo_DestroyOnClose, 2594). +-define(wxAuiPaneInfo_Direction, 2595). +-define(wxAuiPaneInfo_Dock, 2596). +-define(wxAuiPaneInfo_Dockable, 2597). +-define(wxAuiPaneInfo_Fixed, 2598). +-define(wxAuiPaneInfo_Float, 2599). +-define(wxAuiPaneInfo_Floatable, 2600). +-define(wxAuiPaneInfo_FloatingPosition_1, 2601). +-define(wxAuiPaneInfo_FloatingPosition_2, 2602). +-define(wxAuiPaneInfo_FloatingSize_1, 2603). +-define(wxAuiPaneInfo_FloatingSize_2, 2604). +-define(wxAuiPaneInfo_Gripper, 2605). +-define(wxAuiPaneInfo_GripperTop, 2606). +-define(wxAuiPaneInfo_HasBorder, 2607). +-define(wxAuiPaneInfo_HasCaption, 2608). +-define(wxAuiPaneInfo_HasCloseButton, 2609). +-define(wxAuiPaneInfo_HasFlag, 2610). +-define(wxAuiPaneInfo_HasGripper, 2611). +-define(wxAuiPaneInfo_HasGripperTop, 2612). +-define(wxAuiPaneInfo_HasMaximizeButton, 2613). +-define(wxAuiPaneInfo_HasMinimizeButton, 2614). +-define(wxAuiPaneInfo_HasPinButton, 2615). +-define(wxAuiPaneInfo_Hide, 2616). +-define(wxAuiPaneInfo_IsBottomDockable, 2617). +-define(wxAuiPaneInfo_IsDocked, 2618). +-define(wxAuiPaneInfo_IsFixed, 2619). +-define(wxAuiPaneInfo_IsFloatable, 2620). +-define(wxAuiPaneInfo_IsFloating, 2621). +-define(wxAuiPaneInfo_IsLeftDockable, 2622). +-define(wxAuiPaneInfo_IsMovable, 2623). +-define(wxAuiPaneInfo_IsOk, 2624). +-define(wxAuiPaneInfo_IsResizable, 2625). +-define(wxAuiPaneInfo_IsRightDockable, 2626). +-define(wxAuiPaneInfo_IsShown, 2627). +-define(wxAuiPaneInfo_IsToolbar, 2628). +-define(wxAuiPaneInfo_IsTopDockable, 2629). +-define(wxAuiPaneInfo_Layer, 2630). +-define(wxAuiPaneInfo_Left, 2631). +-define(wxAuiPaneInfo_LeftDockable, 2632). +-define(wxAuiPaneInfo_MaxSize_1, 2633). +-define(wxAuiPaneInfo_MaxSize_2, 2634). +-define(wxAuiPaneInfo_MaximizeButton, 2635). +-define(wxAuiPaneInfo_MinSize_1, 2636). +-define(wxAuiPaneInfo_MinSize_2, 2637). +-define(wxAuiPaneInfo_MinimizeButton, 2638). +-define(wxAuiPaneInfo_Movable, 2639). +-define(wxAuiPaneInfo_Name, 2640). +-define(wxAuiPaneInfo_PaneBorder, 2641). +-define(wxAuiPaneInfo_PinButton, 2642). +-define(wxAuiPaneInfo_Position, 2643). +-define(wxAuiPaneInfo_Resizable, 2644). +-define(wxAuiPaneInfo_Right, 2645). +-define(wxAuiPaneInfo_RightDockable, 2646). +-define(wxAuiPaneInfo_Row, 2647). +-define(wxAuiPaneInfo_SafeSet, 2648). +-define(wxAuiPaneInfo_SetFlag, 2649). +-define(wxAuiPaneInfo_Show, 2650). +-define(wxAuiPaneInfo_ToolbarPane, 2651). +-define(wxAuiPaneInfo_Top, 2652). +-define(wxAuiPaneInfo_TopDockable, 2653). +-define(wxAuiPaneInfo_Window, 2654). +-define(wxAuiPaneInfo_GetWindow, 2655). +-define(wxAuiPaneInfo_GetFrame, 2656). +-define(wxAuiPaneInfo_GetDirection, 2657). +-define(wxAuiPaneInfo_GetLayer, 2658). +-define(wxAuiPaneInfo_GetRow, 2659). +-define(wxAuiPaneInfo_GetPosition, 2660). +-define(wxAuiPaneInfo_GetFloatingPosition, 2661). +-define(wxAuiPaneInfo_GetFloatingSize, 2662). +-define(wxAuiNotebook_new_0, 2663). +-define(wxAuiNotebook_new_2, 2664). +-define(wxAuiNotebook_AddPage, 2665). +-define(wxAuiNotebook_Create, 2666). +-define(wxAuiNotebook_DeletePage, 2667). +-define(wxAuiNotebook_GetArtProvider, 2668). +-define(wxAuiNotebook_GetPage, 2669). +-define(wxAuiNotebook_GetPageBitmap, 2670). +-define(wxAuiNotebook_GetPageCount, 2671). +-define(wxAuiNotebook_GetPageIndex, 2672). +-define(wxAuiNotebook_GetPageText, 2673). +-define(wxAuiNotebook_GetSelection, 2674). +-define(wxAuiNotebook_InsertPage, 2675). +-define(wxAuiNotebook_RemovePage, 2676). +-define(wxAuiNotebook_SetArtProvider, 2677). +-define(wxAuiNotebook_SetFont, 2678). +-define(wxAuiNotebook_SetPageBitmap, 2679). +-define(wxAuiNotebook_SetPageText, 2680). +-define(wxAuiNotebook_SetSelection, 2681). +-define(wxAuiNotebook_SetTabCtrlHeight, 2682). +-define(wxAuiNotebook_SetUniformBitmapSize, 2683). +-define(wxAuiNotebook_destroy, 2684). +-define(wxAuiTabArt_SetFlags, 2685). +-define(wxAuiTabArt_SetMeasuringFont, 2686). +-define(wxAuiTabArt_SetNormalFont, 2687). +-define(wxAuiTabArt_SetSelectedFont, 2688). +-define(wxAuiTabArt_SetColour, 2689). +-define(wxAuiTabArt_SetActiveColour, 2690). +-define(wxAuiDockArt_GetColour, 2691). +-define(wxAuiDockArt_GetFont, 2692). +-define(wxAuiDockArt_GetMetric, 2693). +-define(wxAuiDockArt_SetColour, 2694). +-define(wxAuiDockArt_SetFont, 2695). +-define(wxAuiDockArt_SetMetric, 2696). +-define(wxAuiSimpleTabArt_new, 2697). +-define(wxAuiSimpleTabArt_destroy, 2698). +-define(wxMDIParentFrame_new_0, 2699). +-define(wxMDIParentFrame_new_4, 2700). +-define(wxMDIParentFrame_destruct, 2701). +-define(wxMDIParentFrame_ActivateNext, 2702). +-define(wxMDIParentFrame_ActivatePrevious, 2703). +-define(wxMDIParentFrame_ArrangeIcons, 2704). +-define(wxMDIParentFrame_Cascade, 2705). +-define(wxMDIParentFrame_Create, 2706). +-define(wxMDIParentFrame_GetActiveChild, 2707). +-define(wxMDIParentFrame_GetClientWindow, 2708). +-define(wxMDIParentFrame_Tile, 2709). +-define(wxMDIChildFrame_new_0, 2710). +-define(wxMDIChildFrame_new_4, 2711). +-define(wxMDIChildFrame_destruct, 2712). +-define(wxMDIChildFrame_Activate, 2713). +-define(wxMDIChildFrame_Create, 2714). +-define(wxMDIChildFrame_Maximize, 2715). +-define(wxMDIChildFrame_Restore, 2716). +-define(wxMDIClientWindow_new_0, 2717). +-define(wxMDIClientWindow_new_2, 2718). +-define(wxMDIClientWindow_destruct, 2719). +-define(wxMDIClientWindow_CreateClient, 2720). +-define(wxLayoutAlgorithm_new, 2721). +-define(wxLayoutAlgorithm_LayoutFrame, 2722). +-define(wxLayoutAlgorithm_LayoutMDIFrame, 2723). +-define(wxLayoutAlgorithm_LayoutWindow, 2724). +-define(wxLayoutAlgorithm_destroy, 2725). +-define(wxEvent_GetId, 2726). +-define(wxEvent_GetSkipped, 2727). +-define(wxEvent_GetTimestamp, 2728). +-define(wxEvent_IsCommandEvent, 2729). +-define(wxEvent_ResumePropagation, 2730). +-define(wxEvent_ShouldPropagate, 2731). +-define(wxEvent_Skip, 2732). +-define(wxEvent_StopPropagation, 2733). +-define(wxCommandEvent_getClientData, 2734). +-define(wxCommandEvent_GetExtraLong, 2735). +-define(wxCommandEvent_GetInt, 2736). +-define(wxCommandEvent_GetSelection, 2737). +-define(wxCommandEvent_GetString, 2738). +-define(wxCommandEvent_IsChecked, 2739). +-define(wxCommandEvent_IsSelection, 2740). +-define(wxCommandEvent_SetInt, 2741). +-define(wxCommandEvent_SetString, 2742). +-define(wxScrollEvent_GetOrientation, 2743). +-define(wxScrollEvent_GetPosition, 2744). +-define(wxScrollWinEvent_GetOrientation, 2745). +-define(wxScrollWinEvent_GetPosition, 2746). +-define(wxMouseEvent_AltDown, 2747). +-define(wxMouseEvent_Button, 2748). +-define(wxMouseEvent_ButtonDClick, 2749). +-define(wxMouseEvent_ButtonDown, 2750). +-define(wxMouseEvent_ButtonUp, 2751). +-define(wxMouseEvent_CmdDown, 2752). +-define(wxMouseEvent_ControlDown, 2753). +-define(wxMouseEvent_Dragging, 2754). +-define(wxMouseEvent_Entering, 2755). +-define(wxMouseEvent_GetButton, 2756). +-define(wxMouseEvent_GetPosition, 2759). +-define(wxMouseEvent_GetLogicalPosition, 2760). +-define(wxMouseEvent_GetLinesPerAction, 2761). +-define(wxMouseEvent_GetWheelRotation, 2762). +-define(wxMouseEvent_GetWheelDelta, 2763). +-define(wxMouseEvent_GetX, 2764). +-define(wxMouseEvent_GetY, 2765). +-define(wxMouseEvent_IsButton, 2766). +-define(wxMouseEvent_IsPageScroll, 2767). +-define(wxMouseEvent_Leaving, 2768). +-define(wxMouseEvent_LeftDClick, 2769). +-define(wxMouseEvent_LeftDown, 2770). +-define(wxMouseEvent_LeftIsDown, 2771). +-define(wxMouseEvent_LeftUp, 2772). +-define(wxMouseEvent_MetaDown, 2773). +-define(wxMouseEvent_MiddleDClick, 2774). +-define(wxMouseEvent_MiddleDown, 2775). +-define(wxMouseEvent_MiddleIsDown, 2776). +-define(wxMouseEvent_MiddleUp, 2777). +-define(wxMouseEvent_Moving, 2778). +-define(wxMouseEvent_RightDClick, 2779). +-define(wxMouseEvent_RightDown, 2780). +-define(wxMouseEvent_RightIsDown, 2781). +-define(wxMouseEvent_RightUp, 2782). +-define(wxMouseEvent_ShiftDown, 2783). +-define(wxSetCursorEvent_GetCursor, 2784). +-define(wxSetCursorEvent_GetX, 2785). +-define(wxSetCursorEvent_GetY, 2786). +-define(wxSetCursorEvent_HasCursor, 2787). +-define(wxSetCursorEvent_SetCursor, 2788). +-define(wxKeyEvent_AltDown, 2789). +-define(wxKeyEvent_CmdDown, 2790). +-define(wxKeyEvent_ControlDown, 2791). +-define(wxKeyEvent_GetKeyCode, 2792). +-define(wxKeyEvent_GetModifiers, 2793). +-define(wxKeyEvent_GetPosition, 2796). +-define(wxKeyEvent_GetRawKeyCode, 2797). +-define(wxKeyEvent_GetRawKeyFlags, 2798). +-define(wxKeyEvent_GetUnicodeKey, 2799). +-define(wxKeyEvent_GetX, 2800). +-define(wxKeyEvent_GetY, 2801). +-define(wxKeyEvent_HasModifiers, 2802). +-define(wxKeyEvent_MetaDown, 2803). +-define(wxKeyEvent_ShiftDown, 2804). +-define(wxSizeEvent_GetSize, 2805). +-define(wxMoveEvent_GetPosition, 2806). +-define(wxEraseEvent_GetDC, 2807). +-define(wxFocusEvent_GetWindow, 2808). +-define(wxChildFocusEvent_GetWindow, 2809). +-define(wxMenuEvent_GetMenu, 2810). +-define(wxMenuEvent_GetMenuId, 2811). +-define(wxMenuEvent_IsPopup, 2812). +-define(wxCloseEvent_CanVeto, 2813). +-define(wxCloseEvent_GetLoggingOff, 2814). +-define(wxCloseEvent_SetCanVeto, 2815). +-define(wxCloseEvent_SetLoggingOff, 2816). +-define(wxCloseEvent_Veto, 2817). +-define(wxShowEvent_SetShow, 2818). +-define(wxShowEvent_GetShow, 2819). +-define(wxIconizeEvent_Iconized, 2820). +-define(wxJoystickEvent_ButtonDown, 2821). +-define(wxJoystickEvent_ButtonIsDown, 2822). +-define(wxJoystickEvent_ButtonUp, 2823). +-define(wxJoystickEvent_GetButtonChange, 2824). +-define(wxJoystickEvent_GetButtonState, 2825). +-define(wxJoystickEvent_GetJoystick, 2826). +-define(wxJoystickEvent_GetPosition, 2827). +-define(wxJoystickEvent_GetZPosition, 2828). +-define(wxJoystickEvent_IsButton, 2829). +-define(wxJoystickEvent_IsMove, 2830). +-define(wxJoystickEvent_IsZMove, 2831). +-define(wxUpdateUIEvent_CanUpdate, 2832). +-define(wxUpdateUIEvent_Check, 2833). +-define(wxUpdateUIEvent_Enable, 2834). +-define(wxUpdateUIEvent_Show, 2835). +-define(wxUpdateUIEvent_GetChecked, 2836). +-define(wxUpdateUIEvent_GetEnabled, 2837). +-define(wxUpdateUIEvent_GetShown, 2838). +-define(wxUpdateUIEvent_GetSetChecked, 2839). +-define(wxUpdateUIEvent_GetSetEnabled, 2840). +-define(wxUpdateUIEvent_GetSetShown, 2841). +-define(wxUpdateUIEvent_GetSetText, 2842). +-define(wxUpdateUIEvent_GetText, 2843). +-define(wxUpdateUIEvent_GetMode, 2844). +-define(wxUpdateUIEvent_GetUpdateInterval, 2845). +-define(wxUpdateUIEvent_ResetUpdateTime, 2846). +-define(wxUpdateUIEvent_SetMode, 2847). +-define(wxUpdateUIEvent_SetText, 2848). +-define(wxUpdateUIEvent_SetUpdateInterval, 2849). +-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2850). +-define(wxPaletteChangedEvent_SetChangedWindow, 2851). +-define(wxPaletteChangedEvent_GetChangedWindow, 2852). +-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2853). +-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2854). +-define(wxNavigationKeyEvent_GetDirection, 2855). +-define(wxNavigationKeyEvent_SetDirection, 2856). +-define(wxNavigationKeyEvent_IsWindowChange, 2857). +-define(wxNavigationKeyEvent_SetWindowChange, 2858). +-define(wxNavigationKeyEvent_IsFromTab, 2859). +-define(wxNavigationKeyEvent_SetFromTab, 2860). +-define(wxNavigationKeyEvent_GetCurrentFocus, 2861). +-define(wxNavigationKeyEvent_SetCurrentFocus, 2862). +-define(wxHelpEvent_GetOrigin, 2863). +-define(wxHelpEvent_GetPosition, 2864). +-define(wxHelpEvent_SetOrigin, 2865). +-define(wxHelpEvent_SetPosition, 2866). +-define(wxContextMenuEvent_GetPosition, 2867). +-define(wxContextMenuEvent_SetPosition, 2868). +-define(wxIdleEvent_CanSend, 2869). +-define(wxIdleEvent_GetMode, 2870). +-define(wxIdleEvent_RequestMore, 2871). +-define(wxIdleEvent_MoreRequested, 2872). +-define(wxIdleEvent_SetMode, 2873). +-define(wxGridEvent_AltDown, 2874). +-define(wxGridEvent_ControlDown, 2875). +-define(wxGridEvent_GetCol, 2876). +-define(wxGridEvent_GetPosition, 2877). +-define(wxGridEvent_GetRow, 2878). +-define(wxGridEvent_MetaDown, 2879). +-define(wxGridEvent_Selecting, 2880). +-define(wxGridEvent_ShiftDown, 2881). +-define(wxNotifyEvent_Allow, 2882). +-define(wxNotifyEvent_IsAllowed, 2883). +-define(wxNotifyEvent_Veto, 2884). +-define(wxSashEvent_GetEdge, 2885). +-define(wxSashEvent_GetDragRect, 2886). +-define(wxSashEvent_GetDragStatus, 2887). +-define(wxListEvent_GetCacheFrom, 2888). +-define(wxListEvent_GetCacheTo, 2889). +-define(wxListEvent_GetKeyCode, 2890). +-define(wxListEvent_GetIndex, 2891). +-define(wxListEvent_GetColumn, 2892). +-define(wxListEvent_GetPoint, 2893). +-define(wxListEvent_GetLabel, 2894). +-define(wxListEvent_GetText, 2895). +-define(wxListEvent_GetImage, 2896). +-define(wxListEvent_GetData, 2897). +-define(wxListEvent_GetMask, 2898). +-define(wxListEvent_GetItem, 2899). +-define(wxListEvent_IsEditCancelled, 2900). +-define(wxDateEvent_GetDate, 2901). +-define(wxCalendarEvent_GetWeekDay, 2902). +-define(wxFileDirPickerEvent_GetPath, 2903). +-define(wxColourPickerEvent_GetColour, 2904). +-define(wxFontPickerEvent_GetFont, 2905). +-define(wxStyledTextEvent_GetPosition, 2906). +-define(wxStyledTextEvent_GetKey, 2907). +-define(wxStyledTextEvent_GetModifiers, 2908). +-define(wxStyledTextEvent_GetModificationType, 2909). +-define(wxStyledTextEvent_GetText, 2910). +-define(wxStyledTextEvent_GetLength, 2911). +-define(wxStyledTextEvent_GetLinesAdded, 2912). +-define(wxStyledTextEvent_GetLine, 2913). +-define(wxStyledTextEvent_GetFoldLevelNow, 2914). +-define(wxStyledTextEvent_GetFoldLevelPrev, 2915). +-define(wxStyledTextEvent_GetMargin, 2916). +-define(wxStyledTextEvent_GetMessage, 2917). +-define(wxStyledTextEvent_GetWParam, 2918). +-define(wxStyledTextEvent_GetLParam, 2919). +-define(wxStyledTextEvent_GetListType, 2920). +-define(wxStyledTextEvent_GetX, 2921). +-define(wxStyledTextEvent_GetY, 2922). +-define(wxStyledTextEvent_GetDragText, 2923). +-define(wxStyledTextEvent_GetDragAllowMove, 2924). +-define(wxStyledTextEvent_GetDragResult, 2925). +-define(wxStyledTextEvent_GetShift, 2926). +-define(wxStyledTextEvent_GetControl, 2927). +-define(wxStyledTextEvent_GetAlt, 2928). +-define(utils_wxGetKeyState, 2929). +-define(utils_wxGetMousePosition, 2930). +-define(utils_wxGetMouseState, 2931). +-define(utils_wxSetDetectableAutoRepeat, 2932). +-define(utils_wxBell, 2933). +-define(utils_wxFindMenuItemId, 2934). +-define(utils_wxGenericFindWindowAtPoint, 2935). +-define(utils_wxFindWindowAtPoint, 2936). +-define(utils_wxBeginBusyCursor, 2937). +-define(utils_wxEndBusyCursor, 2938). +-define(utils_wxIsBusy, 2939). +-define(utils_wxShutdown, 2940). +-define(utils_wxShell, 2941). +-define(utils_wxLaunchDefaultBrowser, 2942). +-define(utils_wxGetEmailAddress, 2943). +-define(utils_wxGetUserId, 2944). +-define(utils_wxGetHomeDir, 2945). +-define(utils_wxNewId, 2946). +-define(utils_wxRegisterId, 2947). +-define(utils_wxGetCurrentId, 2948). +-define(utils_wxGetOsDescription, 2949). +-define(utils_wxIsPlatformLittleEndian, 2950). +-define(utils_wxIsPlatform64Bit, 2951). +-define(gdicmn_wxDisplaySize, 2952). +-define(gdicmn_wxSetCursor, 2953). +-define(wxPrintout_new, 2954). +-define(wxPrintout_destruct, 2955). +-define(wxPrintout_GetDC, 2956). +-define(wxPrintout_GetPageSizeMM, 2957). +-define(wxPrintout_GetPageSizePixels, 2958). +-define(wxPrintout_GetPaperRectPixels, 2959). +-define(wxPrintout_GetPPIPrinter, 2960). +-define(wxPrintout_GetPPIScreen, 2961). +-define(wxPrintout_GetTitle, 2962). +-define(wxPrintout_IsPreview, 2963). +-define(wxPrintout_FitThisSizeToPaper, 2964). +-define(wxPrintout_FitThisSizeToPage, 2965). +-define(wxPrintout_FitThisSizeToPageMargins, 2966). +-define(wxPrintout_MapScreenSizeToPaper, 2967). +-define(wxPrintout_MapScreenSizeToPage, 2968). +-define(wxPrintout_MapScreenSizeToPageMargins, 2969). +-define(wxPrintout_MapScreenSizeToDevice, 2970). +-define(wxPrintout_GetLogicalPaperRect, 2971). +-define(wxPrintout_GetLogicalPageRect, 2972). +-define(wxPrintout_GetLogicalPageMarginsRect, 2973). +-define(wxPrintout_SetLogicalOrigin, 2974). +-define(wxPrintout_OffsetLogicalOrigin, 2975). +-define(wxStyledTextCtrl_new_2, 2976). +-define(wxStyledTextCtrl_new_0, 2977). +-define(wxStyledTextCtrl_destruct, 2978). +-define(wxStyledTextCtrl_Create, 2979). +-define(wxStyledTextCtrl_AddText, 2980). +-define(wxStyledTextCtrl_AddStyledText, 2981). +-define(wxStyledTextCtrl_InsertText, 2982). +-define(wxStyledTextCtrl_ClearAll, 2983). +-define(wxStyledTextCtrl_ClearDocumentStyle, 2984). +-define(wxStyledTextCtrl_GetLength, 2985). +-define(wxStyledTextCtrl_GetCharAt, 2986). +-define(wxStyledTextCtrl_GetCurrentPos, 2987). +-define(wxStyledTextCtrl_GetAnchor, 2988). +-define(wxStyledTextCtrl_GetStyleAt, 2989). +-define(wxStyledTextCtrl_Redo, 2990). +-define(wxStyledTextCtrl_SetUndoCollection, 2991). +-define(wxStyledTextCtrl_SelectAll, 2992). +-define(wxStyledTextCtrl_SetSavePoint, 2993). +-define(wxStyledTextCtrl_GetStyledText, 2994). +-define(wxStyledTextCtrl_CanRedo, 2995). +-define(wxStyledTextCtrl_MarkerLineFromHandle, 2996). +-define(wxStyledTextCtrl_MarkerDeleteHandle, 2997). +-define(wxStyledTextCtrl_GetUndoCollection, 2998). +-define(wxStyledTextCtrl_GetViewWhiteSpace, 2999). +-define(wxStyledTextCtrl_SetViewWhiteSpace, 3000). +-define(wxStyledTextCtrl_PositionFromPoint, 3001). +-define(wxStyledTextCtrl_PositionFromPointClose, 3002). +-define(wxStyledTextCtrl_GotoLine, 3003). +-define(wxStyledTextCtrl_GotoPos, 3004). +-define(wxStyledTextCtrl_SetAnchor, 3005). +-define(wxStyledTextCtrl_GetCurLine, 3006). +-define(wxStyledTextCtrl_GetEndStyled, 3007). +-define(wxStyledTextCtrl_ConvertEOLs, 3008). +-define(wxStyledTextCtrl_GetEOLMode, 3009). +-define(wxStyledTextCtrl_SetEOLMode, 3010). +-define(wxStyledTextCtrl_StartStyling, 3011). +-define(wxStyledTextCtrl_SetStyling, 3012). +-define(wxStyledTextCtrl_GetBufferedDraw, 3013). +-define(wxStyledTextCtrl_SetBufferedDraw, 3014). +-define(wxStyledTextCtrl_SetTabWidth, 3015). +-define(wxStyledTextCtrl_GetTabWidth, 3016). +-define(wxStyledTextCtrl_SetCodePage, 3017). +-define(wxStyledTextCtrl_MarkerDefine, 3018). +-define(wxStyledTextCtrl_MarkerSetForeground, 3019). +-define(wxStyledTextCtrl_MarkerSetBackground, 3020). +-define(wxStyledTextCtrl_MarkerAdd, 3021). +-define(wxStyledTextCtrl_MarkerDelete, 3022). +-define(wxStyledTextCtrl_MarkerDeleteAll, 3023). +-define(wxStyledTextCtrl_MarkerGet, 3024). +-define(wxStyledTextCtrl_MarkerNext, 3025). +-define(wxStyledTextCtrl_MarkerPrevious, 3026). +-define(wxStyledTextCtrl_MarkerDefineBitmap, 3027). +-define(wxStyledTextCtrl_MarkerAddSet, 3028). +-define(wxStyledTextCtrl_MarkerSetAlpha, 3029). +-define(wxStyledTextCtrl_SetMarginType, 3030). +-define(wxStyledTextCtrl_GetMarginType, 3031). +-define(wxStyledTextCtrl_SetMarginWidth, 3032). +-define(wxStyledTextCtrl_GetMarginWidth, 3033). +-define(wxStyledTextCtrl_SetMarginMask, 3034). +-define(wxStyledTextCtrl_GetMarginMask, 3035). +-define(wxStyledTextCtrl_SetMarginSensitive, 3036). +-define(wxStyledTextCtrl_GetMarginSensitive, 3037). +-define(wxStyledTextCtrl_StyleClearAll, 3038). +-define(wxStyledTextCtrl_StyleSetForeground, 3039). +-define(wxStyledTextCtrl_StyleSetBackground, 3040). +-define(wxStyledTextCtrl_StyleSetBold, 3041). +-define(wxStyledTextCtrl_StyleSetItalic, 3042). +-define(wxStyledTextCtrl_StyleSetSize, 3043). +-define(wxStyledTextCtrl_StyleSetFaceName, 3044). +-define(wxStyledTextCtrl_StyleSetEOLFilled, 3045). +-define(wxStyledTextCtrl_StyleResetDefault, 3046). +-define(wxStyledTextCtrl_StyleSetUnderline, 3047). +-define(wxStyledTextCtrl_StyleSetCase, 3048). +-define(wxStyledTextCtrl_StyleSetHotSpot, 3049). +-define(wxStyledTextCtrl_SetSelForeground, 3050). +-define(wxStyledTextCtrl_SetSelBackground, 3051). +-define(wxStyledTextCtrl_GetSelAlpha, 3052). +-define(wxStyledTextCtrl_SetSelAlpha, 3053). +-define(wxStyledTextCtrl_SetCaretForeground, 3054). +-define(wxStyledTextCtrl_CmdKeyAssign, 3055). +-define(wxStyledTextCtrl_CmdKeyClear, 3056). +-define(wxStyledTextCtrl_CmdKeyClearAll, 3057). +-define(wxStyledTextCtrl_SetStyleBytes, 3058). +-define(wxStyledTextCtrl_StyleSetVisible, 3059). +-define(wxStyledTextCtrl_GetCaretPeriod, 3060). +-define(wxStyledTextCtrl_SetCaretPeriod, 3061). +-define(wxStyledTextCtrl_SetWordChars, 3062). +-define(wxStyledTextCtrl_BeginUndoAction, 3063). +-define(wxStyledTextCtrl_EndUndoAction, 3064). +-define(wxStyledTextCtrl_IndicatorSetStyle, 3065). +-define(wxStyledTextCtrl_IndicatorGetStyle, 3066). +-define(wxStyledTextCtrl_IndicatorSetForeground, 3067). +-define(wxStyledTextCtrl_IndicatorGetForeground, 3068). +-define(wxStyledTextCtrl_SetWhitespaceForeground, 3069). +-define(wxStyledTextCtrl_SetWhitespaceBackground, 3070). +-define(wxStyledTextCtrl_GetStyleBits, 3071). +-define(wxStyledTextCtrl_SetLineState, 3072). +-define(wxStyledTextCtrl_GetLineState, 3073). +-define(wxStyledTextCtrl_GetMaxLineState, 3074). +-define(wxStyledTextCtrl_GetCaretLineVisible, 3075). +-define(wxStyledTextCtrl_SetCaretLineVisible, 3076). +-define(wxStyledTextCtrl_GetCaretLineBackground, 3077). +-define(wxStyledTextCtrl_SetCaretLineBackground, 3078). +-define(wxStyledTextCtrl_AutoCompShow, 3079). +-define(wxStyledTextCtrl_AutoCompCancel, 3080). +-define(wxStyledTextCtrl_AutoCompActive, 3081). +-define(wxStyledTextCtrl_AutoCompPosStart, 3082). +-define(wxStyledTextCtrl_AutoCompComplete, 3083). +-define(wxStyledTextCtrl_AutoCompStops, 3084). +-define(wxStyledTextCtrl_AutoCompSetSeparator, 3085). +-define(wxStyledTextCtrl_AutoCompGetSeparator, 3086). +-define(wxStyledTextCtrl_AutoCompSelect, 3087). +-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3088). +-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3089). +-define(wxStyledTextCtrl_AutoCompSetFillUps, 3090). +-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3091). +-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3092). +-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3093). +-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3094). +-define(wxStyledTextCtrl_UserListShow, 3095). +-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3096). +-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3097). +-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3098). +-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3099). +-define(wxStyledTextCtrl_RegisterImage, 3100). +-define(wxStyledTextCtrl_ClearRegisteredImages, 3101). +-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3102). +-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3103). +-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3104). +-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3105). +-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3106). +-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3107). +-define(wxStyledTextCtrl_SetIndent, 3108). +-define(wxStyledTextCtrl_GetIndent, 3109). +-define(wxStyledTextCtrl_SetUseTabs, 3110). +-define(wxStyledTextCtrl_GetUseTabs, 3111). +-define(wxStyledTextCtrl_SetLineIndentation, 3112). +-define(wxStyledTextCtrl_GetLineIndentation, 3113). +-define(wxStyledTextCtrl_GetLineIndentPosition, 3114). +-define(wxStyledTextCtrl_GetColumn, 3115). +-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3116). +-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3117). +-define(wxStyledTextCtrl_SetIndentationGuides, 3118). +-define(wxStyledTextCtrl_GetIndentationGuides, 3119). +-define(wxStyledTextCtrl_SetHighlightGuide, 3120). +-define(wxStyledTextCtrl_GetHighlightGuide, 3121). +-define(wxStyledTextCtrl_GetLineEndPosition, 3122). +-define(wxStyledTextCtrl_GetCodePage, 3123). +-define(wxStyledTextCtrl_GetCaretForeground, 3124). +-define(wxStyledTextCtrl_GetReadOnly, 3125). +-define(wxStyledTextCtrl_SetCurrentPos, 3126). +-define(wxStyledTextCtrl_SetSelectionStart, 3127). +-define(wxStyledTextCtrl_GetSelectionStart, 3128). +-define(wxStyledTextCtrl_SetSelectionEnd, 3129). +-define(wxStyledTextCtrl_GetSelectionEnd, 3130). +-define(wxStyledTextCtrl_SetPrintMagnification, 3131). +-define(wxStyledTextCtrl_GetPrintMagnification, 3132). +-define(wxStyledTextCtrl_SetPrintColourMode, 3133). +-define(wxStyledTextCtrl_GetPrintColourMode, 3134). +-define(wxStyledTextCtrl_FindText, 3135). +-define(wxStyledTextCtrl_FormatRange, 3136). +-define(wxStyledTextCtrl_GetFirstVisibleLine, 3137). +-define(wxStyledTextCtrl_GetLine, 3138). +-define(wxStyledTextCtrl_GetLineCount, 3139). +-define(wxStyledTextCtrl_SetMarginLeft, 3140). +-define(wxStyledTextCtrl_GetMarginLeft, 3141). +-define(wxStyledTextCtrl_SetMarginRight, 3142). +-define(wxStyledTextCtrl_GetMarginRight, 3143). +-define(wxStyledTextCtrl_GetModify, 3144). +-define(wxStyledTextCtrl_SetSelection, 3145). +-define(wxStyledTextCtrl_GetSelectedText, 3146). +-define(wxStyledTextCtrl_GetTextRange, 3147). +-define(wxStyledTextCtrl_HideSelection, 3148). +-define(wxStyledTextCtrl_LineFromPosition, 3149). +-define(wxStyledTextCtrl_PositionFromLine, 3150). +-define(wxStyledTextCtrl_LineScroll, 3151). +-define(wxStyledTextCtrl_EnsureCaretVisible, 3152). +-define(wxStyledTextCtrl_ReplaceSelection, 3153). +-define(wxStyledTextCtrl_SetReadOnly, 3154). +-define(wxStyledTextCtrl_CanPaste, 3155). +-define(wxStyledTextCtrl_CanUndo, 3156). +-define(wxStyledTextCtrl_EmptyUndoBuffer, 3157). +-define(wxStyledTextCtrl_Undo, 3158). +-define(wxStyledTextCtrl_Cut, 3159). +-define(wxStyledTextCtrl_Copy, 3160). +-define(wxStyledTextCtrl_Paste, 3161). +-define(wxStyledTextCtrl_Clear, 3162). +-define(wxStyledTextCtrl_SetText, 3163). +-define(wxStyledTextCtrl_GetText, 3164). +-define(wxStyledTextCtrl_GetTextLength, 3165). +-define(wxStyledTextCtrl_GetOvertype, 3166). +-define(wxStyledTextCtrl_SetCaretWidth, 3167). +-define(wxStyledTextCtrl_GetCaretWidth, 3168). +-define(wxStyledTextCtrl_SetTargetStart, 3169). +-define(wxStyledTextCtrl_GetTargetStart, 3170). +-define(wxStyledTextCtrl_SetTargetEnd, 3171). +-define(wxStyledTextCtrl_GetTargetEnd, 3172). +-define(wxStyledTextCtrl_ReplaceTarget, 3173). +-define(wxStyledTextCtrl_SearchInTarget, 3174). +-define(wxStyledTextCtrl_SetSearchFlags, 3175). +-define(wxStyledTextCtrl_GetSearchFlags, 3176). +-define(wxStyledTextCtrl_CallTipShow, 3177). +-define(wxStyledTextCtrl_CallTipCancel, 3178). +-define(wxStyledTextCtrl_CallTipActive, 3179). +-define(wxStyledTextCtrl_CallTipPosAtStart, 3180). +-define(wxStyledTextCtrl_CallTipSetHighlight, 3181). +-define(wxStyledTextCtrl_CallTipSetBackground, 3182). +-define(wxStyledTextCtrl_CallTipSetForeground, 3183). +-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3184). +-define(wxStyledTextCtrl_CallTipUseStyle, 3185). +-define(wxStyledTextCtrl_VisibleFromDocLine, 3186). +-define(wxStyledTextCtrl_DocLineFromVisible, 3187). +-define(wxStyledTextCtrl_WrapCount, 3188). +-define(wxStyledTextCtrl_SetFoldLevel, 3189). +-define(wxStyledTextCtrl_GetFoldLevel, 3190). +-define(wxStyledTextCtrl_GetLastChild, 3191). +-define(wxStyledTextCtrl_GetFoldParent, 3192). +-define(wxStyledTextCtrl_ShowLines, 3193). +-define(wxStyledTextCtrl_HideLines, 3194). +-define(wxStyledTextCtrl_GetLineVisible, 3195). +-define(wxStyledTextCtrl_SetFoldExpanded, 3196). +-define(wxStyledTextCtrl_GetFoldExpanded, 3197). +-define(wxStyledTextCtrl_ToggleFold, 3198). +-define(wxStyledTextCtrl_EnsureVisible, 3199). +-define(wxStyledTextCtrl_SetFoldFlags, 3200). +-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3201). +-define(wxStyledTextCtrl_SetTabIndents, 3202). +-define(wxStyledTextCtrl_GetTabIndents, 3203). +-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3204). +-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3205). +-define(wxStyledTextCtrl_SetMouseDwellTime, 3206). +-define(wxStyledTextCtrl_GetMouseDwellTime, 3207). +-define(wxStyledTextCtrl_WordStartPosition, 3208). +-define(wxStyledTextCtrl_WordEndPosition, 3209). +-define(wxStyledTextCtrl_SetWrapMode, 3210). +-define(wxStyledTextCtrl_GetWrapMode, 3211). +-define(wxStyledTextCtrl_SetWrapVisualFlags, 3212). +-define(wxStyledTextCtrl_GetWrapVisualFlags, 3213). +-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3214). +-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3215). +-define(wxStyledTextCtrl_SetWrapStartIndent, 3216). +-define(wxStyledTextCtrl_GetWrapStartIndent, 3217). +-define(wxStyledTextCtrl_SetLayoutCache, 3218). +-define(wxStyledTextCtrl_GetLayoutCache, 3219). +-define(wxStyledTextCtrl_SetScrollWidth, 3220). +-define(wxStyledTextCtrl_GetScrollWidth, 3221). +-define(wxStyledTextCtrl_TextWidth, 3222). +-define(wxStyledTextCtrl_GetEndAtLastLine, 3223). +-define(wxStyledTextCtrl_TextHeight, 3224). +-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3225). +-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3226). +-define(wxStyledTextCtrl_AppendText, 3227). +-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3228). +-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3229). +-define(wxStyledTextCtrl_TargetFromSelection, 3230). +-define(wxStyledTextCtrl_LinesJoin, 3231). +-define(wxStyledTextCtrl_LinesSplit, 3232). +-define(wxStyledTextCtrl_SetFoldMarginColour, 3233). +-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3234). +-define(wxStyledTextCtrl_LineDown, 3235). +-define(wxStyledTextCtrl_LineDownExtend, 3236). +-define(wxStyledTextCtrl_LineUp, 3237). +-define(wxStyledTextCtrl_LineUpExtend, 3238). +-define(wxStyledTextCtrl_CharLeft, 3239). +-define(wxStyledTextCtrl_CharLeftExtend, 3240). +-define(wxStyledTextCtrl_CharRight, 3241). +-define(wxStyledTextCtrl_CharRightExtend, 3242). +-define(wxStyledTextCtrl_WordLeft, 3243). +-define(wxStyledTextCtrl_WordLeftExtend, 3244). +-define(wxStyledTextCtrl_WordRight, 3245). +-define(wxStyledTextCtrl_WordRightExtend, 3246). +-define(wxStyledTextCtrl_Home, 3247). +-define(wxStyledTextCtrl_HomeExtend, 3248). +-define(wxStyledTextCtrl_LineEnd, 3249). +-define(wxStyledTextCtrl_LineEndExtend, 3250). +-define(wxStyledTextCtrl_DocumentStart, 3251). +-define(wxStyledTextCtrl_DocumentStartExtend, 3252). +-define(wxStyledTextCtrl_DocumentEnd, 3253). +-define(wxStyledTextCtrl_DocumentEndExtend, 3254). +-define(wxStyledTextCtrl_PageUp, 3255). +-define(wxStyledTextCtrl_PageUpExtend, 3256). +-define(wxStyledTextCtrl_PageDown, 3257). +-define(wxStyledTextCtrl_PageDownExtend, 3258). +-define(wxStyledTextCtrl_EditToggleOvertype, 3259). +-define(wxStyledTextCtrl_Cancel, 3260). +-define(wxStyledTextCtrl_DeleteBack, 3261). +-define(wxStyledTextCtrl_Tab, 3262). +-define(wxStyledTextCtrl_BackTab, 3263). +-define(wxStyledTextCtrl_NewLine, 3264). +-define(wxStyledTextCtrl_FormFeed, 3265). +-define(wxStyledTextCtrl_VCHome, 3266). +-define(wxStyledTextCtrl_VCHomeExtend, 3267). +-define(wxStyledTextCtrl_ZoomIn, 3268). +-define(wxStyledTextCtrl_ZoomOut, 3269). +-define(wxStyledTextCtrl_DelWordLeft, 3270). +-define(wxStyledTextCtrl_DelWordRight, 3271). +-define(wxStyledTextCtrl_LineCut, 3272). +-define(wxStyledTextCtrl_LineDelete, 3273). +-define(wxStyledTextCtrl_LineTranspose, 3274). +-define(wxStyledTextCtrl_LineDuplicate, 3275). +-define(wxStyledTextCtrl_LowerCase, 3276). +-define(wxStyledTextCtrl_UpperCase, 3277). +-define(wxStyledTextCtrl_LineScrollDown, 3278). +-define(wxStyledTextCtrl_LineScrollUp, 3279). +-define(wxStyledTextCtrl_DeleteBackNotLine, 3280). +-define(wxStyledTextCtrl_HomeDisplay, 3281). +-define(wxStyledTextCtrl_HomeDisplayExtend, 3282). +-define(wxStyledTextCtrl_LineEndDisplay, 3283). +-define(wxStyledTextCtrl_LineEndDisplayExtend, 3284). +-define(wxStyledTextCtrl_HomeWrapExtend, 3285). +-define(wxStyledTextCtrl_LineEndWrap, 3286). +-define(wxStyledTextCtrl_LineEndWrapExtend, 3287). +-define(wxStyledTextCtrl_VCHomeWrap, 3288). +-define(wxStyledTextCtrl_VCHomeWrapExtend, 3289). +-define(wxStyledTextCtrl_LineCopy, 3290). +-define(wxStyledTextCtrl_MoveCaretInsideView, 3291). +-define(wxStyledTextCtrl_LineLength, 3292). +-define(wxStyledTextCtrl_BraceHighlight, 3293). +-define(wxStyledTextCtrl_BraceBadLight, 3294). +-define(wxStyledTextCtrl_BraceMatch, 3295). +-define(wxStyledTextCtrl_GetViewEOL, 3296). +-define(wxStyledTextCtrl_SetViewEOL, 3297). +-define(wxStyledTextCtrl_SetModEventMask, 3298). +-define(wxStyledTextCtrl_GetEdgeColumn, 3299). +-define(wxStyledTextCtrl_SetEdgeColumn, 3300). +-define(wxStyledTextCtrl_SetEdgeMode, 3301). +-define(wxStyledTextCtrl_GetEdgeMode, 3302). +-define(wxStyledTextCtrl_GetEdgeColour, 3303). +-define(wxStyledTextCtrl_SetEdgeColour, 3304). +-define(wxStyledTextCtrl_SearchAnchor, 3305). +-define(wxStyledTextCtrl_SearchNext, 3306). +-define(wxStyledTextCtrl_SearchPrev, 3307). +-define(wxStyledTextCtrl_LinesOnScreen, 3308). +-define(wxStyledTextCtrl_UsePopUp, 3309). +-define(wxStyledTextCtrl_SelectionIsRectangle, 3310). +-define(wxStyledTextCtrl_SetZoom, 3311). +-define(wxStyledTextCtrl_GetZoom, 3312). +-define(wxStyledTextCtrl_GetModEventMask, 3313). +-define(wxStyledTextCtrl_SetSTCFocus, 3314). +-define(wxStyledTextCtrl_GetSTCFocus, 3315). +-define(wxStyledTextCtrl_SetStatus, 3316). +-define(wxStyledTextCtrl_GetStatus, 3317). +-define(wxStyledTextCtrl_SetMouseDownCaptures, 3318). +-define(wxStyledTextCtrl_GetMouseDownCaptures, 3319). +-define(wxStyledTextCtrl_SetSTCCursor, 3320). +-define(wxStyledTextCtrl_GetSTCCursor, 3321). +-define(wxStyledTextCtrl_SetControlCharSymbol, 3322). +-define(wxStyledTextCtrl_GetControlCharSymbol, 3323). +-define(wxStyledTextCtrl_WordPartLeft, 3324). +-define(wxStyledTextCtrl_WordPartLeftExtend, 3325). +-define(wxStyledTextCtrl_WordPartRight, 3326). +-define(wxStyledTextCtrl_WordPartRightExtend, 3327). +-define(wxStyledTextCtrl_SetVisiblePolicy, 3328). +-define(wxStyledTextCtrl_DelLineLeft, 3329). +-define(wxStyledTextCtrl_DelLineRight, 3330). +-define(wxStyledTextCtrl_GetXOffset, 3331). +-define(wxStyledTextCtrl_ChooseCaretX, 3332). +-define(wxStyledTextCtrl_SetXCaretPolicy, 3333). +-define(wxStyledTextCtrl_SetYCaretPolicy, 3334). +-define(wxStyledTextCtrl_GetPrintWrapMode, 3335). +-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3336). +-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3337). +-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3338). +-define(wxStyledTextCtrl_SetHotspotSingleLine, 3339). +-define(wxStyledTextCtrl_ParaDownExtend, 3340). +-define(wxStyledTextCtrl_ParaUp, 3341). +-define(wxStyledTextCtrl_ParaUpExtend, 3342). +-define(wxStyledTextCtrl_PositionBefore, 3343). +-define(wxStyledTextCtrl_PositionAfter, 3344). +-define(wxStyledTextCtrl_CopyRange, 3345). +-define(wxStyledTextCtrl_CopyText, 3346). +-define(wxStyledTextCtrl_SetSelectionMode, 3347). +-define(wxStyledTextCtrl_GetSelectionMode, 3348). +-define(wxStyledTextCtrl_LineDownRectExtend, 3349). +-define(wxStyledTextCtrl_LineUpRectExtend, 3350). +-define(wxStyledTextCtrl_CharLeftRectExtend, 3351). +-define(wxStyledTextCtrl_CharRightRectExtend, 3352). +-define(wxStyledTextCtrl_HomeRectExtend, 3353). +-define(wxStyledTextCtrl_VCHomeRectExtend, 3354). +-define(wxStyledTextCtrl_LineEndRectExtend, 3355). +-define(wxStyledTextCtrl_PageUpRectExtend, 3356). +-define(wxStyledTextCtrl_PageDownRectExtend, 3357). +-define(wxStyledTextCtrl_StutteredPageUp, 3358). +-define(wxStyledTextCtrl_StutteredPageUpExtend, 3359). +-define(wxStyledTextCtrl_StutteredPageDown, 3360). +-define(wxStyledTextCtrl_StutteredPageDownExtend, 3361). +-define(wxStyledTextCtrl_WordLeftEnd, 3362). +-define(wxStyledTextCtrl_WordLeftEndExtend, 3363). +-define(wxStyledTextCtrl_WordRightEnd, 3364). +-define(wxStyledTextCtrl_WordRightEndExtend, 3365). +-define(wxStyledTextCtrl_SetWhitespaceChars, 3366). +-define(wxStyledTextCtrl_SetCharsDefault, 3367). +-define(wxStyledTextCtrl_AutoCompGetCurrent, 3368). +-define(wxStyledTextCtrl_Allocate, 3369). +-define(wxStyledTextCtrl_FindColumn, 3370). +-define(wxStyledTextCtrl_GetCaretSticky, 3371). +-define(wxStyledTextCtrl_SetCaretSticky, 3372). +-define(wxStyledTextCtrl_ToggleCaretSticky, 3373). +-define(wxStyledTextCtrl_SetPasteConvertEndings, 3374). +-define(wxStyledTextCtrl_GetPasteConvertEndings, 3375). +-define(wxStyledTextCtrl_SelectionDuplicate, 3376). +-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3377). +-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3378). +-define(wxStyledTextCtrl_StartRecord, 3379). +-define(wxStyledTextCtrl_StopRecord, 3380). +-define(wxStyledTextCtrl_SetLexer, 3381). +-define(wxStyledTextCtrl_GetLexer, 3382). +-define(wxStyledTextCtrl_Colourise, 3383). +-define(wxStyledTextCtrl_SetProperty, 3384). +-define(wxStyledTextCtrl_SetKeyWords, 3385). +-define(wxStyledTextCtrl_SetLexerLanguage, 3386). +-define(wxStyledTextCtrl_GetProperty, 3387). +-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3388). +-define(wxStyledTextCtrl_GetCurrentLine, 3389). +-define(wxStyledTextCtrl_StyleSetSpec, 3390). +-define(wxStyledTextCtrl_StyleSetFont, 3391). +-define(wxStyledTextCtrl_StyleSetFontAttr, 3392). +-define(wxStyledTextCtrl_StyleSetCharacterSet, 3393). +-define(wxStyledTextCtrl_StyleSetFontEncoding, 3394). +-define(wxStyledTextCtrl_CmdKeyExecute, 3395). +-define(wxStyledTextCtrl_SetMargins, 3396). +-define(wxStyledTextCtrl_GetSelection, 3397). +-define(wxStyledTextCtrl_PointFromPosition, 3398). +-define(wxStyledTextCtrl_ScrollToLine, 3399). +-define(wxStyledTextCtrl_ScrollToColumn, 3400). +-define(wxStyledTextCtrl_SetVScrollBar, 3401). +-define(wxStyledTextCtrl_SetHScrollBar, 3402). +-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3403). +-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3404). +-define(wxStyledTextCtrl_SaveFile, 3405). +-define(wxStyledTextCtrl_LoadFile, 3406). +-define(wxStyledTextCtrl_DoDragOver, 3407). +-define(wxStyledTextCtrl_DoDropText, 3408). +-define(wxStyledTextCtrl_GetUseAntiAliasing, 3409). +-define(wxStyledTextCtrl_AddTextRaw, 3410). +-define(wxStyledTextCtrl_InsertTextRaw, 3411). +-define(wxStyledTextCtrl_GetCurLineRaw, 3412). +-define(wxStyledTextCtrl_GetLineRaw, 3413). +-define(wxStyledTextCtrl_GetSelectedTextRaw, 3414). +-define(wxStyledTextCtrl_GetTextRangeRaw, 3415). +-define(wxStyledTextCtrl_SetTextRaw, 3416). +-define(wxStyledTextCtrl_GetTextRaw, 3417). +-define(wxStyledTextCtrl_AppendTextRaw, 3418). +-define(wxArtProvider_GetBitmap, 3419). +-define(wxArtProvider_GetIcon, 3420). +-define(wxTreeEvent_GetKeyCode, 3421). +-define(wxTreeEvent_GetItem, 3422). +-define(wxTreeEvent_GetKeyEvent, 3423). +-define(wxTreeEvent_GetLabel, 3424). +-define(wxTreeEvent_GetOldItem, 3425). +-define(wxTreeEvent_GetPoint, 3426). +-define(wxTreeEvent_IsEditCancelled, 3427). +-define(wxTreeEvent_SetToolTip, 3428). +-define(wxNotebookEvent_GetOldSelection, 3429). +-define(wxNotebookEvent_GetSelection, 3430). +-define(wxNotebookEvent_SetOldSelection, 3431). +-define(wxNotebookEvent_SetSelection, 3432). +-define(wxFileDataObject_new, 3433). +-define(wxFileDataObject_AddFile, 3434). +-define(wxFileDataObject_GetFilenames, 3435). +-define(wxFileDataObject_destroy, 3436). +-define(wxTextDataObject_new, 3437). +-define(wxTextDataObject_GetTextLength, 3438). +-define(wxTextDataObject_GetText, 3439). +-define(wxTextDataObject_SetText, 3440). +-define(wxTextDataObject_destroy, 3441). +-define(wxBitmapDataObject_new_1_1, 3442). +-define(wxBitmapDataObject_new_1_0, 3443). +-define(wxBitmapDataObject_GetBitmap, 3444). +-define(wxBitmapDataObject_SetBitmap, 3445). +-define(wxBitmapDataObject_destroy, 3446). +-define(wxClipboard_new, 3448). +-define(wxClipboard_destruct, 3449). +-define(wxClipboard_AddData, 3450). +-define(wxClipboard_Clear, 3451). +-define(wxClipboard_Close, 3452). +-define(wxClipboard_Flush, 3453). +-define(wxClipboard_GetData, 3454). +-define(wxClipboard_IsOpened, 3455). +-define(wxClipboard_Open, 3456). +-define(wxClipboard_SetData, 3457). +-define(wxClipboard_UsePrimarySelection, 3459). +-define(wxClipboard_IsSupported, 3460). +-define(wxClipboard_Get, 3461). +-define(wxSpinEvent_GetPosition, 3462). +-define(wxSpinEvent_SetPosition, 3463). +-define(wxSplitterWindow_new_0, 3464). +-define(wxSplitterWindow_new_2, 3465). +-define(wxSplitterWindow_destruct, 3466). +-define(wxSplitterWindow_Create, 3467). +-define(wxSplitterWindow_GetMinimumPaneSize, 3468). +-define(wxSplitterWindow_GetSashGravity, 3469). +-define(wxSplitterWindow_GetSashPosition, 3470). +-define(wxSplitterWindow_GetSplitMode, 3471). +-define(wxSplitterWindow_GetWindow1, 3472). +-define(wxSplitterWindow_GetWindow2, 3473). +-define(wxSplitterWindow_Initialize, 3474). +-define(wxSplitterWindow_IsSplit, 3475). +-define(wxSplitterWindow_ReplaceWindow, 3476). +-define(wxSplitterWindow_SetSashGravity, 3477). +-define(wxSplitterWindow_SetSashPosition, 3478). +-define(wxSplitterWindow_SetSashSize, 3479). +-define(wxSplitterWindow_SetMinimumPaneSize, 3480). +-define(wxSplitterWindow_SetSplitMode, 3481). +-define(wxSplitterWindow_SplitHorizontally, 3482). +-define(wxSplitterWindow_SplitVertically, 3483). +-define(wxSplitterWindow_Unsplit, 3484). +-define(wxSplitterWindow_UpdateSize, 3485). +-define(wxSplitterEvent_GetSashPosition, 3486). +-define(wxSplitterEvent_GetX, 3487). +-define(wxSplitterEvent_GetY, 3488). +-define(wxSplitterEvent_GetWindowBeingRemoved, 3489). +-define(wxSplitterEvent_SetSashPosition, 3490). +-define(wxHtmlWindow_new_0, 3491). +-define(wxHtmlWindow_new_2, 3492). +-define(wxHtmlWindow_AppendToPage, 3493). +-define(wxHtmlWindow_GetOpenedAnchor, 3494). +-define(wxHtmlWindow_GetOpenedPage, 3495). +-define(wxHtmlWindow_GetOpenedPageTitle, 3496). +-define(wxHtmlWindow_GetRelatedFrame, 3497). +-define(wxHtmlWindow_HistoryBack, 3498). +-define(wxHtmlWindow_HistoryCanBack, 3499). +-define(wxHtmlWindow_HistoryCanForward, 3500). +-define(wxHtmlWindow_HistoryClear, 3501). +-define(wxHtmlWindow_HistoryForward, 3502). +-define(wxHtmlWindow_LoadFile, 3503). +-define(wxHtmlWindow_LoadPage, 3504). +-define(wxHtmlWindow_SelectAll, 3505). +-define(wxHtmlWindow_SelectionToText, 3506). +-define(wxHtmlWindow_SelectLine, 3507). +-define(wxHtmlWindow_SelectWord, 3508). +-define(wxHtmlWindow_SetBorders, 3509). +-define(wxHtmlWindow_SetFonts, 3510). +-define(wxHtmlWindow_SetPage, 3511). +-define(wxHtmlWindow_SetRelatedFrame, 3512). +-define(wxHtmlWindow_SetRelatedStatusBar, 3513). +-define(wxHtmlWindow_ToText, 3514). +-define(wxHtmlWindow_destroy, 3515). +-define(wxHtmlLinkEvent_GetLinkInfo, 3516). +-define(wxSystemSettings_GetColour, 3517). +-define(wxSystemSettings_GetFont, 3518). +-define(wxSystemSettings_GetMetric, 3519). +-define(wxSystemSettings_GetScreenType, 3520). +-define(wxSystemOptions_GetOption, 3521). +-define(wxSystemOptions_GetOptionInt, 3522). +-define(wxSystemOptions_HasOption, 3523). +-define(wxSystemOptions_IsFalse, 3524). +-define(wxSystemOptions_SetOption_2_1, 3525). +-define(wxSystemOptions_SetOption_2_0, 3526). +-define(wxAuiNotebookEvent_SetSelection, 3527). +-define(wxAuiNotebookEvent_GetSelection, 3528). +-define(wxAuiNotebookEvent_SetOldSelection, 3529). +-define(wxAuiNotebookEvent_GetOldSelection, 3530). +-define(wxAuiNotebookEvent_SetDragSource, 3531). +-define(wxAuiNotebookEvent_GetDragSource, 3532). +-define(wxAuiManagerEvent_SetManager, 3533). +-define(wxAuiManagerEvent_GetManager, 3534). +-define(wxAuiManagerEvent_SetPane, 3535). +-define(wxAuiManagerEvent_GetPane, 3536). +-define(wxAuiManagerEvent_SetButton, 3537). +-define(wxAuiManagerEvent_GetButton, 3538). +-define(wxAuiManagerEvent_SetDC, 3539). +-define(wxAuiManagerEvent_GetDC, 3540). +-define(wxAuiManagerEvent_Veto, 3541). +-define(wxAuiManagerEvent_GetVeto, 3542). +-define(wxAuiManagerEvent_SetCanVeto, 3543). +-define(wxAuiManagerEvent_CanVeto, 3544). +-define(wxLogNull_new, 3545). +-define(wxLogNull_destroy, 3546). +-define(wxTaskBarIcon_new, 3547). +-define(wxTaskBarIcon_destruct, 3548). +-define(wxTaskBarIcon_PopupMenu, 3549). +-define(wxTaskBarIcon_RemoveIcon, 3550). +-define(wxTaskBarIcon_SetIcon, 3551). +-define(wxLocale_new_0, 3552). +-define(wxLocale_new_2, 3554). +-define(wxLocale_destruct, 3555). +-define(wxLocale_Init, 3557). +-define(wxLocale_AddCatalog_1, 3558). +-define(wxLocale_AddCatalog_3, 3559). +-define(wxLocale_AddCatalogLookupPathPrefix, 3560). +-define(wxLocale_GetCanonicalName, 3561). +-define(wxLocale_GetLanguage, 3562). +-define(wxLocale_GetLanguageName, 3563). +-define(wxLocale_GetLocale, 3564). +-define(wxLocale_GetName, 3565). +-define(wxLocale_GetString_2, 3566). +-define(wxLocale_GetString_4, 3567). +-define(wxLocale_GetHeaderValue, 3568). +-define(wxLocale_GetSysName, 3569). +-define(wxLocale_GetSystemEncoding, 3570). +-define(wxLocale_GetSystemEncodingName, 3571). +-define(wxLocale_GetSystemLanguage, 3572). +-define(wxLocale_IsLoaded, 3573). +-define(wxLocale_IsOk, 3574). +-define(wxActivateEvent_GetActive, 3575). +-define(wxPopupWindow_new_2, 3577). +-define(wxPopupWindow_new_0, 3578). +-define(wxPopupWindow_destruct, 3580). +-define(wxPopupWindow_Create, 3581). +-define(wxPopupWindow_Position, 3582). +-define(wxPopupTransientWindow_new_0, 3583). +-define(wxPopupTransientWindow_new_2, 3584). +-define(wxPopupTransientWindow_destruct, 3585). +-define(wxPopupTransientWindow_Popup, 3586). +-define(wxPopupTransientWindow_Dismiss, 3587). +-define(wxOverlay_new, 3588). +-define(wxOverlay_destruct, 3589). +-define(wxOverlay_Reset, 3590). +-define(wxDCOverlay_new_6, 3591). +-define(wxDCOverlay_new_2, 3592). +-define(wxDCOverlay_destruct, 3593). +-define(wxDCOverlay_Clear, 3594). diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index 93a4c24a84..876db9893f 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -526,14 +526,19 @@ toolbar(Config) -> Wx = wx:new(), Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"), TB = wxFrame:createToolBar(Frame), - wxToolBar:addTool(TB, 747, "PressMe", wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}]), + BM1 = wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}, {client, "wxART_TOOLBAR"}]), + BM2 = wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}, {client, "wxART_TOOLBAR"}]), + wxToolBar:addTool(TB, 747, "PressMe", BM1, [{shortHelp, "Press Me"}]), - + catch wxToolBar:addStretchableSpace(TB), %% wxWidgets 3.0 only Add = fun(#wx{}, _) -> - wxToolBar:addTool(TB, -1, "Added", wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}]), - [{shortHelp, "Test 2 popup text"}]) + wxToolBar:addTool(TB, -1, "Added", BM2, + [{shortHelp, "Test 2 popup text"}]), + catch wxToolBar:addStretchableSpace(TB), %% wxWidgets 3.0 only + wxToolBar:realize(TB) end, + wxToolBar:realize(TB), wxFrame:connect(Frame, command_menu_selected, [{callback, Add}, {id, 747}]), wxFrame:show(Frame), wx_test_lib:wx_destroy(Frame,Config). -- cgit v1.2.3 From 52701a71707e44bef90c7ad8db8dc8a0f9a1feaf Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 7 Dec 2015 14:38:22 +0100 Subject: ssh: Add testcase precondition --- lib/ssh/test/ssh_to_openssh_SUITE.erl | 80 +++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index d1dfa2efdf..18690d8669 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -96,19 +96,9 @@ end_per_group(_, Config) -> init_per_testcase(erlang_server_openssh_client_public_key_dsa, Config) -> - case ssh_test_lib:openssh_supports(sshc, public_key, 'ssh-dss') of - true -> - init_per_testcase('__default__',Config); - false -> - {skip,"openssh client does not support DSA"} - end; + chk_key(sshc, 'ssh-dss', ".ssh/id_dsa", Config); init_per_testcase(erlang_client_openssh_server_publickey_dsa, Config) -> - case ssh_test_lib:openssh_supports(sshd, public_key, 'ssh-dss') of - true -> - init_per_testcase('__default__',Config); - false -> - {skip,"openssh client does not support DSA"} - end; + chk_key(sshd, 'ssh-dss', ".ssh/id_dsa", Config); init_per_testcase(_TestCase, Config) -> ssh:start(), Config. @@ -117,6 +107,27 @@ end_per_testcase(_TestCase, _Config) -> ssh:stop(), ok. + +chk_key(Pgm, Name, File, Config) -> + case ssh_test_lib:openssh_supports(Pgm, public_key, Name) of + true -> + {skip,lists:concat(["openssh client does not support ",Name])}; + false -> + {ok,[[Home]]} = init:get_argument(home), + KeyFile = filename:join(Home, File), + case file:read_file(KeyFile) of + {ok, Pem} -> + case public_key:pem_decode(Pem) of + [{_,_, not_encrypted}] -> + init_per_testcase('__default__',Config); + _ -> + {skip, {error, "Has pass phrase can not be used by automated test case"}} + end; + _ -> + {skip, lists:concat(["no ~/",File])} + end + end. + %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- @@ -328,27 +339,16 @@ erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) -> erlang_client_openssh_server_publickey_dsa() -> [{doc, "Validate using dsa publickey."}]. erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) -> - {ok,[[Home]]} = init:get_argument(home), - KeyFile = filename:join(Home, ".ssh/id_dsa"), - case file:read_file(KeyFile) of - {ok, Pem} -> - case public_key:pem_decode(Pem) of - [{_,_, not_encrypted}] -> - ConnectionRef = - ssh_test_lib:connect(?SSH_DEFAULT_PORT, - [{public_key_alg, ssh_dsa}, - {user_interaction, false}, - silently_accept_hosts]), - {ok, Channel} = - ssh_connection:session_channel(ConnectionRef, infinity), - ok = ssh_connection:close(ConnectionRef, Channel), - ok = ssh:close(ConnectionRef); - _ -> - {skip, {error, "Has pass phrase can not be used by automated test case"}} - end; - _ -> - {skip, "no ~/.ssh/id_dsa"} - end. + ConnectionRef = + ssh_test_lib:connect(?SSH_DEFAULT_PORT, + [{public_key_alg, ssh_dsa}, + {user_interaction, false}, + silently_accept_hosts]), + {ok, Channel} = + ssh_connection:session_channel(ConnectionRef, infinity), + ok = ssh_connection:close(ConnectionRef, Channel), + ok = ssh:close(ConnectionRef). + %%-------------------------------------------------------------------- erlang_server_openssh_client_public_key_dsa() -> [{doc, "Validate using dsa publickey."}]. @@ -360,7 +360,7 @@ erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) -> {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {public_key_alg, ssh_dsa}, {failfun, fun ssh_test_lib:failfun/2}]), - + ct:sleep(500), Cmd = "ssh -p " ++ integer_to_list(Port) ++ @@ -369,12 +369,12 @@ erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) -> SshPort = open_port({spawn, Cmd}, [binary]), receive - {SshPort,{data, <<"2\n">>}} -> + {SshPort,{data, <<"2\n">>}} -> ok after ?TIMEOUT -> ct:fail("Did not receive answer") end, - ssh:stop_daemon(Pid). + ssh:stop_daemon(Pid). %%-------------------------------------------------------------------- erlang_client_openssh_server_password() -> @@ -384,10 +384,10 @@ erlang_client_openssh_server_password(Config) when is_list(Config) -> UserDir = ?config(data_dir, Config), {error, Reason0} = ssh:connect(any, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true}, - {user, "foo"}, - {password, "morot"}, - {user_interaction, false}, - {user_dir, UserDir}]), + {user, "foo"}, + {password, "morot"}, + {user_interaction, false}, + {user_dir, UserDir}]), ct:log("Test of user foo that does not exist. " "Error msg: ~p~n", [Reason0]), -- cgit v1.2.3 From b424835b0d08c9fdf2650782e481e3e7a08eb1ae Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 7 Dec 2015 15:06:49 +0100 Subject: ssh: add check for available ipv6 addr in test case --- lib/ssh/test/ssh_basic_SUITE.erl | 8 ++++++++ lib/ssh/test/ssh_test_lib.erl | 12 ++++++++++++ 2 files changed, 20 insertions(+) (limited to 'lib') diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 85a6bac972..6c4c215b3d 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -311,6 +311,14 @@ init_per_testcase(TC, Config) when TC==shell_no_unicode ; ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p", [file:native_name_encoding(),io:getopts()]), wait_for_erlang_first_line([{io,IO}, {shell,Shell}, {sftpd, Sftpd} | Config]); + +init_per_testcase(inet6_option, Config) -> + case ssh_test_lib:has_inet6_address() of + true -> + init_per_testcase('__default__', Config); + false -> + {skip,"No ipv6 interface address"} + end; init_per_testcase(_TestCase, Config) -> ssh:start(), Config. diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 424afc76fe..ed76f4f795 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -646,3 +646,15 @@ ssh_supports(Alg, SshDefaultAlg_tag) -> {false,UnSup} end end. + +%%%---------------------------------------------------------------- +has_inet6_address() -> + try + [throw(6) || {ok,L} <- [inet:getifaddrs()], + {_,L1} <- L, + {addr,{_,_,_,_,_,_,_,_}} <- L1] + of + [] -> false + catch + throw:6 -> true + end. -- cgit v1.2.3 From 7061105f5a8458486d43183a8b925c203b7a21fe Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 7 Dec 2015 15:15:33 +0100 Subject: ssh: add econnaborted as correct tcp disconnect reason in testcase --- lib/ssh/test/ssh_protocol_SUITE.erl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 4639904061..5af60adfae 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -279,7 +279,9 @@ no_common_alg_server_disconnects(Config) -> {send, ssh_msg_kexinit}, % with server unsupported 'ssh-dss' ! {match, {'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, - tcp_closed]}, + tcp_closed, + {tcp_error,econnaborted} + ]}, receive_msg} ] ). @@ -475,7 +477,8 @@ bad_packet_length(Config, LengthExcess) -> %% Prohibit remote decoder starvation: {send, #ssh_msg_service_request{name="ssh-userauth"}}, {match, {'or',[#ssh_msg_disconnect{_='_'}, - tcp_closed + tcp_closed, + {tcp_error,econnaborted} ]}, receive_msg} ], InitialState). @@ -507,7 +510,8 @@ bad_service_name_length(Config, LengthExcess) -> %% Prohibit remote decoder starvation: {send, #ssh_msg_service_request{name="ssh-userauth"}}, {match, {'or',[#ssh_msg_disconnect{_='_'}, - tcp_closed + tcp_closed, + {tcp_error,econnaborted} ]}, receive_msg} ], InitialState). -- cgit v1.2.3 From b8ac85a0673d06606c6523e4bb8f46e1034d0638 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 7 Dec 2015 18:38:54 +0100 Subject: ssh: fix error for bad packet lengths found by Defensics --- lib/ssh/src/ssh_connection_handler.erl | 20 ++++++++++++++++++-- lib/ssh/src/ssh_transport.erl | 5 +---- 2 files changed, 19 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 516a09bf6a..0eaeba26a9 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -999,7 +999,8 @@ handle_info({Protocol, Socket, Data}, StateName, encoded_data_buffer = EncData0, undecoded_packet_length = RemainingSshPacketLen0} = State0) -> Encoded = <>, - case ssh_transport:handle_packet_part(DecData0, Encoded, RemainingSshPacketLen0, Ssh0) of + try ssh_transport:handle_packet_part(DecData0, Encoded, RemainingSshPacketLen0, Ssh0) + of {get_more, DecBytes, EncDataRest, RemainingSshPacketLen, Ssh1} -> {next_state, StateName, next_packet(State0#state{encoded_data_buffer = EncDataRest, @@ -1021,7 +1022,22 @@ handle_info({Protocol, Socket, Data}, StateName, #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, description = "Bad mac", language = ""}, - handle_disconnect(DisconnectMsg, State0#state{ssh_params=Ssh1}) + handle_disconnect(DisconnectMsg, State0#state{ssh_params=Ssh1}); + + {error, {exceeds_max_size,PacketLen}} -> + DisconnectMsg = + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad packet length " + ++ integer_to_list(PacketLen), + language = ""}, + handle_disconnect(DisconnectMsg, State0) + catch + _:_ -> + DisconnectMsg = + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad packet", + language = ""}, + handle_disconnect(DisconnectMsg, State0) end; handle_info({CloseTag, _Socket}, _StateName, diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 67a0d29bb8..18037b8461 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -1004,10 +1004,7 @@ handle_packet_part(<<>>, Encrypted0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0 {ok, PacketLen, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE -> %% far too long message than expected - throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, - description = "Bad packet length " - ++ integer_to_list(PacketLen), - language = ""}); + {error, {exceeds_max_size,PacketLen}}; {ok, PacketLen, Decrypted, Encrypted1, #ssh{recv_mac_size = MacSize} = Ssh1} -> -- cgit v1.2.3 From 2ae91c3ade0538500ff4dbda29ad539e595f64df Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Oct 2015 20:10:46 +0200 Subject: erts: Change erts_internal:map_type/1 into term_type/1 to support other terms, not just maps --- lib/kernel/src/erts_debug.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 87f001fdf4..8e2b5ad214 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -243,7 +243,7 @@ map_size(Map,Seen0,Sum0) -> %% is not allowed to leak anywhere. They are only allowed in %% containers (cons cells and tuples, not maps), in gc and %% in erts_debug:same/2 - case erts_internal:map_type(Map) of + case erts_internal:term_type(Map) of flatmap -> Kt = erts_internal:map_to_tuple_keys(Map), Vs = maps:values(Map), -- cgit v1.2.3 From bb1a28deb139c34e2425e08e11f55480f5de6526 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 7 Dec 2015 19:39:28 +0100 Subject: ssh: fix error for data fields errors --- lib/ssh/src/ssh_connection_handler.erl | 80 +++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 0eaeba26a9..f082db136c 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1408,44 +1408,54 @@ generate_event(<> = Msg, StateName, Byte == ?SSH_MSG_CHANNEL_REQUEST; Byte == ?SSH_MSG_CHANNEL_SUCCESS; Byte == ?SSH_MSG_CHANNEL_FAILURE -> - ConnectionMsg = ssh_message:decode(Msg), - State1 = generate_event_new_state(State0, EncData), - try ssh_connection:handle_msg(ConnectionMsg, Connection0, Role) of - {{replies, Replies0}, Connection} -> - if StateName == connected -> - Replies = Replies0, - State2 = State1; - true -> - {ConnReplies, Replies} = - lists:splitwith(fun not_connected_filter/1, Replies0), - Q = State1#state.event_queue ++ ConnReplies, - State2 = State1#state{ event_queue = Q } - end, - State = send_replies(Replies, State2#state{connection_state = Connection}), - {next_state, StateName, next_packet(State)}; - {noreply, Connection} -> - {next_state, StateName, next_packet(State1#state{connection_state = Connection})}; - {disconnect, {_, Reason}, {{replies, Replies}, Connection}} when - Role == client andalso ((StateName =/= connected) and (not Renegotiation)) -> - State = send_replies(Replies, State1#state{connection_state = Connection}), - User ! {self(), not_connected, Reason}, - {stop, {shutdown, normal}, - next_packet(State#state{connection_state = Connection})}; - {disconnect, _Reason, {{replies, Replies}, Connection}} -> - State = send_replies(Replies, State1#state{connection_state = Connection}), - {stop, {shutdown, normal}, State#state{connection_state = Connection}} + try + ssh_message:decode(Msg) + of + ConnectionMsg -> + State1 = generate_event_new_state(State0, EncData), + try ssh_connection:handle_msg(ConnectionMsg, Connection0, Role) of + {{replies, Replies0}, Connection} -> + if StateName == connected -> + Replies = Replies0, + State2 = State1; + true -> + {ConnReplies, Replies} = + lists:splitwith(fun not_connected_filter/1, Replies0), + Q = State1#state.event_queue ++ ConnReplies, + State2 = State1#state{ event_queue = Q } + end, + State = send_replies(Replies, State2#state{connection_state = Connection}), + {next_state, StateName, next_packet(State)}; + {noreply, Connection} -> + {next_state, StateName, next_packet(State1#state{connection_state = Connection})}; + {disconnect, {_, Reason}, {{replies, Replies}, Connection}} when + Role == client andalso ((StateName =/= connected) and (not Renegotiation)) -> + State = send_replies(Replies, State1#state{connection_state = Connection}), + User ! {self(), not_connected, Reason}, + {stop, {shutdown, normal}, + next_packet(State#state{connection_state = Connection})}; + {disconnect, _Reason, {{replies, Replies}, Connection}} -> + State = send_replies(Replies, State1#state{connection_state = Connection}), + {stop, {shutdown, normal}, State#state{connection_state = Connection}} + catch + _:Error -> + {disconnect, _Reason, {{replies, Replies}, Connection}} = + ssh_connection:handle_msg( + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION, + description = "Internal error", + language = "en"}, Connection0, Role), + State = send_replies(Replies, State1#state{connection_state = Connection}), + {stop, {shutdown, Error}, State#state{connection_state = Connection}} + end + catch - _:Error -> - {disconnect, _Reason, {{replies, Replies}, Connection}} = - ssh_connection:handle_msg( - #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION, - description = "Internal error", - language = "en"}, Connection0, Role), - State = send_replies(Replies, State1#state{connection_state = Connection}), - {stop, {shutdown, Error}, State#state{connection_state = Connection}} + _:_ -> + handle_disconnect( + #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR, + description = "Bad packet received", + language = ""}, State0) end; - generate_event(Msg, StateName, State0, EncData) -> try Event = ssh_message:decode(set_prefix_if_trouble(Msg,State0)), -- cgit v1.2.3 From fb64cba70b4b08442e04c932f88579a35e219fdb Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 7 Dec 2015 11:10:35 +0100 Subject: ssl: Prepare for release --- lib/ssl/src/ssl.app.src | 2 +- lib/ssl/src/ssl.appup.src | 14 ++------------ lib/ssl/vsn.mk | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src index be8ef6f85f..619ab7b610 100644 --- a/lib/ssl/src/ssl.app.src +++ b/lib/ssl/src/ssl.app.src @@ -54,6 +54,6 @@ {env, []}, {mod, {ssl_app, []}}, {runtime_dependencies, ["stdlib-2.0","public_key-1.0","kernel-3.0", - "erts-6.0","crypto-3.3", "inets-5.10.7"]}]}. + "erts-7.0","crypto-3.3", "inets-5.10.7"]}]}. diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index 8d5bd6f8d8..11728128c4 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,24 +1,14 @@ %% -*- erlang -*- {"%VSN%", [ - {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, - {load_module, ssl_connection, soft_purge, soft_purge, []}, - {load_module, tls_connection, soft_purge, soft_purge, []}, - {load_module, ssl_session, soft_purge, soft_purge, []}, - {load_module, ssl_session_cache, soft_purge, soft_purge, []} - ]}, + {<<"7\\..*">>, [{restart_application, ssl}]}, {<<"6\\..*">>, [{restart_application, ssl}]}, {<<"5\\..*">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, {<<"3\\..*">>, [{restart_application, ssl}]} ], [ - {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []}, - {load_module, ssl_connection, soft_purge, soft_purge, []}, - {load_module, tls_connection, soft_purge, soft_purge, []}, - {load_module, ssl_session, soft_purge, soft_purge, []}, - {load_module, ssl_session_cache, soft_purge, soft_purge, []} - ]}, + {<<"7\\..*">>, [{restart_application, ssl}]}, {<<"6\\..*">>, [{restart_application, ssl}]}, {<<"5\\..*">>, [{restart_application, ssl}]}, {<<"4\\..*">>, [{restart_application, ssl}]}, diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 4587c448f6..aa1af21990 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 7.1 +SSL_VSN = 7.2 -- cgit v1.2.3 From 80bf91029f9afcef147493a449ad0ae328efb3ae Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 8 Dec 2015 14:59:28 +0100 Subject: ssl: Correct spec --- lib/ssl/src/tls_record.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl index 1e266ed424..9348c8bbdd 100644 --- a/lib/ssl/src/tls_record.erl +++ b/lib/ssl/src/tls_record.erl @@ -298,7 +298,7 @@ highest_protocol_version(_,Version) -> Version. %%-------------------------------------------------------------------- --spec is_higher(V1 :: tls_version(), V2::tls_version()) -> tls_version(). +-spec is_higher(V1 :: tls_version(), V2::tls_version()) -> boolean(). %% %% Description: Is V1 > V2 %%-------------------------------------------------------------------- -- cgit v1.2.3 From c1dd51bdc908ca5bb92da136a1204d3487b2bfc4 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 8 Dec 2015 15:59:06 +0100 Subject: Update appup for 18.2 OTP-13137 request table leak No load order requirements (one file). --- lib/diameter/src/diameter.appup.src | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index b77043d983..ddde648e08 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -60,7 +60,8 @@ {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_base_accounting}, - {load_module, diameter_gen_relay}]} + {load_module, diameter_gen_relay}]}, + {"1.11", [{load_module, diameter_traffic}]} %% 18.1 ], [ {"0.9", [{restart_application, diameter}]}, @@ -102,6 +103,7 @@ {load_module, diameter_stats}, {load_module, diameter_watchdog}, {load_module, diameter_peer_fsm}, - {load_module, diameter_codec}]} + {load_module, diameter_codec}]}, + {"1.11", [{load_module, diameter_traffic}]} ] }. -- cgit v1.2.3 From 34adc77f01e666eaea5e45b3857b7791626e81ac Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 8 Dec 2015 16:01:20 +0100 Subject: vsn -> 1.11.1 --- lib/diameter/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk index 041d21b261..7ac4a7adfb 100644 --- a/lib/diameter/vsn.mk +++ b/lib/diameter/vsn.mk @@ -17,5 +17,5 @@ # %CopyrightEnd% APPLICATION = diameter -DIAMETER_VSN = 1.11 +DIAMETER_VSN = 1.11.1 APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN) -- cgit v1.2.3 From 8a6a4c6f289a8326e52af52a232f6d89e63a7068 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 8 Dec 2015 16:25:18 +0100 Subject: ssh: more info from failed case --- lib/ssh/test/ssh_to_openssh_SUITE.erl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 18690d8669..02cc79e4d5 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -366,13 +366,17 @@ erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) -> Cmd = "ssh -p " ++ integer_to_list(Port) ++ " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.", - SshPort = open_port({spawn, Cmd}, [binary]), + SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]), receive {SshPort,{data, <<"2\n">>}} -> ok after ?TIMEOUT -> - ct:fail("Did not receive answer") + receive + X -> ct:fail("Received: ~p",[X]) + after 0 -> + ct:fail("Did not receive answer") + end end, ssh:stop_daemon(Pid). -- cgit v1.2.3 From 306afe7480eb4f1f4e29aa02cea538b58e468e0f Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 9 Dec 2015 12:26:08 +0100 Subject: ssl: Add renegotiation exception --- lib/ssl/test/ssl_to_openssl_SUITE.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 16b6cb10b9..9c38549cc7 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -1753,7 +1753,9 @@ check_sane_openssl_renegotaite(Config, _) -> check_sane_openssl_renegotaite(Config). check_sane_openssl_renegotaite(Config) -> - case os:cmd("openssl version") of + case os:cmd("openssl version") of + "OpenSSL 1.0.0" ++ _ -> + {skip, "Known renegotiation bug in OpenSSL"}; "OpenSSL 0.9.8" ++ _ -> {skip, "Known renegotiation bug in OpenSSL"}; "OpenSSL 0.9.7" ++ _ -> -- cgit v1.2.3 From 646e1b9e6a836526865f15582bb22c600c54d26a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:01:09 +0200 Subject: [common_test] Correct documentation Fix mistakes found by 'xmllint'. --- lib/common_test/doc/src/ct_hooks_chapter.xml | 20 ++++++++++---------- lib/common_test/doc/src/event_handler_chapter.xml | 5 +++-- lib/common_test/doc/src/notes.xml | 21 +++++++++------------ lib/common_test/src/ct_slave.erl | 10 +++++----- lib/common_test/src/ct_snmp.erl | 18 +++++++++--------- lib/common_test/src/ct_telnet.erl | 12 ++++++------ 6 files changed, 42 insertions(+), 44 deletions(-) (limited to 'lib') diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml index d9892c66f7..3905e23dcc 100644 --- a/lib/common_test/doc/src/ct_hooks_chapter.xml +++ b/lib/common_test/doc/src/ct_hooks_chapter.xml @@ -30,8 +30,8 @@ ct_hooks_chapter.xml -
+ General

The Common Test Hook (henceforth called CTH) framework allows @@ -60,8 +60,8 @@

-
+ Installing a CTH

There are multiple ways to install a CTH in your test run. You can do it for all tests in a run, for specific test suites and for specific groups @@ -120,8 +120,8 @@

-
+ CTH Scope

Once the CTH is installed into a certain test run it will be there until its scope is expired. The scope of a CTH depends on when it is @@ -208,8 +208,8 @@

-
+ Manipulating tests

It is through CTHs possible to manipulate the results of tests and configuration functions. The main purpose of doing this with CTHs is to @@ -226,8 +226,8 @@ makes it possible to use hooks as configuration fallbacks, or even completely replace all configuration functions with hook functions.

-
+ Pre Hooks

It is possible in a CTH to hook in behaviour before @@ -263,8 +263,8 @@

-
+ Post Hooks

It is also possible in a CTH to hook in behaviour after init_per_suite, @@ -308,8 +308,8 @@ post_end_per_testcase(_TC, Config, Return, CTHState) ->

-
+ Skip and Fail hooks

After any post hook has been executed for all installed CTHs, @@ -323,8 +323,8 @@ post_end_per_testcase(_TC, Config, Return, CTHState) ->

-
+ Synchronizing external user applications with Common Test

CTHs can be used to synchronize test runs with external user applications. The init function may e.g. start and/or communicate with an application that @@ -351,8 +351,8 @@ post_end_per_testcase(_TC, Config, Return, CTHState) ->

-
+ Example CTH

The CTH below will log information about a test run into a format parseable by file:consult/1. @@ -455,8 +455,8 @@ terminate(State) -> ok.

-
+ Built-in CTHs

Common Test is delivered with a couple of general purpose CTHs that can be enabled by the user to provide some generic testing functionality. diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml index cb7033b196..78e5bb5e70 100644 --- a/lib/common_test/doc/src/event_handler_chapter.xml +++ b/lib/common_test/doc/src/event_handler_chapter.xml @@ -194,8 +194,9 @@ the current test case log file.

- - #event{name = tc_done, data = {Suite,FuncOrGroup,Result}} + + + #event{name = tc_done, data = {Suite,FuncOrGroup,Result}}

Suite = atom(), name of the suite.

FuncOrGroup = Func | {Conf,GroupName,GroupProperties}

Func = atom(), name of test case or configuration function.

diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index aaf6dffc88..6972d18dfc 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -760,7 +760,7 @@ configuration function or test specification term), the affected test cases get the status user_skipped instead.

This update has meant a few changes that - may affect Common Test users in various ways: + may affect Common Test users in various ways:

The test results and statistics will be affected, which is important to know when running regression tests and comparing results to previous test runs. @@ -780,7 +780,7 @@ auto_skipped rather than user_skipped as before.
The event messages that Common Test generates during test runs have been affected by this - update. For details see OTP-11524.

+ update. For details see OTP-11524.

Own Id: OTP-11305 Aux Id: OTP-11524

@@ -831,7 +831,7 @@

The following modifications have been made to the event messages that Common Test sends during test - execution: For the tc_auto_skip + execution:

For the tc_auto_skip event, the value of the Func element has changed from end_per_group to {end_per_group,GroupName}. When @@ -843,7 +843,7 @@ configuration name already in use, the tc_done event now reports the error with a tuple (of size 2) tagged failed instead of skipped. - Please see the Event Handling chapter in the +

Please see the Event Handling chapter in the Common Test User's Guide for reference.

Own Id: OTP-11524 Aux Id: OTP-11305

@@ -1247,7 +1247,6 @@

Some bugfixes in ct_snmp:

-

ct_snmp will now use the value of the 'agent_vsns' config variable when setting the 'variables' parameter to snmp application agent configuration. @@ -1255,14 +1254,13 @@ supported versions had to be specified twice. Snmp application failed to write notify.conf since ct_snmp gave the notify type as a string instead of an - atom. This has been corrected.

+ atom. This has been corrected.

Own Id: OTP-10432

Some bugfixes in ct_snmp:

-

Functions register_users/2, register_agents/2 and register_usm_users/2, and the corresponding unregister_*/1 functions @@ -1279,7 +1277,7 @@ priv_dir instead of in the configuration dir (priv_dir/conf). This has been corrected. Arguments to register_usm_users/2 were faulty - documented. This has been corrected.

+ documented. This has been corrected.

Own Id: OTP-10434 Aux Id: kunagi-264 [175]

@@ -1343,7 +1341,7 @@

- Update common test modules to handle unicode + Update common test modules to handle unicode:

Use UTF-8 encoding for all HTML files, except the HTML version of the test suite generated with erl2html2:convert, which will have the same encoding as @@ -1354,7 +1352,7 @@ unicode:characters_to_list and unicode:characters_to_binary for conversion between binaries and strings instead of binary_to_list and - list_to_binary.

+ list_to_binary.

Own Id: OTP-10783

@@ -1395,7 +1393,6 @@

The following corrections/changes are done in the cth_surefire hook:

-

Earlier there would always be a 'properties' element under the 'testsuites' element. This would exist even if there were no 'property' element @@ -1428,7 +1425,7 @@ A new option named 'url_base' is added for this hook. If this option is used, a new attribute named 'url' will be added to the 'testcase' and 'testsuite' - elements.

+ elements.

Own Id: OTP-10589

diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl index 32a1ff4dbc..0cd83b9f04 100644 --- a/lib/common_test/src/ct_slave.erl +++ b/lib/common_test/src/ct_slave.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -134,7 +134,7 @@ start(Host, Node) -> %%% executed after startup of the node. Note that all used modules should be %%% present in the code path on the Host.

%%% -%%%

The timeouts are applied as follows: +%%%

The timeouts are applied as follows:

%%% %%% %%% BootTimeout - time to start the Erlang node, in seconds. @@ -154,7 +154,7 @@ start(Host, Node) -> %%% If this timeout occurs, the result %%% {error, startup_timeout, NodeName} is returned. %%% -%%%

+%%% %%% %%%

Option monitor_master specifies, if the slave node should be %%% stopped in case of master node stop. Defaults to false.

@@ -170,7 +170,7 @@ start(Host, Node) -> %%%

Option env specifies a list of environment variables %%% that will extended the environment.

%%% -%%%

Special return values are: +%%%

Special return values are:

%%% %%% {error, already_started, NodeName} - if the node with %%% the given name is already started on a given host; @@ -179,7 +179,7 @@ start(Host, Node) -> %%% {error, not_alive, NodeName} - if node on which the %%% ct_slave:start/3 is called, is not alive. Note that %%% NodeName is the name of current node in this case. -%%%

+%%% %%% start(Host, Node, Opts) -> ENode = enodename(Host, Node), diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl index 95098bdaca..bb0167eb22 100644 --- a/lib/common_test/src/ct_snmp.erl +++ b/lib/common_test/src/ct_snmp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ %%% @doc Common Test user interface module for the OTP snmp application %%% -%%% The purpose of this module is to make snmp configuration easier for +%%%

The purpose of this module is to make snmp configuration easier for %%% the test case writer. Many test cases can use default values for common %%% operations and then no snmp configuration files need to be supplied. When %%% it is necessary to change particular configuration parameters, a subset @@ -31,7 +31,7 @@ %%% To simplify the test suite, Common Test keeps track %%% of some of the snmp manager information. This way the test suite doesn't %%% have to handle as many input parameters as it would if it had to interface the -%%% OTP snmp manager directly. +%%% OTP snmp manager directly.

%%% %%%

The following snmp manager and agent parameters are configurable:

%%% @@ -326,9 +326,9 @@ set_info(Config) -> %%% @doc Register the manager entity (=user) responsible for specific agent(s). %%% Corresponds to making an entry in users.conf. %%% -%%% This function will try to register the given users, without +%%%

This function will try to register the given users, without %%% checking if any of them already exist. In order to change an -%%% already registered user, the user must first be unregistered. +%%% already registered user, the user must first be unregistered.

register_users(MgrAgentConfName, Users) -> case setup_users(Users) of ok -> @@ -351,10 +351,10 @@ register_users(MgrAgentConfName, Users) -> %%% @doc Explicitly instruct the manager to handle this agent. %%% Corresponds to making an entry in agents.conf %%% -%%% This function will try to register the given managed agents, +%%%

This function will try to register the given managed agents, %%% without checking if any of them already exist. In order to change %%% an already registered managed agent, the agent must first be -%%% unregistered. +%%% unregistered.

register_agents(MgrAgentConfName, ManagedAgents) -> case setup_managed_agents(MgrAgentConfName,ManagedAgents) of ok -> @@ -378,9 +378,9 @@ register_agents(MgrAgentConfName, ManagedAgents) -> %%% @doc Explicitly instruct the manager to handle this USM user. %%% Corresponds to making an entry in usm.conf %%% -%%% This function will try to register the given users, without +%%%

This function will try to register the given users, without %%% checking if any of them already exist. In order to change an -%%% already registered user, the user must first be unregistered. +%%% already registered user, the user must first be unregistered.

register_usm_users(MgrAgentConfName, UsmUsers) -> EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID), case setup_usm_users(UsmUsers, EngineID) of diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl index e9487e94db..4d3fd2d094 100644 --- a/lib/common_test/src/ct_telnet.erl +++ b/lib/common_test/src/ct_telnet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2014. All Rights Reserved. +%% Copyright Ericsson AB 2003-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -327,16 +327,16 @@ cmd(Connection,Cmd) -> %%% Reason = term() %%% @doc Send a command via telnet and wait for prompt. %%% -%%% This function will by default add a newline to the end of the +%%%

This function will by default add a newline to the end of the %%% given command. If this is not desired, the option %%% `{newline,false}' can be used. This is necessary, for example, %%% when sending telnet command sequences (prefixed with the -%%% Interprete As Command, IAC, character). +%%% Interprete As Command, IAC, character).

%%% -%%% The option `timeout' specifies how long the client shall wait for +%%%

The option `timeout' specifies how long the client shall wait for %%% prompt. If the time expires, the function returns %%% `{error,timeout}'. See the module description for information -%%% about the default value for the command timeout. +%%% about the default value for the command timeout.

cmd(Connection,Cmd,Opts) when is_list(Opts) -> case check_cmd_opts(Opts) of ok -> @@ -378,7 +378,7 @@ cmdf(Connection,CmdFormat,Args) -> %%% @doc Send a telnet command and wait for prompt %%% (uses a format string and list of arguments to build the command). %%% -%%% See {@link cmd/3} further description. +%%%

See {@link cmd/3} further description.

cmdf(Connection,CmdFormat,Args,Opts) when is_list(Args) -> Cmd = lists:flatten(io_lib:format(CmdFormat,Args)), cmd(Connection,Cmd,Opts). -- cgit v1.2.3 From 3e0e79218065458b816cd726bd637f1ecd00a882 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 13 Oct 2015 14:02:48 +0200 Subject: [observer] Correct documentation Fix mistakes found by 'xmllint'. --- lib/observer/doc/src/crashdump_ug.xml | 2 -- lib/observer/doc/src/notes.xml | 12 ++++-------- lib/observer/doc/src/observer_ug.xml | 3 +-- lib/observer/doc/src/ttb.xml | 17 ++++++++--------- lib/observer/doc/src/ttb_ug.xml | 7 +++---- 5 files changed, 16 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/observer/doc/src/crashdump_ug.xml b/lib/observer/doc/src/crashdump_ug.xml index 3cd97f2f18..4bb3628ab5 100644 --- a/lib/observer/doc/src/crashdump_ug.xml +++ b/lib/observer/doc/src/crashdump_ug.xml @@ -377,7 +377,6 @@

The Memory panel shows memory and allocator information. From the left hand menu you can select:

-

Memory More... -

diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml index 5243f50e34..f0c87d865e 100644 --- a/lib/observer/doc/src/notes.xml +++ b/lib/observer/doc/src/notes.xml @@ -273,13 +273,12 @@
Improvements and New Features -

The new Memory field from a crash dump is now presented by crashdump viewer, both in the process overview and in the process detail page. A summary of blocks- and carriers sizes is added to the allocator information page in the crashdump viewer. -

+

Own Id: OTP-10604 Aux Id: kunagi-336 [247]

@@ -408,7 +407,6 @@

The following bugs in ttb have been corrected:

-

ttb:tracer/2 would earlier crash when trying to set up tracing for a diskless node to wrap files, i.e. when option @@ -421,7 +419,7 @@ {file,{local,Filename}} A deadlock would sometimes occur due to an information printout from the ttb_control process when ttb was - stopped.

+ stopped.

Own Id: OTP-9431

@@ -449,7 +447,6 @@

The following new features are added to ttb:

-

A one-command trace setup is added, ttb:start_trace/4. The following new options are added to ttb:tracer/2: @@ -485,7 +482,7 @@ disable_sort is added to ttb:format/2. When this option is used, trace messages from different logs are not merged according to timestamps, but just appended - one log after the other.

+ one log after the other.

Own Id: OTP-9403

@@ -493,7 +490,6 @@

The following non backwards compatible changes are done in ttb:

-

When setting up trace with ttb, the 'timestamp' trace flag will now always be set. The 'fetch' option to ttb:stop/1 is removed since @@ -509,7 +505,7 @@ trace file, this is now changed so the handler state is passed not only from one trace message to the next in the same file, but also from one file to the next. -

+

*** POTENTIAL INCOMPATIBILITY ***

diff --git a/lib/observer/doc/src/observer_ug.xml b/lib/observer/doc/src/observer_ug.xml index 8388cb6736..ff30d70913 100644 --- a/lib/observer/doc/src/observer_ug.xml +++ b/lib/observer/doc/src/observer_ug.xml @@ -105,7 +105,7 @@

Reds can be presented as accumulated values or as values since last update.

-

Process info open a detailed information window on the selected process. +

Process info open a detailed information window on the selected process.

Process Information Shows the process information. @@ -127,7 +127,6 @@ rb server will be stopped on the observed node when exiting or changing observed node.

-

Trace Processes will add the selected process identifiers to the Trace Overview view and the node the processes reside on will be added as well. Trace Named Processes will add the registered name of processes. This can be useful diff --git a/lib/observer/doc/src/ttb.xml b/lib/observer/doc/src/ttb.xml index 0b064b51b8..0a50a20716 100644 --- a/lib/observer/doc/src/ttb.xml +++ b/lib/observer/doc/src/ttb.xml @@ -25,8 +25,7 @@ ttb - Siri hansen - Bartlomiej Puzon + Siri hansen, Bartlomiej Puzon 1 @@ -60,17 +59,16 @@

This function is a shortcut allowing to start a trace with one command. Each tuple in Patterns is converted to list which is in turn passed to ttb:tpl. - The call: + The call:

ttb:start_trace([Node, OtherNode], [{mod, foo, []}, {mod, bar, 2}], {all, call}, [{file, File}, {handler,{fun myhandler/4, S}}]) - is equivalent to +

is equivalent to

ttb:start_trace([Node, OtherNode], [{file, File}, {handler,{fun myhandler/4, S}}]), ttb:tpl(mod, foo, []), ttb:tpl(mod, bar, 2, []), ttb:p(all, call) -

@@ -193,7 +191,7 @@ ttb:p(all, call)
(i.e. on diskless nodes), a custom module to handle autostart information storage and retrieval can be provided by specifying ttb_autostart_module environment variable for the runtime_tools - application. The module has to respond to the following API: + application. The module has to respond to the following API:

write_config(Data) -> ok Store the provided data for further retrieval. It is @@ -207,7 +205,6 @@ ttb:p(all, call)
must return {error, Error}.
-

The resume option implies the default FetchTimeout, which is 10 seconds

@@ -272,17 +269,19 @@ ttb:p(all, call)
Clear trace pattern on global function calls

With tp and tpl one of match specification shortcuts - may be used (example: ttb:tp(foo_module, caller)). The shortcuts are: + may be used (example: ttb:tp(foo_module, caller)). The shortcuts are:

+ return - for [{'_',[],[{return_trace}]}] (report the return value) + caller - for [{'_',[],[{message,{caller}}]}] (report the calling function) + {codestr, Str} - for dbg:fun2ms/1 arguments passed as strings (example: "fun(_) -> return_trace() end") -

diff --git a/lib/observer/doc/src/ttb_ug.xml b/lib/observer/doc/src/ttb_ug.xml index ba8c997133..e2a28d67d0 100644 --- a/lib/observer/doc/src/ttb_ug.xml +++ b/lib/observer/doc/src/ttb_ug.xml @@ -320,7 +320,7 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
- + Overload protection

When tracing live systems, special care needs to be always taken not to overload a node with too heavy tracing. ttb provides the overload option to help to address the problem.

@@ -747,7 +747,7 @@ f3() -> of the ttb for setting trace flags on processes and trace patterns for call trace, i.e. the functions p, tp, tpl, ctp, ctpl and ctpg. There are only - two things added by ttb for these functions: + two things added by ttb for these functions:

all calls are stored in the history buffer and can be recalled and stored in a configuration file. This makes it @@ -756,9 +756,8 @@ f3() -> typing when using ttb from the erlang shell; shortcuts are provided for the most common match specifications (in order not to force the user to use - dbg:fun2ms continually). + dbg:fun2ms continually). -

Use list_history/0 to see the content of the history buffer, and run_history/1 to re-execute one of the entries.

-- cgit v1.2.3 From f8fa795ac4885af5c9f396fbcf26143a67fbdf49 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Tue, 1 Dec 2015 08:11:25 +0100 Subject: Fix request table leak at exit signal The storing of request records in the ets table diameter_request was wrapped in a try/after so that the latter would unconditionally remove written entries. The problem is that it didn't deal with the process exiting as a result of an exit signal, since this doesn't raise in an exception. Since the process in question applies callbacks to user code, we can potentially be linked to other process and exit as a result. Trapping exits changes the current behaviour of the process, so spawn a monitoring process that cleans up upon reception of 'DOWN'. --- lib/diameter/src/base/diameter_traffic.erl | 32 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index eb4bbae931..d1adb084ce 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -1490,16 +1490,20 @@ send_R(Pkt0, caps = Caps, packet = Pkt0}, - try - incr(send, Pkt, TPid, AppDict), - TRef = send_request(TPid, Pkt, Req, SvcName, Timeout), - Pid ! Ref, %% tell caller a send has been attempted - handle_answer(SvcName, - App, - recv_A(Timeout, SvcName, App, Opts, {TRef, Req})) - after - erase_requests(Pkt) - end. + %% Ensure that request table is cleaned even if we receive an exit + %% signal. An alternative would be to simply trap exits, but + %% callbacks are applied in this process, and these could possibly + %% be expecting the prevailing behaviour. + Self = self(), + Seqs = diameter_codec:sequence_numbers(Pkt), + spawn(fun() -> diameter_lib:wait([Self]), erase_requests(Seqs) end), + + incr(send, Pkt, TPid, AppDict), + TRef = send_request(TPid, Pkt, Req, SvcName, Timeout), + Pid ! Ref, %% tell caller a send has been attempted + handle_answer(SvcName, + App, + recv_A(Timeout, SvcName, App, Opts, {TRef, Req})). %% recv_A/5 @@ -1831,6 +1835,10 @@ store_request(TPid, Bin, Req, Timeout) -> TRef. %% lookup_request/2 +%% +%% Note the match on both the key and transport pid. The latter is +%% necessary since the same Hop-by-Hop and End-to-End identifiers are +%% reused in the case of retransmission. lookup_request(Msg, TPid) -> Seqs = diameter_codec:sequence_numbers(Msg), @@ -1846,8 +1854,8 @@ lookup_request(Msg, TPid) -> %% erase_requests/1 -erase_requests(Pkt) -> - ets:delete(?REQUEST_TABLE, diameter_codec:sequence_numbers(Pkt)). +erase_requests(Seqs) -> + ets:delete(?REQUEST_TABLE, Seqs). %% match_requests/1 -- cgit v1.2.3 From 6c9cbd96d01da3194715d3caf8aa23350dfaa53a Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Thu, 3 Dec 2015 13:09:11 +0100 Subject: Fix request table leak at retransmission In the case of retranmission, a prepare_retransmit callback could modify End-to-End and/or Hop-by-Hop identifiers so that the resulting diameter_request entry was not removed, since the removal was of entries with the identifiers of the original request. The chances someone doing this in practice are probably minimal. --- lib/diameter/src/base/diameter_traffic.erl | 65 +++++++++++++----------------- 1 file changed, 28 insertions(+), 37 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index d1adb084ce..61ea5e69ba 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -169,7 +169,7 @@ incr_error(Dir, Id, TPid, _) -> incr_error(Dir, Id, TPid) -> incr(TPid, {Id, Dir, error}). - + %% --------------------------------------------------------------------------- %% incr_rc/4 %% --------------------------------------------------------------------------- @@ -1490,14 +1490,6 @@ send_R(Pkt0, caps = Caps, packet = Pkt0}, - %% Ensure that request table is cleaned even if we receive an exit - %% signal. An alternative would be to simply trap exits, but - %% callbacks are applied in this process, and these could possibly - %% be expecting the prevailing behaviour. - Self = self(), - Seqs = diameter_codec:sequence_numbers(Pkt), - spawn(fun() -> diameter_lib:wait([Self]), erase_requests(Seqs) end), - incr(send, Pkt, TPid, AppDict), TRef = send_request(TPid, Pkt, Req, SvcName, Timeout), Pid ! Ref, %% tell caller a send has been attempted @@ -1706,9 +1698,18 @@ encode(_, _, #diameter_packet{} = Pkt) -> send_request(TPid, #diameter_packet{bin = Bin} = Pkt, Req, _SvcName, Timeout) when node() == node(TPid) -> - %% Store the outgoing request before sending to avoid a race with - %% reply reception. - TRef = store_request(TPid, Bin, Req, Timeout), + Seqs = diameter_codec:sequence_numbers(Bin), + TRef = erlang:start_timer(Timeout, self(), TPid), + Entry = {Seqs, Req, TRef}, + + %% Ensure that request table is cleaned even if we receive an exit + %% signal. An alternative would be to simply trap exits, but + %% callbacks are applied in this process, and these could possibly + %% be expecting the prevailing behaviour. + Self = self(), + spawn(fun() -> diameter_lib:wait([Self]), erase_request(Entry) end), + + store_request(Entry, TPid), send(TPid, Pkt), TRef; @@ -1723,31 +1724,21 @@ send_request(TPid, #diameter_packet{} = Pkt, Req, SvcName, Timeout) -> %% send/1 send({TPid, Pkt, #request{handler = Pid} = Req0, SvcName, Timeout, TRef}) -> - Seqs = diameter_codec:sequence_numbers(Pkt), Req = Req0#request{handler = self()}, - Ref = send_request(TPid, Pkt, Req, SvcName, Timeout), - - try - recv(TPid, Pid, TRef, Ref) - after - %% Remove only the entry for this specific send since a resend - %% from the originating node can pick another transport on - %% this one. - ets:delete_object(?REQUEST_TABLE, {Seqs, Req, Ref}) - end. + recv(TPid, Pid, TRef, send_request(TPid, Pkt, Req, SvcName, Timeout)). %% recv/4 %% %% Relay an answer from a remote node. -recv(TPid, Pid, TRef, Ref) -> +recv(TPid, Pid, TRef, LocalTRef) -> receive {answer, _, _, _, _} = A -> Pid ! A; - {failover = T, Ref} -> + {failover = T, LocalTRef} -> Pid ! {T, TRef}; T -> - exit({timeout, Ref, TPid} = T) + exit({timeout, LocalTRef, TPid} = T) end. %% send/2 @@ -1824,15 +1815,15 @@ resend_request(Pkt0, TRef = send_request(TPid, Pkt, Req, SvcName, Tmo), {TRef, Req}. -%% store_request/4 +%% store_request/2 -store_request(TPid, Bin, Req, Timeout) -> - Seqs = diameter_codec:sequence_numbers(Bin), - TRef = erlang:start_timer(Timeout, self(), TPid), - ets:insert(?REQUEST_TABLE, {Seqs, Req, TRef}), +store_request(T, TPid) -> + ets:insert(?REQUEST_TABLE, T), ets:member(?REQUEST_TABLE, TPid) - orelse (self() ! {failover, TRef}), %% failover/1 may have missed - TRef. + orelse begin + {_Seqs, _Req, TRef} = T, + (self() ! {failover, TRef}) %% failover/1 may have missed + end. %% lookup_request/2 %% @@ -1852,10 +1843,10 @@ lookup_request(Msg, TPid) -> false end. -%% erase_requests/1 +%% erase_request/1 -erase_requests(Seqs) -> - ets:delete(?REQUEST_TABLE, Seqs). +erase_request(T) -> + ets:delete_object(?REQUEST_TABLE, T). %% match_requests/1 @@ -1878,7 +1869,7 @@ failover(TPid) when is_pid(TPid) -> lists:foreach(fun failover/1, match_requests(TPid)); %% Note that a request process can store its request after failover -%% notifications are sent here: store_request/4 sends the notification +%% notifications are sent here: store_request/2 sends the notification %% in that case. %% Failover as a consequence of request_peer_down/1: inform the -- cgit v1.2.3 From 22afaebfc419df5a0ca78340ffc659f72439e2db Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 1 Dec 2015 18:48:12 +0100 Subject: ssl: Use spawn_executable --- lib/ssl/test/ssl_ECC_SUITE.erl | 20 ++-- lib/ssl/test/ssl_test_lib.erl | 14 ++- lib/ssl/test/ssl_to_openssl_SUITE.erl | 208 +++++++++++++++++----------------- 3 files changed, 124 insertions(+), 118 deletions(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 3a9f21ea99..fd2afc808c 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -248,10 +248,13 @@ start_client(openssl, Port, CA, OwnCa, Cert, Key, Config) -> PrivDir = ?config(priv_dir, Config), NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -verify 2 -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ Cert ++ " -CAfile " ++ NewCA - ++ " -key " ++ Key ++ " -host localhost -msg -debug", - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_client", "-verify", "2", "-port", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", Cert, "-CAfile", NewCA, + "-key", Key, "-host","localhost", "-msg", "-debug"], + + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, "Hello world"), OpenSslPort; start_client(erlang, Port, CA, _, Cert, Key, Config) -> @@ -270,10 +273,11 @@ start_server(openssl, CA, OwnCa, Cert, Key, Config) -> Port = ssl_test_lib:inet_port(node()), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -verify 2 -cert " ++ Cert ++ " -CAfile " ++ NewCA - ++ " -key " ++ Key ++ " -msg -debug", - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-verify", "2", "-cert ", Cert, "-CAfile", NewCA, + "-key", Key, "-msg" "-debug"], + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, "Hello world"), {OpenSslPort, Port}; start_server(erlang, CA, _, Cert, Key, Config) -> diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index f25f6f9425..9a76d603b1 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1192,13 +1192,13 @@ wait_for_openssl_server(Port, N) -> end. version_flag(tlsv1) -> - " -tls1 "; + "-tls1"; version_flag('tlsv1.1') -> - " -tls1_1 "; + "-tls1_1"; version_flag('tlsv1.2') -> - " -tls1_2 "; + "-tls1_2"; version_flag(sslv3) -> - " -ssl3 ". + "-ssl3". filter_suites(Ciphers0) -> Version = tls_record:highest_protocol_version([]), @@ -1243,3 +1243,9 @@ close_loop(Port, Time, SentClose) -> ct:log("Timeout~n",[]) end end. + +portable_open_port(Exe, Args) -> + AbsPath = os:find_executable(Exe), + ct:pal("open_port({spawn_executable, ~p}, [{args, ~p}, stderr_to_stdout]).", [AbsPath, Args]), + open_port({spawn_executable, AbsPath}, + [{args, Args}, stderr_to_stdout]). diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 16b6cb10b9..52b078f27b 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -262,12 +262,11 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile, - - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + "-cert", CertFile, "-key", KeyFile], - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -302,13 +301,11 @@ basic_erlang_server_openssl_client(Config) when is_list(Config) -> {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ - " -host localhost" ++ workaround_openssl_s_clinent(), - - ct:log("openssl cmd: ~p~n", [Cmd]), - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port) | workaround_openssl_s_clinent()], + + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, Data), ssl_test_lib:check_result(Server, ok), @@ -334,12 +331,12 @@ erlang_client_openssl_server(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile, - - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key", KeyFile], + + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -376,12 +373,12 @@ erlang_server_openssl_client(Config) when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost", + Exe = "openssl", + Args = ["s_client", "-connect", "localhost: " ++ integer_to_list(Port), + ssl_test_lib:version_flag(Version)], - ct:log("openssl cmd: ~p~n", [Cmd]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), true = port_command(OpenSslPort, Data), ssl_test_lib:check_result(Server, ok), @@ -407,14 +404,13 @@ erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-CAfile", CaCertFile, + "-key", KeyFile, "-Verify", "2", "-msg"], - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile - ++ " -key " ++ KeyFile ++ " -Verify 2 -msg", - - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -455,13 +451,14 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) -> {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost " ++ " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile - ++ " -key " ++ KeyFile ++ " -msg", - - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_client", "-connect", "localhost: " ++ integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, + "-CAfile", CaCertFile, + "-key", KeyFile, "-msg"], + + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, Data), ssl_test_lib:check_result(Server, ok), @@ -491,12 +488,13 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) -> {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost -reconnect", - - ct:log("openssl cmd: ~p~n", [Cmd]), - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-reconnect"], + + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, Data), @@ -527,12 +525,12 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) -> KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key", KeyFile, "-msg"], - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -576,12 +574,12 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key", KeyFile, "-msg"], - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -622,12 +620,12 @@ erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) -> {options, [{renegotiate_at, N}, {reuse_sessions, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost -msg", - - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_client","-connect", "localhost: " ++ integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-msg"], - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, Data), @@ -657,13 +655,13 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key", KeyFile, "-msg"], - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), + ssl_test_lib:wait_for_openssl_server(Port), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, @@ -699,13 +697,13 @@ erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> CaCertFile = proplists:get_value(cacertfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile - ++ " -key " ++ KeyFile ++ " -Verify 2", + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-CAfile", CaCertFile, + "-key", KeyFile, "-Verify", "2"], - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -750,13 +748,14 @@ erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ClientOpts), KeyFile = proplists:get_value(keyfile, ClientOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile - ++ " -key " ++ KeyFile ++ " -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost", - - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_client", "-cert", CertFile, + "-CAfile", CaCertFile, + "-key", KeyFile,"-connect", "localhost:" ++ integer_to_list(Port), + ssl_test_lib:version_flag(Version)], - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), + true = port_command(OpenSslPort, Data), ssl_test_lib:check_result(Server, ok), @@ -839,12 +838,11 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", - - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key", KeyFile], - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -895,12 +893,11 @@ expired_session(Config) when is_list(Config) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), + "-cert", CertFile,"-key", KeyFile], - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -953,12 +950,11 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) -> {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ - " -host localhost -ssl2 -msg", - - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port), + "-ssl2", "-msg"], - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, Data), ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]), @@ -1033,7 +1029,7 @@ erlang_server_alpn_openssl_client(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_server_and_openssl_client_with_opts(Config, [{alpn_preferred_protocols, [<<"spdy/2">>]}], - "", + [], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) @@ -1046,7 +1042,7 @@ erlang_server_openssl_client_alpn(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_server_and_openssl_client_with_opts(Config, [], - "-alpn spdy/2", + ["-alpn", "spdy/2"], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) @@ -1179,7 +1175,7 @@ erlang_client_openssl_server_npn_only_client(Config) when is_list(Config) -> %%-------------------------------------------------------------------------- erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) -> Data = "From openssl to erlang", - start_erlang_server_and_openssl_client_with_opts(Config, [{next_protocols_advertised, [<<"spdy/2">>]}], "", + start_erlang_server_and_openssl_client_with_opts(Config, [{next_protocols_advertised, [<<"spdy/2">>]}], [], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) @@ -1188,7 +1184,7 @@ erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) -> erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) -> Data = "From openssl to erlang", - start_erlang_server_and_openssl_client_with_opts(Config, [], "-nextprotoneg spdy/2", + start_erlang_server_and_openssl_client_with_opts(Config, [], ["-nextprotoneg", "spdy/2"], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) @@ -1613,12 +1609,12 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -nextprotoneg http/1.0,spdy/2 -msg -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost", - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_client", "-nextprotoneg", "http/1.0,spdy/2", "-msg", "-connect", "localhost:" + ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)], - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), Callback(Server, OpenSslPort), @@ -1642,12 +1638,12 @@ start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenS {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client " ++ OpenSSLClientOpts ++ " -msg -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost", - - ct:log("openssl cmd: ~p~n", [Cmd]), + + Exe = "openssl", + Args = ["s_client"] ++ OpenSSLClientOpts ++ ["-msg", "-connect", "localhost:" ++ integer_to_list(Port), + ssl_test_lib:version_flag(Version)], - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), Callback(Server, OpenSslPort), @@ -1793,13 +1789,13 @@ workaround_openssl_s_clinent() -> %% explicitly specified case os:cmd("openssl version") of "OpenSSL 1.0.1c" ++ _ -> - " -no_tls1_2 "; + ["-no_tls1_2"]; "OpenSSL 1.0.1d" ++ _ -> - " -no_tls1_2 "; + ["-no_tls1_2"]; "OpenSSL 1.0.1e" ++ _ -> - " -no_tls1_2 "; + ["-no_tls1_2"]; "OpenSSL 1.0.1f" ++ _ -> - " -no_tls1_2 "; + ["-no_tls1_2"]; _ -> - "" + [] end. -- cgit v1.2.3 From a609e31025b2b93d5d360879193eb6f1dac90d51 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 9 Dec 2015 15:14:51 +0100 Subject: ssl: Use test case time out instead --- lib/ssl/test/ssl_to_openssl_SUITE.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 52b078f27b..67045043cf 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -1257,7 +1257,7 @@ client_check_result(Port, DataExpected, DataReceived) -> client_check_result(Port, DataExpected, NewData) end after 3000 -> - ct:fail({"Time out on opensssl Client", {expected, DataExpected}, + ct:fail({"Time out on openSSL Client", {expected, DataExpected}, {got, DataReceived}}) end. client_check_result(Port, DataExpected) -> @@ -1675,8 +1675,6 @@ erlang_ssl_receive(Socket, Data) -> erlang_ssl_receive(Socket,Data); Other -> ct:fail({unexpected_message, Other}) - after 4000 -> - ct:fail({did_not_get, Data}) end. connection_info(Socket, Version) -> -- cgit v1.2.3 From f84858101803153a04caeb1b300b80e376fc105d Mon Sep 17 00:00:00 2001 From: xsipewe Date: Fri, 2 Oct 2015 13:01:27 +0200 Subject: sasl: Editorial changes --- lib/sasl/doc/src/alarm_handler.xml | 84 ++-- lib/sasl/doc/src/appup.xml | 449 +++++++++++---------- lib/sasl/doc/src/book.xml | 4 +- lib/sasl/doc/src/error_logging.xml | 215 +++++----- lib/sasl/doc/src/overload.xml | 124 +++--- lib/sasl/doc/src/part.xml | 5 +- lib/sasl/doc/src/rb.xml | 285 +++++++------- lib/sasl/doc/src/ref_man.xml | 4 +- lib/sasl/doc/src/rel.xml | 91 ++--- lib/sasl/doc/src/release_handler.xml | 743 +++++++++++++++++++---------------- lib/sasl/doc/src/relup.xml | 70 ++-- lib/sasl/doc/src/sasl_app.xml | 178 +++++---- lib/sasl/doc/src/sasl_intro.xml | 38 +- lib/sasl/doc/src/script.xml | 157 ++++---- lib/sasl/doc/src/systools.xml | 347 ++++++++-------- 15 files changed, 1434 insertions(+), 1360 deletions(-) (limited to 'lib') diff --git a/lib/sasl/doc/src/alarm_handler.xml b/lib/sasl/doc/src/alarm_handler.xml index b98f22d2a1..68076ba28d 100644 --- a/lib/sasl/doc/src/alarm_handler.xml +++ b/lib/sasl/doc/src/alarm_handler.xml @@ -37,94 +37,92 @@ alarm_handler An Alarm Handling Process -

The alarm handler process is a gen_event event manager - process which receives alarms in the system. This process is not - intended to be a complete alarm handler. It defines a - place to which alarms can be sent. One simple event handler is - installed in the alarm handler at start-up, but users are - encouraged to write and install their own handlers. -

+

The alarm handler process is a + gen_event + event manager process that receives alarms in the system. + This process is not intended to be a complete alarm handler. + It defines a place to which alarms can be sent. One simple event + handler is installed in the alarm handler at startup, but users + are encouraged to write and install their own handlers.

The simple event handler sends all alarms as info reports to - the error logger, and saves all of them in a list which can be - passed to a user defined event handler, which may be installed at - a later stage. The list can grow large if many alarms are - generated. So it is a good reason to install a better user defined - handler. -

-

There are functions to set and clear alarms. The format of - alarms are defined by the user. For example, an event handler - for SNMP could be defined, together with an alarm MIB. -

-

The alarm handler is part of the SASL application. -

+ the error logger, and saves all in a list. This list can be + passed to a user-defined event handler, which can be installed + later. The list can grow large if many alarms are generated. + This is a good reason to install a better user-defined + handler.

+

Functions are provided to set and clear alarms. The alarm + format is defined by the user. For example, an event handler + for SNMP can be defined, together with an alarm Management + Information Base (MIB).

+

The alarm handler is part of the SASL application.

When writing new event handlers for the alarm handler, the - following events must be handled: -

+ following events must be handled:

{set_alarm, {AlarmId, AlarmDescr}}

This event is generated by - alarm_handler:set_alarm({AlarmId, AlarmDecsr}). -

+ alarm_handler:set_alarm({AlarmId, AlarmDecsr}).

{clear_alarm, AlarmId}

This event is - generated by alarm_handler:clear_alarm(AlarmId). -

+ generated by alarm_handler:clear_alarm(AlarmId).

The default simple handler is called alarm_handler and - it may be exchanged by calling gen_event:swap_handler/3 - as gen_event:swap_handler(alarm_handler, {alarm_handler, swap}, {NewHandler, Args}). NewHandler:init({Args, {alarm_handler, Alarms}}) is called. Refer to gen_event(3) - for further details. -

+ it can be exchanged by calling + gen_event:swap_handler/3 + as gen_event:swap_handler(alarm_handler, {alarm_handler, swap}, + {NewHandler, Args}). NewHandler:init({Args, {alarm_handler, + Alarms}}) is called. For more details, see + gen_event(3) + in STDLIB.

+ clear_alarm(AlarmId) -> void() - Clear the specified alarms + Clears the specified alarms. AlarmId = term() -

Sends the clear_alarm event to all event handlers.

+

Sends event clear_alarm to all event handlers.

When receiving this event, the default simple handler - clears the latest received alarm with id AlarmId. -

+ clears the latest received alarm with id AlarmId.

+ get_alarms() -> [alarm()] - Get all active alarms + Gets all active alarms.

Returns a list of all active alarms. This function can only - be used when the simple handler is installed. -

+ be used when the simple handler is installed.

+ set_alarm(alarm()) - Set an alarm with an id + Sets an alarm with an id. alarm() = {AlarmId, AlarmDescription} AlarmId = term() AlarmDescription = term() -

Sends the set_alarm event to all event handlers.

+

Sends event set_alarm to all event handlers.

When receiving this event, the default simple handler - stores the alarm. The AlarmId identifies the alarm - and is used when the alarm is cleared. -

+ stores the alarm. AlarmId identifies the alarm + and is used when the alarm is cleared.

See Also -

error_logger(3), gen_event(3) -

+

error_logger(3), + gen_event(3)

diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml index 72333960ec..b54d2adb19 100644 --- a/lib/sasl/doc/src/appup.xml +++ b/lib/sasl/doc/src/appup.xml @@ -29,78 +29,85 @@ appup - Application upgrade file. + Application upgrade file

The application upgrade file defines how an application is upgraded or downgraded in a running system.

-

This file is used by the functions in systools when - generating a release upgrade file relup.

+

This file is used by the functions in + systools + when generating a release upgrade file relup.

- FILE SYNTAX -

The application upgrade file should be called - Application.appup where Application is the name of - the application. The file should be located in the ebin + File Syntax +

The application upgrade file is to be called + Application.appup, where Application is the + application name. The file is to be located in the ebin directory for the application.

The .appup file contains one single Erlang term, which defines the instructions used to upgrade or downgrade - the application. The file has the following syntax:

+ the application. The file has the following syntax:

{Vsn, [{UpFromVsn, Instructions}, ...], - [{DownToVsn, Instructions}, ...]}. - - - -

Vsn = string() is the current version of - the application.

-
- -

UpFromVsn = string() | binary() is an earlier - version of the application to upgrade from. If it is a - string, it will be interpreted as a specific version - number. If it is a binary, it will be interpreted as a - regular expression which can match multiple version - numbers.

-
- -

DownToVsn = string() | binary() is an earlier - version of the application to downgrade to. If it is a - string, it will be interpreted as a specific version - number. If it is a binary, it will be interpreted as a - regular expression which can match multiple version - numbers.

-
- -

Instructions is a list of release upgrade instructions, see below. It is recommended to use + [{DownToVsn, Instructions}, ...]}. + + Vsn = string() +

Current application version.

+ UpFromVsn = string() | binary() +

An earlier + application version to upgrade from. If it is a + string, it is interpreted as a specific version + number. If it is a binary, it is interpreted as a + regular expression that can match multiple version + numbers.

+ DownToVsn = string() | binary() +

An earlier + application version to downgrade to. If it is a + string, it is interpreted as a specific version + number. If it is a binary, it is interpreted as a + regular expression that can match multiple version + numbers.

+ Instructions +

A list of release upgrade instructions, see + Release + Upgrade Instructions. It is recommended to use high-level instructions only. These are automatically translated to low-level instructions by systools when - creating the relup file.

-
- -

In order to avoid duplication of upgrade instructions it is - allowed to use regular expressions to specify the UpFromVsn - and DownToVsn. To be considered a regular expression, the - version identifier must be specified as a binary, e.g.

- <<"2\\.1\\.[0-9]+">> -

will match all versions 2.1.x, where x is any number.

-

Note that the regular expression must match the complete - version string, so the above example will work for for - e.g. 2.1.1, but not for 2.1.1.1

+ creating the relup file.

+ +

To avoid duplication of upgrade instructions, it is + allowed to use regular expressions to specify UpFromVsn + and DownToVsn. To be considered a regular expression, the + version identifier must be specified as a binary. For example, + the following match all versions 2.1.x, where x is + any number:

+ +<<"2\\.1\\.[0-9]+">> +

Notice that the regular expression must match the complete + version string, so this example works for, for example, + 2.1.1, but not for 2.1.1.1.

- RELEASE UPGRADE INSTRUCTIONS + + Release Upgrade Instructions

Release upgrade instructions are interpreted by the release handler when an upgrade or downgrade is made. For more - information about release handling, refer to OTP Design Principles.

-

A process is said to use a module Mod, if + information about release handling, see + OTP + Design Principles in System Documentation.

+

A process is said to use a module Mod if Mod is listed in the Modules part of the child - specification used to start the process, see supervisor(3). - In the case of gen_event, an event manager process is said to use - Mod if Mod is an installed event handler.

-

High-level instructions

+ specification used to start the process, see + supervisor(3). + In the case of + gen_event, + an event manager process is said to use Mod if Mod + is an installed event handler.

+ +
+ High-Level Instructions
 {update, Mod}
 {update, Mod, supervisor}
@@ -116,52 +123,68 @@
   Change = soft | {advanced,Extra}
     Extra = term()
   PrePurge = PostPurge = soft_purge | brutal_purge
-  DepMods = [Mod]
-    
-

Synchronized code replacement of processes using the module - Mod. All those processes are suspended using - sys:suspend, the new version of the module is loaded and - then the processes are resumed using sys:resume.

-

Change defaults to soft and defines the type of - code change. If it is set to {advanced,Extra}, processes - implemented using gen_server, gen_fsm or gen_event will transform - their internal state by calling the callback function - code_change. Special processes will call the callback + DepMods = [Mod] +

Synchronized code replacement of processes using module + Mod.

+

All those processes are suspended using + sys:suspend, + the new module version is loaded, and + then the processes are resumed using + sys:resume.

+ + Change +

Defaults to soft and defines the type of + code change. If it is set to {advanced,Extra}, implemented + processes using + gen_server, + gen_fsm, or + gen_event + transform their internal state by calling the callback function + code_change. Special processes call the callback function system_code_change/4. In both cases, the term - Extra is passed as an argument to the callback function.

-

PrePurge defaults to brutal_purge and controls - what action to take with processes that are executing old code - before loading the new version of the module. If the value + Extra is passed as an argument to the callback + function.

+ PrePurge +

Defaults to brutal_purge. It controls + what action to take with processes executing old code + before loading the new module version. If the value is brutal_purge, the processes are killed. If the value is - soft_purge, release_handler:install_release/1 - returns {error,{old_processes,Mod}}.

-

PostPurge defaults to brutal_purge and controls + soft_purge, + release_handler:install_release/1 + returns {error,{old_processes,Mod}}.

+ PostPurge +

Defaults to brutal_purge. It controls what action to take with processes that are executing old code - when the new version of the module has been loaded. If the value + when the new module version has been loaded. If the value is brutal_purge, the code is purged when the release is made permanent and the processes are killed. If the value is - soft_purge, the release handler will purge the old code - when no remaining processes execute the code.

-

DepMods defaults to [] and defines which other modules - Mod is dependent on. In relup, instructions for - suspending processes using Mod will come before + soft_purge, the release handler purges the old code + when no remaining processes execute the code.

+ DepMods +

Defaults to [] and defines other modules that + Mod is dependent on. In the relup file, instructions + for suspending processes using Mod come before instructions for suspending processes using modules in - DepMods when upgrading, and vice versa when downgrading. + DepMods when upgrading, and conversely when downgrading. In case of circular dependencies, the order of the instructions in - the appup script is kept.

-

Timeout defines the timeout when suspending processes. - If no value or default is given, the default value for - sys:suspend is used.

-

ModType defaults to dynamic and specifies if - the code is "dynamic", that is if a process using the module does - spontaneously switch to new code, or if it is "static". - When doing an advanced update and upgrading, the new version of a + the appup file is kept.

+ Timeout +

Defines the time-out when suspending processes. + If no value or default is specified, the default value for + sys:suspend + is used.

+ ModType +

Defaults to dynamic. It specifies if + the code is "dynamic", that is, if a process using the module + spontaneously switches to new code, or if it is "static". + When doing an advanced update and upgrade, the new version of a dynamic module is loaded before the process is asked to change code. When downgrading, the process is asked to change code before loading the new version. For static modules, the new version is loaded before the process is asked to change code, both in the case of upgrading and downgrading. Callback modules are - dynamic.

+ dynamic.

+

update with argument supervisor is used when changing the start specification of a supervisor.

@@ -170,239 +193,229 @@
 {load_module, Mod, PrePurge, PostPurge, DepMods}
   Mod = atom()
   PrePurge = PostPurge = soft_purge | brutal_purge
-  DepMods = [Mod]
-    
+ DepMods = [Mod]

Simple code replacement of the module Mod.

-

See update above for a description of PrePurge and - PostPurge.

-

DepMods defaults to [] and defines which other modules - Mod is dependent on. In relup, instructions for - loading these modules will come before the instruction for loading - Mod when upgrading, and vice versa when downgrading.

+

For a description of PrePurge and PostPurge, + see update above.

+

DepMods defaults to [] and defines which other modules + Mod is dependent on. In the relup file, instructions for + loading these modules come before the instruction for loading + Mod when upgrading, and conversely when downgrading.

 {add_module, Mod}
 {add_module, Mod, DepMods}
   Mod = atom()
-  DepMods = [Mod]
-    
+ DepMods = [Mod]

Loads a new module Mod.

-

DepMods defaults to [] and defines which other modules - Mod is dependent on. In relup, instructions - related to these modules will come before the instruction for - loading Mod when upgrading, and vice versa when +

DepMods defaults to [] and defines which other modules + Mod is dependent on. In the relup file, instructions + related to these modules come before the instruction for + loading Mod when upgrading, and conversely when downgrading.

 {delete_module, Mod}
 {delete_module, Mod, DepMods}
-  Mod = atom()
-    
+ Mod = atom()

Deletes a module Mod using the low-level instructions remove and purge.

-

DepMods defaults to [] and defines which other modules - Mod is dependent on. In relup, instructions - related to these modules will come before the instruction for - removing Mod when upgrading, and vice versa when +

DepMods defaults to [] and defines which other modules + Mod is dependent on. In the relup file, instructions + related to these modules come before the instruction for + removing Mod when upgrading, and conversely when downgrading.

 {add_application, Application}
 {add_application, Application, Type}
   Application = atom()
-  Type = permanent | transient | temporary | load | none
-    
+ Type = permanent | transient | temporary | load | none

Adding an application means that the modules defined by the modules key in the .app file are loaded using add_module.

Type defaults to permanent and specifies the start type of the application. If Type = permanent | transient | temporary, - the application will be loaded and started in the corresponding way, - see application(3). If Type = load, the application will - only be loaded. If Type = none, the application will be neither - loaded nor started, although the code for its modules will be loaded.

+ the application is loaded and started in the corresponding way, see + application(3). + If Type = load, the application is only loaded. + If Type = none, the application is not loaded and not + started, although the code for its modules is loaded.

 {remove_application, Application}
-  Application = atom()
-    
+ Application = atom()

Removing an application means that the application is stopped, - the modules are unloaded using delete_module and then + the modules are unloaded using delete_module, and then the application specification is unloaded from the application controller.

 {restart_application, Application}
-  Application = atom()
-    
+ Application = atom()

Restarting an application means that the application is - stopped and then started again similar to using the instructions + stopped and then started again, similar to using the instructions remove_application and add_application in sequence.

-

Low-level instructions

+
+ +
+ Low-Level Instructions
 {load_object_code, {App, Vsn, [Mod]}}
   App = Mod = atom()
-  Vsn = string()
-    
-

Reads each Mod from the directory App-Vsn/ebin as - a binary. It does not load the modules. The instruction should be - placed first in the script in order to read all new code from file - to make the suspend-load-resume cycle less time consuming. After - this instruction has been executed, the code server with the new - version of App.

+ Vsn = string() +

Reads each Mod from directory App-Vsn/ebin as + a binary. It does not load the modules. The instruction is to be + placed first in the script to read all new code from the file + to make the suspend-load-resume cycle less time-consuming.

-point_of_no_return
-    
+point_of_no_return

If a crash occurs after this instruction, the system cannot - recover and is restarted from the old version of the release. - The instruction must only occur once in a script. It should be + recover and is restarted from the old release version. + The instruction must only occur once in a script. It is to be placed after all load_object_code instructions.

 {load, {Mod, PrePurge, PostPurge}}
   Mod = atom()
-  PrePurge = PostPurge = soft_purge | brutal_purge
-    
+ PrePurge = PostPurge = soft_purge | brutal_purge

Before this instruction occurs, Mod must have been loaded using load_object_code. This instruction loads the module. - PrePurge is ignored. See the high-level instruction - update for a description of PostPurge.

+ PrePurge is ignored. For a description of PostPurge, + see the high-level instruction update earlier.

 {remove, {Mod, PrePurge, PostPurge}}
   Mod = atom()
-  PrePurge = PostPurge = soft_purge | brutal_purge
-    
+ PrePurge = PostPurge = soft_purge | brutal_purge

Makes the current version of Mod old. - PrePurge is ignored. See the high-level instruction - update for a description of PostPurge.

+ PrePurge is ignored. For a description of PostPurge, + see the high-level instruction update earlier.

 {purge, [Mod]}
-  Mod = atom()
-    
-

Purges each module Mod, that is removes the old code. - Note that any process executing purged code is killed.

+ Mod = atom() +

Purges each module Mod, that is, removes the old code. + Notice that any process executing purged code is killed.

 {suspend, [Mod | {Mod, Timeout}]}
   Mod = atom()
-  Timeout = int()>0 | default | infinity
-    
+ Timeout = int()>0 | default | infinity

Tries to suspend all processes using a module Mod. If a - process does not respond, it is ignored. This may cause + process does not respond, it is ignored. This can cause the process to die, either because it crashes when it spontaneously switches to new code, or as a result of a purge operation. If no Timeout is specified or default is - given, the default value for sys:suspend is used.

+ specified, the default value for + sys:suspend + is used.

 {resume, [Mod]}
-  Mod = atom()
-    
+ Mod = atom()

Resumes all suspended processes using a module Mod.

 {code_change, [{Mod, Extra}]}
 {code_change, Mode, [{Mod, Extra}]}
   Mod = atom()
   Mode = up | down
-  Extra = term()
-    
+ Extra = term()

Mode defaults to up and specifies if it is an - upgrade or downgrade.

-

This instruction sends a code_change system message to - all processes using a module Mod by calling the function - sys:change_code, passing the term Extra as argument.

+ upgrade or downgrade. This instruction sends a code_change + system message to all processes using a module Mod by + calling function + sys:change_code, + passing term Extra as argument.

 {stop, [Mod]}
-  Mod = atom()
-    
+ Mod = atom()

Stops all processes using a module Mod by calling - supervisor:terminate_child/2. The instruction is useful + supervisor:terminate_child/2. + This instruction is useful when the simplest way to change code is to stop and restart the - processes which run the code.

+ processes that run the code.

 {start, [Mod]}
-  Mod = atom()
-    
+ Mod = atom()

Starts all stopped processes using a module Mod by calling - supervisor:restart_child/2.

+ supervisor:restart_child/2.

 {sync_nodes, Id, [Node]}
 {sync_nodes, Id, {M, F, A}}
   Id = term()
   Node = node()
   M = F = atom()
-  A = [term()]
-    
+ A = [term()]

apply(M, F, A) must return a list of nodes.

-

The instruction synchronizes the release installation with other - nodes. Each Node must evaluate this command, with the same +

This instruction synchronizes the release installation with other + nodes. Each Node must evaluate this command with the same Id. The local node waits for all other nodes to evaluate - the instruction before execution continues. In case a node goes + the instruction before execution continues. If a node goes down, it is considered to be an unrecoverable error, and the local node is restarted from the old release. There is no - timeout for this instruction, which means that it may hang + time-out for this instruction, which means that it can hang forever.

 {apply, {M, F, A}}
   M = F = atom()
-  A = [term()]
-    
-

Evaluates apply(M, F, A). If the instruction appears - before the point_of_no_return instruction, a failure is - caught. release_handler:install_release/1 then returns - {error,{'EXIT',Reason}}, unless {error,Error} is - thrown or returned. Then it returns {error,Error}.

-

If the instruction appears after the point_of_no_return - instruction, and the function call fails, the system is - restarted.

+ A = [term()] +

Evaluates apply(M, F, A).

+

If the instruction appears before instruction + point_of_no_return, a failure is caught. + release_handler:install_release/1 + then returns {error,{'EXIT',Reason}}, unless {error,Error} + is thrown or returned. Then it returns {error,Error}.

+

If the instruction appears after instruction + point_of_no_return and the function call fails, the + system is restarted.

-restart_new_emulator
-    
-

This instruction is used when erts, kernel, stdlib or sasl is +restart_new_emulator +

This instruction is used when the application ERTS, + Kernel, STDLIB, or SASL is upgraded. It shuts down the current emulator and starts a new one. All processes are terminated gracefully, and the new - version of erts, kernel, stdlib and sasl are used when the - emulator restarts. Only one restart_new_emulator - instruction is allowed in the relup, and it shall be placed - first. systools:make_relup/3,4 - will ensure this when the relup is generated. The rest of the - relup script is executed after the restart as a part of the boot - script.

-

An info report will be written when the upgrade is - completed. To programatically find out if the upgrade is - complete, + version of ERTS, Kernel, STDLIB, and + SASL are used when the emulator restarts. + Only one restart_new_emulator instruction is allowed + in the relup file, and it must be placed first. + systools:make_relup/3,4 + ensures this when the relup file is generated. The rest of the + instructions in the relup file is executed after the + restart as a part of the boot script.

+

An info report is written when the upgrade is completed. + To programmatically determine if the upgrade is complete, call - release_handler:which_releases/0,1 and check if the + release_handler:which_releases/0,1 and check if the expected release has status current.

The new release must still be made permanent after the upgrade - is completed. Otherwise, the old emulator is started in case of + is completed, otherwise the old emulator is started if there is an emulator restart.

-

As stated above, the restart_new_emulator - instruction causes the emulator to be restarted with new - versions of erts, kernel, stdlib and - sasl. All other applications, however, will at startup - be running their old versions in this new emulator. In most - cases this is no problem, but every now and then there will be - incompatible changes to the core applications which may cause - trouble in this setting. Such incompatible changes (when - functions are removed) are normally preceded by a deprecation - over two major releases. To make sure your application is not - crashed by an incompatible change, always remove any call to - deprecated functions as soon as possible.

+

As stated earlier, instruction restart_new_emulator + causes the emulator to be restarted with new versions of + ERTS, Kernel, STDLIB, and SASL. + However, all other applications do at startup run their old + versions in this new emulator. This is usually no problem, + but every now and then incompatible changes occur to the + core applications, which can cause + trouble in this setting. Such incompatible changes (when + functions are removed) are normally preceded by a deprecation + over two major releases. To ensure that your application is not + crashed by an incompatible change, always remove any call to + deprecated functions as soon as possible.

-restart_emulator
-    
+restart_emulator

This instruction is similar to restart_new_emulator, - except it shall be placed at the end of the relup script. It is - not related to an upgrade of the emulator or the core + except it must be placed at the end of the relup file. + It is not related to an upgrade of the emulator or the core applications, but can be used by any application when a complete - reboot of the system is reqiured. When generating the - relup, systools:make_relup/3,4 + reboot of the system is required.

+

When generating the relup file, + systools:make_relup/3,4 ensures that there is only one restart_emulator - instruction and that it is the last instruction of the - relup.

+ instruction and that it is the last instruction in the + relup file.

+
- SEE ALSO -

relup(4), - release_handler(3), - supervisor(3), - systools(3)

+ See Also +

release_handler(3), + relup(4), + supervisor(3), + systools(3)

diff --git a/lib/sasl/doc/src/book.xml b/lib/sasl/doc/src/book.xml index 2bb5339d94..624c32a66f 100644 --- a/lib/sasl/doc/src/book.xml +++ b/lib/sasl/doc/src/book.xml @@ -22,7 +22,7 @@ - System Application Support Libraries (SASL) + System Architecture Support Libraries (SASL) OTP Team 1999-04-22 @@ -31,7 +31,7 @@ - System Application Support Libraries (SASL) + System Architecture Support Libraries (SASL) diff --git a/lib/sasl/doc/src/error_logging.xml b/lib/sasl/doc/src/error_logging.xml index 7c45b1970e..46b12f3872 100644 --- a/lib/sasl/doc/src/error_logging.xml +++ b/lib/sasl/doc/src/error_logging.xml @@ -31,89 +31,93 @@ 1999-04-13 B error_logging.xml - -

The SASL application introduces three types of reports:

+ +

The SASL application introduces three types of reports:

- supervisor report - progress report - crash report. + Supervisor report + Progress report + Crash report -

When the SASL application is started, it adds a handler that - formats and writes these reports, as specified in the - configuration parameters for sasl, i.e the environment variables - in the SASL application specification, which is found in the - .app file of SASL. See - sasl(Application), and app(File) - in the Kernel Reference Manual - for the details.

+

When the SASL application is started, it adds a handler that + formats and writes these reports, as specified in the configuration + parameters for SASL, that is, the environment variables + in the SASL application specification, which is found in the + .app file of SASL. For details, see the + sasl(6) application in the + Reference Manual and the app(4) + file in the Kernel Reference Manual.

Supervisor Report -

A supervisor report is issued when a supervised child terminates in - an unexpected way. A supervisor report contains the following +

A supervisor report is issued when a supervised child terminates + unexpectedly. A supervisor report contains the following items:

- Supervisor. - The name of the reporting supervisor. - Context. - Indicates in which phase the child terminated + Supervisor +

Name of the reporting supervisor.

+ Context +

Indicates in which phase the child terminated from the supervisor's point of view. This can be - start_error, child_terminated, or - shutdown_error. - Reason. - The termination reason. - Offender. - The start specification for the child. + start_error, child_terminated, or + shutdown_error.

+ Reason +

Termination reason.

+ Offender +

Start specification for the child.

Progress Report -

A progress report is issued whenever a supervisor starts or - restarts. A progress report contains the following items:

+

A progress report is issued when a supervisor starts or + restarts a child. A progress report contains the following items:

- Supervisor. - The name of the reporting supervisor. - Started. - The start specification for the successfully - started child. + Supervisor +

Name of the reporting supervisor.

+ Started +

Start specification for the successfully + started child.

Crash Report -

Processes started with the proc_lib:spawn or - proc_lib:spawn_link functions are wrapped within a - catch. A crash report is issued whenever such a process - terminates with an unexpected reason, which is any reason other - than normal or shutdown. Processes using the - gen_server and gen_fsm behaviours are examples of - such processes. A crash report contains the following items:

+

Processes started with functions + proc_lib:spawn or + proc_lib:spawn_link + are wrapped within a catch. A crash report is issued when such + a process terminates with an unexpected reason, which is any reason + other than normal, shutdown, or {shutdown,Term}. + Processes using behaviors + gen_server or + gen_fsm + are examples of such processes. A crash report contains the following items:

- Crasher. - Information about the crashing process is reported, such - as initial function call, exit reason, and message queue. - Neighbours. - Information about processes which are linked to the crashing + Crasher +

Information about the crashing process, such + as initial function call, exit reason, and message queue.

+ Neighbours +

Information about processes that are linked to the crashing process and do not trap exits. These processes are the - neighbours which will terminate because of this process + neighbours that terminate because of this process crash. The information gathered is the same as the information - for Crasher, shown in the previous item. + for Crasher, described in the previous item.

- An Example -

The following example shows the reports which are generated - when a process crashes. The example process is an + Example +

The following example shows the reports generated + when a process crashes. The example process is a permanent process supervised by the test_sup supervisor. A division by zero is executed and the error is first reported by the faulty process. A crash report is - generated as the process was started using the - proc_lib:spawn/3 function. The supervisor generates a - supervisor report showing the process that has crashed, and then a + generated, as the process was started using function + proc_lib:spawn/3. + The supervisor generates a + supervisor report showing the crashed process. A progress report is generated when the process is finally - re-started.

+ restarted.

         =ERROR REPORT==== 27-May-1996::13:38:56 ===
         <0.63.0>: Divide by zero !
@@ -146,7 +150,6 @@
         {shutdown,200},
         {child_type,worker}]
         
-        
         =PROGRESS REPORT==== 27-May-1996::13:38:56 ===
         Supervisor: {local,test_sup}
         Started:  [{pid,<0.64.0>},
@@ -154,64 +157,66 @@
         {mfa,{test,t,[]}},
         {restart_type,permanent},
         {shutdown,200},
-        {child_type,worker}]
-      
+ {child_type,worker}]
Multi-File Error Report Logging -

Multi-file error report logging is used to store error messages, - which are received by the error_logger. The error messages +

Multi-file error report logging is used to store error messages + received by error_logger. The error messages are stored in several files and each file is smaller than a - specified amount of kilobytes, and no more than a specified number - of files exist at the same time. The logging is very fast because + specified number of kilobytes. No more than a specified number + of files exist at the same time. The logging is very fast, as each error message is written as a binary term.

-

Refer to - sasl application in the Reference Manual for more details.

+

For more details, see the + sasl(6) + application in the Reference Manual.

Report Browser

The report browser is used to browse and format error reports - written by the error logger handler log_mf_h defined in - stdlib.

+ written by the error logger handler + log_mf_h + defined in STDLIB.

The log_mf_h handler writes all reports to a - report logging directory. This directory is specified when - configuring the SASL application.

+ report logging directory, which is specified when + configuring the SASL application.

If the report browser is - used off-line, the reports can be copied to another directory - which is specified when starting the browser. If no such directory - is specified, the browser reads reports from the SASL + used offline, the reports can be copied to another directory + specified when starting the browser. If no such directory + is specified, the browser reads reports from the SASL error_logger_mf_dir.

- Starting the Report Browser -

Start the rb_server with the function - rb:start([Options]) as shown in the following - example:

+ Starting Report Browser +

Start the rb_server with function + rb:start([Options]) + as shown in the following example:

-
-        5>rb:start([{max, 20}]).
+        5> rb:start([{max, 20}]).
         rb: reading report...done.
         rb: reading report...done.
         rb: reading report...done.
         rb: reading report...done.
-      
+ {ok,<0.199.0>}
- On-line Help -

Enter the command rb:help(). to access the report - browser on-line help system.

+ Online Help +

Enter command + rb:help() + to access the report browser online help system.

- List Reports in the Server -

The function rb:list() lists all loaded reports:

+ List Reports in Server +

Use function + rb:list() + to list all loaded reports:

-
-        4>rb:list().
+        4> rb:list().
         No                Type          Process       Date     Time
         ==                ====          =======       ====     ====
         20            progress         <0.17.0> 1996-10-16 16:14:54
@@ -234,17 +239,15 @@
         3            progress         <0.14.0> 1996-10-16 16:16:36
         2               error         <0.15.0> 1996-10-16 16:17:04
         1            progress         <0.14.0> 1996-10-16 16:17:09
-        ok
-      
+ ok
Show Reports -

To show details of a specific report, use the function - rb:show(Number):

+

Use function + rb:show(Number) + to show details of a specific report:

-
-10> rb:show(1).
 7> rb:show(4).
         
 PROGRESS REPORT  <0.20.0>                                   1996-10-16 16:16:36
@@ -259,7 +262,7 @@ started
 {child_type,worker}]
         
 ok
-8> rb:show(9).
+8> rb:show(9).
         
 CRASH REPORT  <0.24.0>                                      1996-10-16 16:16:21
 ===============================================================================
@@ -287,19 +290,17 @@ heap_size                                                                610
 stack_size                                                               142
 reductions                                                                54
 
-ok
-      
+ok
- Search the Reports -

It is possible to show all reports which contain a common - pattern. Suppose a process crashes because it tries to call a - non-existing function release_handler:mbj_func. We could - then show reports as follows:

+ Search Reports +

All reports containing a common pattern can be shown. + Suppose a process crashes because it tries to call a + non-existing function release_handler:mbj_func/1. + The reports can then be shown as follows:

-
-12>rb:grep("mbj_func").          
+12> rb:grep("mbj_func").
 Found match in report number 11
         
 ERROR REPORT  <0.24.0>                                      1996-10-16 16:16:21
@@ -368,19 +369,17 @@ restart_type                                                       permanent
 shutdown                                                                2000
 child_type                                                            worker
         
-ok
-      
+ok
- Stop the Server -

Stop the rb_server with the function - rb:stop():

+ Stop Server +

Use function + rb:stop() + to stop the rb_server:

-
-13>rb:stop().
-ok
-      
+13> rb:stop(). +ok
diff --git a/lib/sasl/doc/src/overload.xml b/lib/sasl/doc/src/overload.xml index 35877220ab..5c3d00afeb 100644 --- a/lib/sasl/doc/src/overload.xml +++ b/lib/sasl/doc/src/overload.xml @@ -35,98 +35,88 @@ overload An Overload Regulation Process -

overload is a process which indirectly regulates CPU +

overload is a process that indirectly regulates the CPU usage in the system. The idea is that a main application calls - the request/0 function before starting a major job, and + function + request/0 + before starting a major job and proceeds with the job if the return value is positive; otherwise - the job must not be started. -

-

overload is part of the sasl application, and all - configuration parameters are defined there. -

-

A set of two intensities are maintained, the total intensity and the accept intensity. For that purpose - there are two configuration parameters, the MaxIntensity - and the Weight value (both are measured in 1/second). -

+ the job must not be started.

+

overload is part of the SASL application and all + configuration parameters are defined there.

+

A set of two intensities are maintained, the total intensity + and the accept intensity. For that purpose, + there are two configuration parameters, MaxIntensity + and Weight; both are measured in 1/second.

Then total and accept intensities are calculated as follows. Assume that the time of the current call to - request/0 is T(n), and that the time of the - previous call was T(n-1). -

+ request/0 is T(n) and that the time of the + previous call was T(n-1).

The current total intensity, denoted - TI(n), is calculated according to the formula, -

-

TI(n) = exp(-Weight*(T(n) - T(n-1)) * TI(n-1) + Weight, -

-

where TI(n-1) is the previous total intensity. -

+ TI(n), is calculated according to the formula

+

TI(n) = exp(-Weight*(T(n) - T(n-1)) * TI(n-1) + Weight,

+

where TI(n-1) is the previous total intensity.

The current accept intensity, denoted - AI(n), is determined by the formula, -

-

AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1) + Weight, -

-

where AI(n-1) is the previous accept intensity, - provided that the value of exp(-Weight*(T(n) - T(n-1)) * AI(n-1) is less than MaxIntensity; otherwise the - value is -

-

AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1). -

+ AI(n), is determined by the formula

+

AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1) + Weight,

+

where AI(n-1) is the previous accept intensity, + if the value of exp(-Weight*(T(n) - T(n-1)) * AI(n-1) + is less than MaxIntensity. Otherwise the value is

+

AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1)

The value of configuration parameter Weight controls the - speed with which the calculations of intensities will react to + speed with which the calculations of intensities react to changes in the underlying input intensity. The inverted value of - Weight, -

-

T = 1/Weight

-

can be thought of as the "time constant" - of the intensity calculation formulas. For example, if Weight = 0.1, then a change in the underlying input intensity will be - reflected in the total and accept intensities within - approximately 10 seconds. -

+ Weight, T = 1/Weight, can be thought of as the + "time constant" of the intensity calculation formulas. For example, + if Weight = 0.1, a change in the underlying input intensity is + reflected in total intensity and accept intensity within + about 10 seconds.

The overload process defines one alarm, which it sets using - alarm_handler:set_alarm(Alarm). Alarm is defined - as: -

+ alarm_handler:set_alarm(Alarm). Alarm is defined + as follows:

{overload, []} -

This alarm is set when the current accept intensity exceeds - MaxIntensity. -

+

This alarm is set when the current accept intensity exceeds + MaxIntensity.

-

A new overload alarm is not set until the current accept - intensity has fallen below MaxIntensity. To prevent the - overload process from generating a lot of set/reset alarms, the - alarm is not reset until the current accept intensity has fallen - below 75% of MaxIntensity, and it is not until then that - the alarm can be set again. -

+

A new request is not accepted until the current accept + intensity has fallen below MaxIntensity. To prevent the + overload process from generating many set/reset alarms, the + alarm is not reset until the current accept intensity has fallen + below 75% of MaxIntensity; it is not until then that + the alarm can be set again.

+ request() -> accept | reject - Request to proceed with current job + Requests to proceed with current job.

Returns accept or reject depending on the - current value of the accept intensity.

+ current value of the accept intensity.

The application - calling this function should be processed with the job in + calling this function is to proceed with the job in question if the return value is accept; otherwise it - should not continue with that job. -

+ is not to continue with that job.

+ get_overload_info() -> OverloadInfo - Return current overload information data + Returns current overload information data. - OverloadInfo = [{total_intensity, TotalIntensity}, {accept_intensity, AcceptIntensity}, {max_intensity, MaxIntensity}, {weight, Weight}, {total_requests, TotalRequests}, {accepted_requests, AcceptedRequests}]. + OverloadInfo = [{total_intensity, TotalIntensity}, + {accept_intensity, AcceptIntensity}, {max_intensity, + MaxIntensity}, {weight, Weight}, {total_requests, + TotalRequests}, {accepted_requests, AcceptedRequests}]. TotalIntensity = float() > 0 AcceptIntensity = float() > 0 MaxIntensity = float() > 0 @@ -135,18 +125,22 @@ AcceptedRequests = integer() -

Returns the current total and accept intensities, the - configuration parameters, and absolute counts of the total - number of requests, and accepted number of requests (since - the overload process was started).

+

Returns:

+ + Current total and accept intensities + Configuration parameters + Absolute counts of the total number of requests + Accepted number of requests (since the overload + process was started) +
See Also -

alarm_handler(3), sasl(3) -

+

alarm_handler(3), + sasl(6)

diff --git a/lib/sasl/doc/src/part.xml b/lib/sasl/doc/src/part.xml index bcd345a7c4..2f47a8ad80 100644 --- a/lib/sasl/doc/src/part.xml +++ b/lib/sasl/doc/src/part.xml @@ -30,8 +30,9 @@ part.xml -

The System Architecture Support Libraries, SASL, - provides support for alarm and release handling etc.

+

The System Architecture Support Libraries SASL application + provides support for alarm handling, release handling, and + related functions.

diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml index 85252fc088..e16e9f5a62 100644 --- a/lib/sasl/doc/src/rb.xml +++ b/lib/sasl/doc/src/rb.xml @@ -35,241 +35,252 @@ rb The Report Browser Tool -

The Report Browser (RB) tool makes it possible to browse and +

The Report Browser (RB) tool is used to browse and format error reports written by the error logger handler - log_mf_h. -

+ log_mf_h + in STDLIB.

+ filter(Filters) filter(Filters, Dates) - Filter reports and displays them on the screen + Filters reports and displays them on the screen. Filters = [filter()] - filter() = {Key, Value} | {Key, Value, no} | {Key, RegExp, re} | {Key, RegExp, re, no} + filter() = {Key, Value} | {Key, Value, no} | {Key, RegExp, re} | + {Key, RegExp, re, no} Key = term() Value = term() - RegExp = string() | {string, Options} | mp(), {mp(), Options} + RegExp = string() | {string(), Options} | re:mp() | {re:mp(), Options} Dates = {DateFrom, DateTo} | {DateFrom, from} | {DateTo, to} - DateFrom = DateTo = {date(), time()} - date() and time() are the same type as in the calendar module + DateFrom = DateTo = calendar:datetime() -

This function displays the reports that match the provided filters.

-

- When a filter includes the no atom it will exclude the reports that match - that filter. -

-

- The reports are matched using the proplists module. The report must be a proplist - to be matched against any of the filters(). -

-

- If the filter is of the form {Key, RegExp, re} the report must contain an element with - key = Key and Value must match the RegExp regular expression. -

-

- If the Dates parameter is provided, then the reports are filtered according to the date - when they occurred. If Dates is of the form {DateFrom, from} then reports that occurred - after DateFrom are displayed. -

-

- If Dates is of the form {DateTo, to} then reports that occurred before DateTo - are displayed. -

-

- If two Dates are provided, then reports that occurred between those dates are returned. -

-

- If you only want to filter only by dates, then you can provide the empty list as the Filters - parameter. -

-

- See rb:grep/1 for more information on the RegExp parameter. -

+

Displays the reports that match the provided filters.

+

When a filter includes the no atom, it excludes the + reports that match that filter.

+

The reports are matched using the + proplists + module in STDLIB. The report must be a proplist + to be matched against any of the filters.

+

If the filter has the form {Key, RegExp, re}, the + report must contain an element with key equal to Key and + the value must match the regular expression RegExp.

+

If parameter Dates is specified, the reports are filtered + according to the date when they occurred. If Dates has + the form {DateFrom, from}, reports that occurred after + DateFrom are displayed.

+

If Dates has the form {DateTo, to}, reports that + occurred before DateTo are displayed.

+

If two Dates are specified, reports that occurred between + those dates are returned.

+

To filter only by dates, specify the empty list as the Filters + parameter.

+

For details about parameter RegExp, see rb:grep/1.

+

For details about data type mp(), see + re:mp().

+

For details about data type datetime(), see + calendar:datetime().

+ grep(RegExp) - Search the reports for a regular expression + Searches the reports for a regular expression. - RegExp = string() | {string, Options} | mp(), {mp(), Options} + RegExp = string() | {string(), Options} | re:mp() | {re:mp(), Options} -

All reports containing the regular expression RegExp - are printed. -

-

RegExp can be a string containing the regular - expression; a tuple with the string and the options for - compilation; a compiled regular expression; a compiled - regular expression and the options for running it. - Refer to the module re and specially the function re:run/3 - for a definition of valid regular expressions and options. -

+

All reports matching the regular expression RegExp + are displayed. RegExp can be any of the following:

+ + A string containing the regular expression + A tuple with the string and the options for compilation + A compiled regular expression + A compiled regular expression and the options for running it + +

For a definition of valid regular expressions and options, see + the re module in + STDLIB and in particular function re:run/3.

+

For details about data type mp(), see + re:mp().

+ h() help() - Print help information + Displays help information. -

Prints the on-line help information. -

+

Displays online help information.

+ list() list(Type) - List all reports + Lists all reports. Type = type() type() = error | error_report | info_msg | info_report | - warning_msg | warning_report | crash_report | - supervisor_report | progress + warning_msg | warning_report | crash_report | + supervisor_report | progress -

This function lists all reports loaded in the +

Lists all reports loaded in rb_server. Each report is given a unique number that - can be used as a reference to the report in the - show/1 function. -

-

If no Type is given, all reports are listed. -

+ can be used as a reference to the report in function + show/1.

+

If no Type is specified, all reports are listed.

+ log_list() log_list(Type) - Log reports list + Logs report lists. Type = type() type() = error | error_report | info_msg | info_report | - warning_msg | warning_report | crash_report | - supervisor_report | progress + warning_msg | warning_report | crash_report | + supervisor_report | progress -

Same as list/0 or list/1 functions - but result is printed to logfile, if set, otherwise to standard_io. -

-

If no Type is given, all reports are listed. -

+

Same as functions + list/0 or + list/1, + but the result is printed to a log file, if set; otherwise + to standard_io.

+

If no Type is specified, all reports are listed.

+ rescan() rescan(Options) - Rescan the report directory + Rescans the report directory. Options = [opt()]

Rescans the report directory. Options is the same as - for start(). -

+ for function + start/1.

+ show() show(Report) - Show reports + Displays reports. - Report = int() | type() + Report = integer() | type() -

If a type argument is given, all loaded reports of this - type are printed. If an integer argument is given, the - report with this reference number is printed. If no argument - is given, all reports are shown. -

+

If argument type is specified, all loaded reports of this + type are displayed. If an integer argument is specified, the + report with this reference number is displayed. If no argument + is specified, all reports are displayed.

+ start() start(Options) - Start the RB server + Starts the rb_server. Options = [opt()] - opt() = {start_log, FileName} | {max, MaxNoOfReports} | {report_dir, DirString} | {type, ReportType} | {abort_on_error, Bool} + opt() = {start_log, FileName} | {max, MaxNoOfReports} | + {report_dir, DirString} | {type, ReportType} | + {abort_on_error, Bool} FileName = string() | atom() | pid() - MaxNoOfReports = int() | all + MaxNoOfReports = integer() | all DirString = string() ReportType = type() | [type()] | all - Bool = true | false + Bool = boolean() -

The function start/1 starts the rb_server - with the specified options, while start/0 starts with - default options. The rb_server must be started before - reports can be browsed. When the rb_server is +

Function start/1 starts rb_server with the + specified options, whereas function start/0 starts with + default options. rb_server must be started before + reports can be browsed. When rb_server is started, the files in the specified directory are scanned. The other functions assume that the server has - started. -

-

{start_log, FileName} starts logging to file, - registered name or io_device. All reports will be printed - to the named file. The default is standard_io. - The option {start_log, standard_error} is not allowed and - will be replaced by default standard_io. -

-

{max, MaxNoOfReports}. Controls how many reports the - rb_server should read on start-up. This option is - useful as the directory may contain 20.000 reports. If this - option is given, the MaxNoOfReports latest reports - will be read. The default is 'all'. -

-

{report_dir, DirString}. Defines the directory where - the error log files are located. The default is {sasl, error_logger_mf_dir}.

-

{type, ReportType}. Controls what kind of reports the - rb_server should read on start-up. ReportType - is a supported type, 'all', or a list of supported - types. The default is 'all'. -

-

{abort_on_error, Bool}. This option specifies whether - or not logging should be aborted if rb encounters an unprintable - report. (You may get a report on incorrect form if the - error_logger function error_msg or - info_msg has been called with an invalid format string). - If Bool is true, rb will stop logging (and print an - error message to stdout) if it encounters a badly formatted report. - If logging to file is enabled, an error message will be appended to - the log file as well. - If Bool is false (which is the default value), rb will - print an error message to stdout for every bad report it - encounters, but the logging process is never aborted. All printable - reports will be written. If logging to file is enabled, rb prints - * UNPRINTABLE REPORT * in the log file at the location of an - unprintable report. -

+ started.

+

Options:

+ + {start_log, FileName} +

Starts logging to file, + registered name, or io_device. All reports are printed + to the specified destination. Default is standard_io. + Option {start_log, standard_error} is not allowed and + will be replaced by default standard_io.

+ {max, MaxNoOfReports} +

Controls how many reports + rb_server is to read at startup. This option is + useful, as the directory can contain a large amount of reports. If this + option is specified, the MaxNoOfReports latest reports + are read. Default is all.

+ {report_dir, DirString} +

Defines the directory where + the error log files are located. Default is + the directory specified by application environment + variable error_logger_mf_dir, + see sasl(6).

+ {type, ReportType} +

Controls what kind of reports + rb_server is to read at startup. ReportType + is a supported type, all, or a list of supported + types. Default is all.

+ {abort_on_error, Bool} +

Specifies if + logging is to be ended if rb encounters an unprintable + report. (You can get a report with an incorrect form if function + error_logger, error_msg, or + info_msg has been called with an invalid format string)

+ + If Bool is true, rb stops logging + (and prints an error message to stdout) if it encounters + a badly formatted report. If logging to file is enabled, an + error message is appended to the log file as well. + If Bool is false (the default value), rb + prints an error message to stdout for every bad report it + encounters, but the logging process is never ended. All printable + reports are written. If logging to file is enabled, rb prints + * UNPRINTABLE REPORT * in the log file at the location of an + unprintable report. +
+
+ start_log(FileName) - Redirect all output to FileName + Redirects all output to FileName. FileName = string() | atom() | pid()

Redirects all report output from the RB tool to the - specified file, registered name or io_device. -

+ specified file, registered name, or io_device.

+ stop() - Stop the RB server + Stops the rb_server. -

Stops the rb_server. -

+

Stops rb_server.

+ stop_log() - Stop logging to file + Stops logging to file. -

Closes the log file. The output from the RB tool will be - directed to standard_io. -

+

Closes the log file. The output from the RB tool is + directed to standard_io.

diff --git a/lib/sasl/doc/src/ref_man.xml b/lib/sasl/doc/src/ref_man.xml index 2b608c7c51..a80e5a2a00 100644 --- a/lib/sasl/doc/src/ref_man.xml +++ b/lib/sasl/doc/src/ref_man.xml @@ -30,8 +30,8 @@ application.xml -

The System Architecture Support Libraries application, SASL, - provides support for alarm and release handling etc.

+

The SASL application provides support for alarm handling, + release handling, and related functions.

diff --git a/lib/sasl/doc/src/rel.xml b/lib/sasl/doc/src/rel.xml index a16db24295..d5f3c7310a 100644 --- a/lib/sasl/doc/src/rel.xml +++ b/lib/sasl/doc/src/rel.xml @@ -33,74 +33,65 @@ rel Release resource file -

The release resource file specifies which applications are +

The release resource file specifies which applications are included in a release (system) based on Erlang/OTP.

-

This file is used by the functions in systools when generating - start scripts (.script, .boot) and release upgrade - files (relup).

+

This file is used by the functions in + systools + when generating start scripts (.script, .boot) and + release upgrade files (relup).

- FILE SYNTAX -

The release resource file should be called Name.rel.

+ File Syntax +

The release resource file is to be called Name.rel.

The .rel file contains one single Erlang term, which is - called a release specification. The file has the + called a release specification. The file has the following syntax:

{release, {RelName,Vsn}, {erts, EVsn}, [{Application, AppVsn} | {Application, AppVsn, Type} | {Application, AppVsn, IncApps} | - {Application, AppVsn, Type, IncApps}]}. - - - -

RelName = string() is the name of the release.

-
- -

Vsn = string() is the version of the release.

-
- -

EVsn = string() is the version of ERTS the release is - intended for.

-
- -

Application = atom() is the name of an application - included in the release.

-
- -

AppVsn = string() is the version of an application - included in the release.

-
- -

Type = permanent | transient | temporary | load | none - is the start type of an application included in the release.

-

If Type = permanent | transient | temporary, - the application will be loaded and started in the corresponding - way, see application(3). If Type = load, - the application will only be loaded. If Type = none, - the application will be neither loaded nor started, although - the code for its modules will be loaded. - Defaults to permanent

-
- -

IncApps = [atom()] is a list of applications that are - included by an application included in the release.

-

The list must be a subset of the included applications + {Application, AppVsn, Type, IncApps}]}. + + RelName = string() +

Release name.

+ Vsn = string() +

Release version.

+ EVsn = string() +

ERTS version the release is intended for.

+ Application = atom() +

Name of an application included in the release.

+ AppVsn = string() +

Version of an application included in the release.

+ Type = permanent | transient | temporary | load | none +

Start type of an application included in the release.

+

If Type = permanent | transient | temporary, the + application is loaded and started in the corresponding way, see + application(3).

+

If Type = load, the application is only loaded.

+

If Type = none, the application is not loaded and not + started, although the code for its modules is loaded.

+

Defaults to permanent

+ IncApps = [atom()] +

A list of applications that are included by an application + included in the release. The list must be a subset of the + included applications specified in the application resource file (Application.app) and overrides this value. Defaults - to the same value as in the application resource file.

-
-
+ to the same value as in the application resource file.

+ -

The list of applications must contain the kernel and - stdlib applications.

+

The list of applications must contain the Kernel and + STDLIB applications.

- SEE ALSO -

application(3), relup(4), systools(3)

+ See Also +

application(3), + relup(4), + systools(3)

diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml index 692159d7bf..162707676c 100644 --- a/lib/sasl/doc/src/release_handler.xml +++ b/lib/sasl/doc/src/release_handler.xml @@ -31,109 +31,115 @@ release_handler Unpacking and Installation of Release Packages -

The release handler is a process belonging to the SASL - application which is responsible for release handling, +

The release handler process belongs to the SASL + application, which is responsible for release handling, that is, unpacking, installation, and removal of release packages.

-

An introduction to release handling and a usage example can be - found in - Design Principles. -

+

An introduction to release handling and an example is provided in + OTP Design + Principles in System Documentation.

A release package is a compressed tar file containing code for a certain version of a release, created by calling - systools:make_tar/1,2. - The release package should be placed in the $ROOT/releases - directory of the previous version of the release where + systools:make_tar/1,2. + The release package is to be located in the $ROOT/releases + directory of the previous version of the release, where $ROOT is the installation root directory, - code:root_dir(). - Another releases directory can be specified using the SASL - configuration parameter releases_dir, or the OS environment + code:root_dir(). + Another releases directory can be specified using the SASL + configuration parameter releases_dir or the OS environment variable RELDIR. The release handler must have write access - to this directory in order to install the new release. + to this directory to install the new release. The persistent state of the release handler is stored there in a file called RELEASES.

-

A release package should always contain the release resource file - Name.rel and a boot script Name.boot. It may contain - a release upgrade file relup and a system configuration - file sys.config. The .rel file contains information - about the release: its name, version, and which ERTS and - application versions it uses. The relup file contains - scripts for how to upgrade to, or downgrade from, this version of - the release.

+

A release package is always to contain:

+ + A release resource file, Name.rel + A boot script, Name.boot + +

The .rel file contains information about the release: its name, + version, and which ERTS and application versions it uses.

+

A release package can also contain:

+ + A release upgrade file, relup + A system configuration file, sys.config + +

The relup file contains instructions for how to upgrade + to, or downgrade from, this version of the release.

The release package can be unpacked, which extracts the files. An unpacked release can be installed. The currently used version of the release is then upgraded or downgraded to the specified version by evaluating the instructions - in relup. An installed release can be made - permanent. There can only be one permanent release in - the system, and this is the release that is used if the system + in the relup file. An installed release can be made + permanent. Only one permanent release can exist in + the system, and this release is used if the system is restarted. An installed release, except the permanent one, can be removed. When a release is removed, all files - that belong to that release only are deleted.

-

Each version of the release has a status. The status can be + belonging to that release only are deleted.

+

Each release version has a status, which can be unpacked, current, permanent, or old. - There is always one latest release which either has status - permanent (normal case), or current (installed, but - not yet made permanent). The following table illustrates - the meaning of the status values:

+ There is always one latest release, which either has status + permanent (normal case) or current (installed, but + not yet made permanent). The meaning of the status values are + illustrated in the following table:

-Status     Action                NextStatus
--------------------------------------------
-  -        unpack                unpacked
-unpacked   install               current
-           remove                  -
-current    make_permanent        permanent
-           install other         old
-           remove                  -
-permanent  make other permanent  old
-           install               permanent
-old        reboot_old            permanent
-           install               current
-           remove                  -
-    
+ Status Action NextStatus + ------------------------------------------- + - unpack unpacked + unpacked install current + remove - + current make_permanent permanent + install other old + remove - + permanent make other permanent old + install permanent + old reboot_old permanent + install current + remove -

The release handler process is a locally registered process on each node. When a release is installed in a distributed system, the release handler on each node must be called. The release - installation may be synchronized between nodes. From an operator - view, it may be unsatisfactory to specify each node. The aim is + installation can be synchronized between nodes. From an operator + view, it can be unsatisfactory to specify each node. The aim is to install one release package in the system, no matter how many - nodes there are. If this is the case, it is recommended that - software management functions are written which take care of - this problem. Such a function may have knowledge of the system + nodes there are. It is recommended that + software management functions are written that take care of + this problem. Such a function can have knowledge of the system architecture, so it can contact each individual release handler to install the package.

-

For release handling to work properly, the runtime system needs - to have knowledge about which release it is currently running. It - must also be able to change (in run-time) which boot script and - system configuration file should be used if the system is +

For release handling to work properly, the runtime system must + know which release it is running. It + must also be able to change (in runtime) which boot script and + system configuration file are to be used if the system is restarted. This is taken care of automatically if Erlang is - started as an embedded system. Read about this in Embedded System. In this case, the system configuration file - sys.config is mandatory.

-

The installation of a new release may restart the system. Which - program to use is specified by the SASL configuration - parameter start_prg which defaults + started as an embedded system. Read about this in + Embedded System in + System Documentation. In this case, the system + configuration file sys.config is mandatory.

+

The installation of a new release can restart the system. Which + program to use is specified by the SASL configuration + parameter start_prg, which defaults to $ROOT/bin/start.

The emulator restart on Windows NT expects that the system is started using the erlsrv program (as a service). - Furthermore the release handler expects that the service is named - NodeName_Release, where NodeName is - the first part of the Erlang nodename (up to, but not including - the "@") and Release is the current version of - the release. The release handler furthermore expects that a + Furthermore, the release handler expects that the service is named + NodeName_Release, where NodeName is + the first part of the Erlang node name (up to, but not including + the "@") and Release is the current release version. + The release handler furthermore expects that a program like start_erl.exe is specified as "machine" to - erlsrv. During upgrading with restart, a new service will - be registered and started. The new service will be set to - automatic and the old service removed as soon as the new release + erlsrv. During upgrading with restart, a new service + is registered and started. The new service is set to + automatic and the old service is removed when the new release is made permanent.

-

The release handler at a node which runs on a diskless machine, +

The release handler at a node running on a diskless machine, or with a read-only file system, must be configured accordingly - using the following sasl configuration parameters (see - sasl(6) for details):

+ using the following SASL configuration parameters (for + details, see sasl(6)):

masters -

This node uses a number of master nodes in order to store - and fetch release information. All master nodes must be up - and running whenever release information is written by this +

This node uses some master nodes to store + and fetch release information. All master nodes must be + operational whenever release information is written by this node.

client_directory @@ -145,24 +151,25 @@ old reboot_old permanent

This parameter specifies if the Erlang emulator is statically installed at the client node. A node with a static - emulator cannot dynamically switch to a new emulator because + emulator cannot dynamically switch to a new emulator, as the executable files are statically written into memory.

-

It is also possible to use the release handler to unpack and +

The release handler can also be used to unpack and install release packages when not running Erlang as an embedded - system, but in this case the user must somehow make sure that + system. However, in this case the user must somehow ensure that correct boot scripts and configuration files are used if - the system needs to be restarted.

-

There are additional functions for using another file structure + the system must be restarted.

+

Functions are provided for using another file structure than the structure defined in OTP. These functions can be used to test a release upgrade locally.

+ check_install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason} check_install_release(Vsn,Opts) -> {ok, OtherVsn, Descr} | {error, Reason} - Check installation of a release in the system. + Checks installation of a release in the system. Vsn = OtherVsn = string() Opts = [Opt] @@ -173,27 +180,29 @@ old reboot_old permanent

Checks if the specified version Vsn of the release can be installed. The release must not have status - current. Issues warnings if relup or - sys.config are not present. If relup is present, + current. Issues warnings if relup file or + sys.config is not present. If relup file is present, its contents are checked and {error,Reason} is returned if an error is found. Also checks that all required - applications are present and that all new code can be loaded, - or {error,Reason} is returned.

-

This function evaluates all instructions that occur before + applications are present and that all new code can be loaded; + {error,Reason} is returned if an error is found.

+

Evaluates all instructions that occur before the point_of_no_return instruction in the release upgrade script.

-

Returns the same as install_release/1. Descr - defaults to "" if no relup file is found.

-

If the option purge is given, all old code that can - be soft purged will be purged after all other checks are - successfully completed. This can be useful in order to +

Returns the same as + install_release/1. + Descr defaults to "" if no relup file is found.

+

If option purge is specified, all old code that can + be soft-purged is purged after all other checks are + successfully completed. This can be useful to reduce the time needed by install_release.

+ marker="#install_release/1">install_release/1.

+ create_RELEASES(Root, RelDir, RelFile, AppDirs) -> ok | {error, Reason} - Create an initial RELEASES file. + Creates an initial RELEASES file. Root = RelDir = RelFile = string() AppDirs = [{App, Vsn, Dir}] @@ -202,52 +211,55 @@ old reboot_old permanent Reason = term() -

Creates an initial RELEASES file to be used by the release - handler. This file must exist in order to install new +

Creates an initial RELEASES file to be used by the + release handler. This file must exist to install new releases.

Root is the root of the installation ($ROOT) as - described above. RelDir is the the directory where - the RELEASES file should be created (normally + described earlier. RelDir is the directory where + the RELEASES file is to be created (normally $ROOT/releases). RelFile is the name of the .rel file that describes the initial release, including the extension .rel.

AppDirs can be used to specify from where the modules - for the specified applications should be loaded. App is + for the specified applications are to be loaded. App is the name of an application, Vsn is the version, and Dir is the name of the directory where App-Vsn - is located. The corresponding modules should be located under + is located. The corresponding modules are to be located under Dir/App-Vsn/ebin. The directories for applications not specified in AppDirs are assumed to be located in $ROOT/lib.

+ install_file(Vsn, File) -> ok | {error, Reason} - Install a release file in the release structure. + Installs a release file in the release structure. Vsn = File = string() Reason = term() -

Installs a release dependent file in the release structure. - A release dependent file is a file that must be in +

Installs a release-dependent file in the release structure. + The release-dependent file must be in the release structure when a new release is installed: - start.boot, relup and sys.config.

+ start.boot, relup, and sys.config.

The function can be called, for example, when these files - are generated at the target. It should be called after - set_unpacked/2 has been called.

+ are generated at the target. The function is to be called after + set_unpacked/2 + has been called.

+ install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason} install_release(Vsn, [Opt]) -> {ok, OtherVsn, Descr} | {continue_after_restart, OtherVsn, Descr} | {error, Reason} - Install a release in the system. + Installs a release in the system. Vsn = OtherVsn = string() Opt = {error_action, Action} | {code_change_timeout, Timeout}    | {suspend_timeout, Timeout} | {update_paths, Bool}  Action = restart | reboot -  Timeout = default | infinity | int()>0 +  Timeout = default | infinity | pos_integer()  Bool = boolean() Descr = term() Reason = {illegal_option, Opt} | {already_installed, Vsn} | {change_appl_data, term()} | {missing_base_app, OtherVsn, App} | {could_not_create_hybrid_boot, term()} | term() @@ -262,7 +274,7 @@ old reboot_old permanent version and a script {Vsn,Descr2,Instructions2} in this file for downgrading to Vsn.

If a script is found, the first thing that happens is that - the applications specifications are updated according to + the application specifications are updated according to the .app files and sys.config belonging to the release version Vsn.

After the application specifications have been updated, @@ -271,101 +283,120 @@ old reboot_old permanent OtherVsn and Descr are the version (UpFromVsn or Vsn) and description (Descr1 or Descr2) as specified in the script.

-

If {continue_after_restart,OtherVsn,Descr} is - returned, it means that the emulator will be restarted - before the upgrade instructions are executed. This will - happen if the emulator or any of the applications kernel, - stdlib or sasl are updated. The new version of the emulator - and these core applications will execute after the restart, - but for all other applications the old versions will be - started and the upgrade will be performed as normal by +

If {continue_after_restart,OtherVsn,Descr} is + returned, the emulator is restarted + before the upgrade instructions are executed. This + occurs if the emulator or any of the applications + Kernel, STDLIB, or SASL + are updated. The new emulator version + and these core applications execute after the restart. + For all other applications the old versions are + started and the upgrade is performed as normal by executing the upgrade instructions.

If a recoverable error occurs, the function returns {error,Reason} and the original application specifications are restored. If a non-recoverable error occurs, the system is restarted.

-

The option error_action defines if the node should be - restarted (init:restart()) or rebooted - (init:reboot()) in case of an error during - the installation. Default is restart.

-

The option code_change_timeout defines the timeout - for all calls to sys:change_code. If no value is - specified or default is given, the default value - defined in sys is used.

-

The option suspend_timeout defines the timeout for - all calls to sys:suspend. If no value is specified, - the values defined by the Timeout parameter of - the upgrade or suspend instructions are used. - If default is specified, the default value defined in - sys is used.

-

The option {update_paths,Bool} indicates if all - application code paths should be updated (Bool==true), - or if only code paths for modified applications should be - updated (Bool==false, default). This option only has - effect for other application directories than the default - $ROOT/lib/App-Vsn, that is, application directories - provided in the AppDirs argument in a call to - create_RELEASES/4 or set_unpacked/2.

-

Example: In the current version CurVsn of a release, - the application directory of myapp is - $ROOT/lib/myapp-1.0. A new version NewVsn is - unpacked outside the release handler, and the release handler - is informed about this with a call to:

- +

Options:

+ + error_action +

Defines if the node is to be + restarted + (init:restart()) + or rebooted + (init:reboot()) + if there is an error during + the installation. Default is restart.

+ code_change_timeout +

Defines the time-out + for all calls to + stdlib:sys:change_code. + If no value is specified or default is specified, the + default value defined in sys is used.

+ suspend_timeout +

Defines the time-out for + all calls to + stdlib:sys:suspend. + If no value is specified, the values defined by the Timeout + parameter of the upgrade or suspend instructions are used. + If default is specified, the default value defined in + sys is used.

+ {update_paths,Bool} +

Indicates if all + application code paths are to be updated (Bool==true) + or if only code paths for modified applications are to be + updated (Bool==false, default). This option has only + effect for other application directories than the default + $ROOT/lib/App-Vsn, that is, application directories + specified in argument AppDirs in a call to + create_RELEASES/4 or + set_unpacked/2.

+

Example:

+

In the current version CurVsn of a release, the + application directory of myapp is + $ROOT/lib/myapp-1.0. A new version NewVsn is + unpacked outside the release handler and the release + handler is informed about this with a call as follows:

+ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]). -=> {ok,NewVsn} - -

If NewVsn is installed with the option - {update_paths,true}, afterwards - code:lib_dir(myapp) will return - /home/user/myapp-1.0.

+=> {ok,NewVsn}
+

If NewVsn is installed with option + {update_paths,true}, then + kernel:code:lib_dir(myapp) + returns /home/user/myapp-1.0.

+ -

Installing a new release might be quite time consuming if +

Installing a new release can be time consuming if there are many processes in the system. The reason is that each process must be checked for references to old code - before a module can be purged. This check might lead to + before a module can be purged. This check can lead to garbage collections and copying of data.

-

If you wish to speed up the execution of - install_release, then you may call check_install_release - first, using the option purge. This will do the same - check for old code, and then purge all modules that can be - soft purged. The purged modules will then no longer have any - old code, and install_release will not need to do the +

To speed up the execution of + install_release, + first call check_install_release, + using option purge. This does the same + check for old code. Then purges all modules that can be + soft-purged. The purged modules do then no longer have any + old code, and + install_release + does not need to do the checks.

-

Obviously, this will not reduce the overall time for the - upgrade, but it will allow checks and purge to be executed +

This does not reduce the overall time for the + upgrade, but it allows checks and purge to be executed in the background before the real upgrade is started.

When upgrading the emulator from a version older than OTP - R15, there will be an attempt to load new application beam - code into the old emulator. In some cases, the new beam - format can not be read by the old emulator, and so the code - loading will fail and terminate the complete upgrade. To - overcome this problem, the new application code should be - compiled with the old emulator. See Design - Principles for more information about emulator - upgrade from pre OTP R15 versions.

+ R15, an attempt is made to load new application beam + code into the old emulator. Sometimes the new beam + format cannot be read by the old emulator, so the code + loading fails and the complete upgrade is terminated. To + overcome this problem, the new application code is to be + compiled with the old emulator. For more information about + emulator upgrade from pre OTP R15 versions, see + Design + Principles in System Documentation.

+ make_permanent(Vsn) -> ok | {error, Reason} - Make the specified release version permanent. + Makes the specified release version permanent. Vsn = string() Reason = {bad_status, Status} | term() -

Makes the specified version Vsn of the release +

Makes the specified release version Vsn permanent.

+ remove_release(Vsn) -> ok | {error, Reason} - Remove a release from the system. + Removes a release from the system. Vsn = string() Reason = {permanent, Vsn} | client_node | term() @@ -375,23 +406,26 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]). The release must not be the permanent release. Removes only the files and directories not in use by another release.

+
reboot_old_release(Vsn) -> ok | {error, Reason} - Reboot the system from an old release. + Reboots the system from an old release. Vsn = string() Reason = {bad_status, Status} | term()

Reboots the system by making the old release permanent, and - calls init:reboot() directly. The release must have - status old.

+ calls + init:reboot() + directly. The release must have status old.

+ set_removed(Vsn) -> ok | {error, Reason} - Mark a release as removed. + Marks a release as removed. Vsn = string() Reason = {permanent, Vsn} | term() @@ -403,9 +437,10 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]). not delete any files.

+ set_unpacked(RelFile, AppDirs) -> {ok, Vsn} | {error, Reason} - Mark a release as unpacked. + Marks a release as unpacked. RelFile = string() AppDirs = [{App, Vsn, Dir}] @@ -419,18 +454,19 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]). the release is unpacked. Vsn is extracted from the release resource file RelFile.

AppDirs can be used to specify from where the modules - for the specified applications should be loaded. App is + for the specified applications are to be loaded. App is the name of an application, Vsn is the version, and Dir is the name of the directory where App-Vsn - is located. The corresponding modules should be located under + is located. The corresponding modules are to be located under Dir/App-Vsn/ebin. The directories for applications not specified in AppDirs are assumed to be located in $ROOT/lib.

+ unpack_release(Name) -> {ok, Vsn} | {error, Reason} - Unpack a release package. + Unpacks a release package. Name = Vsn = string() Reason = client_node | term() @@ -438,14 +474,15 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).

Unpacks a release package Name.tar.gz located in the releases directory.

-

Performs some checks on the package - for example checks - that all mandatory files are present - and extracts its +

Performs some checks on the package, for example, checks + that all mandatory files are present, and extracts its contents.

+ which_releases() -> [{Name, Vsn, Apps, Status}] - Return all known releases + Returns all known releases. Name = Vsn = string() Apps = ["App-Vsn"] @@ -455,16 +492,18 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).

Returns all releases known to the release handler.

+ which_releases(Status) -> [{Name, Vsn, Apps, Status}] - Return all known releases of a specific status + Returns all known releases of a specific status. Name = Vsn = string() Apps = ["App-Vsn"] Status = unpacked | current | permanent | old -

Returns all releases known to the release handler of a specific status.

+

Returns all releases, known to the release handler, of a + specific status.

@@ -473,7 +512,8 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]). Application Upgrade/Downgrade

The following functions can be used to test upgrade and downgrade of single applications (instead of upgrading/downgrading an entire - release). A script corresponding to relup is created + release). A script corresponding to the instructions in the + relup file is created on-the-fly, based on the .appup file for the application, and evaluated exactly in the same way as release_handler does.

@@ -482,20 +522,22 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]). of .appup files. They are not run within the context of the release_handler process. They must therefore not be used together with calls to - install_release/1,2, as this will cause + install_release/1,2, + as this causes the release_handler to end up in an inconsistent state.

-

No persistent information is updated, why these functions can +

No persistent information is updated, so these functions can be used on any Erlang node, embedded or not. Also, using these - functions does not affect which code will be loaded in case of + functions does not affect which code is loaded if there is a reboot.

-

If the upgrade or downgrade fails, the application may end up +

If the upgrade or downgrade fails, the application can end up in an inconsistent state.

+ upgrade_app(App, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason} - Upgrade to a new application version + Upgrades to a new application version. App = atom() Dir = string() @@ -506,39 +548,46 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).

Upgrades an application App from the current version to a new version located in Dir according to - the .appup script.

+ the .appup file.

App is the name of the application, which must be started. Dir is the new library directory of - App, the corresponding modules as well as - the .app and .appup files should be located + App. The corresponding modules as well as + the .app and .appup files are to be located under Dir/ebin.

The function looks in the .appup file and tries to find an upgrade script from the current version of the application using - upgrade_script/2. + upgrade_script/2. This script is evaluated using - eval_appup_script/4, + eval_appup_script/4, exactly in the same way as - install_release/1,2 + install_release/1,2 does.

-

Returns {ok, Unpurged} if evaluating the script is - successful, where Unpurged is a list of unpurged - modules, or restart_emulator if this instruction is - encountered in the script, or {error, Reason} if - an error occurred when finding or evaluating the script.

+

Returns one of the following:

+ + {ok, Unpurged} if evaluating the script is + successful, where Unpurged is a list of unpurged + modules + restart_emulator if this instruction is + encountered in the script + {error, Reason} if an error occurred when + finding or evaluating the script +

If the restart_new_emulator instruction is found in - the script, upgrade_app/2 will return - {error,restart_new_emulator}. The reason for this is - that this instruction requires that a new version of the - emulator is started before the rest of the upgrade - instructions can be executed, and this can only be done by - install_release/1,2.

+ the script, + upgrade_app/2 + returns {error,restart_new_emulator}. This because + restart_new_emulator requires a new version of the + emulator to be started before the rest of the upgrade + instructions can be executed, and this can only be done by + install_release/1,2.

+ downgrade_app(App, Dir) -> downgrade_app(App, OldVsn, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason} - Downgrade to a previous application version + Downgrades to a previous application version. App = atom() Dir = OldVsn = string() @@ -549,110 +598,124 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).

Downgrades an application App from the current version to a previous version OldVsn located in - Dir according to the .appup script.

+ Dir according to the .appup file.

App is the name of the application, which must be - started. OldVsn is the previous version of - the application and can be omitted if Dir is of + started. OldVsn is the previous application version + and can be omitted if Dir is of the format "App-OldVsn". Dir is the library - directory of this previous version of App, - the corresponding modules as well as the old .app file - should be located under Dir/ebin. The .appup - file should be located in the ebin directory of + directory of the previous version of App. + The corresponding modules and the old .app file + are to be located under Dir/ebin. The .appup + file is to be located in the ebin directory of the current library directory of the application - (code:lib_dir(App)).

+ (code:lib_dir(App)).

The function looks in the .appup file and tries to - find an downgrade script to the previous version of + find a downgrade script to the previous version of the application using - downgrade_script/3. + downgrade_script/3. This script is evaluated using - eval_appup_script/4, + eval_appup_script/4, exactly in the same way as - install_release/1,2 + install_release/1,2 does.

-

Returns {ok, Unpurged} if evaluating the script is - successful, where Unpurged is a list of unpurged - modules, or restart_emulator if this instruction is - encountered in the script, or {error, Reason} if - an error occurred when finding or evaluating the script.

+

Returns one of the following:

+ + {ok, Unpurged} if evaluating the script is + successful, where Unpurged is a list of unpurged + modules + restart_emulator if this instruction is + encountered in the script + {error, Reason} if an error occurred when + finding or evaluating the script +
+ upgrade_script(App, Dir) -> {ok, NewVsn, Script} - Find an application upgrade script + Finds an application upgrade script. App = atom() Dir = string() NewVsn = string() - Script = Instructions -- see appup(4) + Script = Instructions

Tries to find an application upgrade script for App from the current version to a new version located in Dir.

The upgrade script can then be evaluated using - eval_appup_script/4. + eval_appup_script/4. It is recommended to use - upgrade_app/2 - instead, but this function is useful in order to inspect - the contents of the script.

+ upgrade_app/2 + instead, but this function (upgrade_script) is useful + to inspect the contents of the script.

App is the name of the application, which must be started. Dir is the new library directory of - App, the corresponding modules as well as - the .app and .appup files should be located + App. The corresponding modules as well as + the .app and .appup files are to be located under Dir/ebin.

The function looks in the .appup file and tries to - find an upgrade script from the current version of - the application. High-level instructions are translated to - low-level instructions and the instructions are sorted in - the same manner as when generating a relup script.

+ find an upgrade script from the current application version. + High-level instructions are translated to + low-level instructions. The instructions are sorted in + the same manner as when generating a relup file.

Returns {ok, NewVsn, Script} if successful, where - NewVsn is the new application version.

+ NewVsn is the new application version. + For details about Script, see + appup(4).

Failure: If a script cannot be found, the function fails with an appropriate error reason.

+ downgrade_script(App, OldVsn, Dir) -> {ok, Script} - Find an application downgrade script + Finds an application downgrade script. App = atom() OldVsn = Dir = string() - Script = Instructions -- see appup(4) + Script = Instructions

Tries to find an application downgrade script for App from the current version to a previous version OldVsn located in Dir.

The downgrade script can then be evaluated using - eval_appup_script/4. + eval_appup_script/4. It is recommended to use - downgrade_app/2,3 - instead, but this function is useful in order to inspect - the contents of the script.

+ downgrade_app/2,3 + instead, but this function (downgrade_script) is useful + to inspect the contents of the script.

App is the name of the application, which must be started. Dir is the previous library directory of - App, the corresponding modules as well as - the old .app file should be located under - Dir/ebin. The .appup file should be located in + App. The corresponding modules and + the old .app file are to be located under + Dir/ebin. The .appup file is to be located in the ebin directory of the current library - directory of the application (code:lib_dir(App)).

+ directory of the application + (code:lib_dir(App)).

The function looks in the .appup file and tries to - find an downgrade script from the current version of - the application. High-level instructions are translated to - low-level instructions and the instructions are sorted in - the same manner as when generating a relup script.

-

Returns {ok, Script} if successful.

+ find a downgrade script from the current application version. + High-level instructions are translated to + low-level instructions. The instructions are sorted in + the same manner as when generating a relup file.

+

Returns {ok, Script} if successful. + For details about Script, see + appup(4).

Failure: If a script cannot be found, the function fails with an appropriate error reason.

+ eval_appup_script(App, ToVsn, ToDir, Script) -> {ok, Unpurged} | restart_emulator | {error, Reason} - Evaluate an application upgrade or downgrade script + Evaluates an application upgrade or downgrade script. App = atom() ToVsn = ToDir = string() - Script -- see upgrade_script/2, downgrade_script/3 + Script + See upgrade_script/2, downgrade_script/3 Unpurged = [Module]  Module = atom() Reason = term() @@ -660,114 +723,100 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).

Evaluates an application upgrade or downgrade script Script, the result from calling - upgrade_script/2 or - downgrade_script/3, + upgrade_script/2 or + downgrade_script/3, exactly in the same way as - install_release/1,2 + install_release/1,2 does.

App is the name of the application, which must be started. ToVsn is the version to be upgraded/downgraded to, and ToDir is the library directory of this version. The corresponding modules as well as the .app and - .appup files should be located under Dir/ebin.

-

Returns {ok, Unpurged} if evaluating the script is - successful, where Unpurged is a list of unpurged - modules, or restart_emulator if this instruction is - encountered in the script, or {error, Reason} if - an error occurred when evaluating the script.

-

If the restart_new_emulator instruction is found in - the script, eval_appup_script/4 will return - {error,restart_new_emulator}. The reason for this is - that this instruction requires that a new version of the - emulator is started before the rest of the upgrade - instructions can be executed, and this can only be done by - install_release/1,2.

+ .appup files are to be located under Dir/ebin.

+

Returns one of the following:

+ + {ok, Unpurged} if evaluating the script is + successful, where Unpurged is a list of unpurged + modules + restart_emulator if this instruction is + encountered in the script + {error, Reason} if an error occurred when + finding or evaluating the script + +

If the restart_new_emulator instruction is found in + the script, + eval_appup_script/4 + returns {error,restart_new_emulator}. This because + restart_new_emulator requires a new version of the + emulator to be started before the rest of the upgrade + instructions can be executed, and this can only be done by + install_release/1,2.

Typical Error Reasons - - -

{bad_masters, Masters} - The master nodes - Masters are not alive.

-
- -

{bad_rel_file, File} - Specified .rel file - File can not be read, or does not contain a single - term.

-
- -

{bad_rel_data, Data} - Specified .rel file - does not contain a recognized release specification, but - another term Data.

-
- -

{bad_relup_file, File} - Specified relup file - Relup contains bad data.

-
- -

{cannot_extract_file, Name, Reason} - Problems when - extracting from a tar file, erl_tar:extract/2 returned - {error, {Name, Reason}}.

-
- -

{existing_release, Vsn} - Specified release version - Vsn is already in use.

-
- -

{Master, Reason, When} - Some operation, indicated by - the term When, failed on the master node Master - with the specified error reason Reason.

-
- -

{no_matching_relup, Vsn, CurrentVsn} - Cannot find a - script for up/downgrading between CurrentVsn and - Vsn.

-
- -

{no_such_directory, Path} - The directory Path - does not exist.

-
- -

{no_such_file, Path} - The path Path (file or - directory) does not exist.

-
- -

{no_such_file, {Master, Path}} - The path Path - (file or directory) does not exist at the master node - Master.

-
- -

{no_such_release, Vsn} - The specified version - Vsn of the release does not exist.

-
- -

{not_a_directory, Path} - Path exists, but is - not a directory.

-
- -

{Posix, File} - Some file operation failed for - File. Posix is an atom named from the Posix - error codes, such as enoent, eacces or - eisdir. See file(3).

-
- -

Posix - Some file operation failed, as above.

-
-
+ + {bad_masters, Masters} +

The master nodes Masters are not alive.

+ {bad_rel_file, File} +

Specified .rel file File cannot be read or + does not contain a single term.

+ {bad_rel_data, Data} +

Specified .rel file does not contain a recognized + release specification, but another term Data.

+ {bad_relup_file, File} +

Specified relup file Relup contains bad + data.

+ {cannot_extract_file, Name, Reason} +

Problems when extracting from a tar file, + erl_tar:extract/2 + returned {error, {Name, Reason}}.

+ {existing_release, Vsn} +

Specified release version Vsn is already + in use.

+ {Master, Reason, When} +

Some operation, indicated by the term When, failed + on the master node Master with the specified error + reason Reason.

+ {no_matching_relup, Vsn, CurrentVsn} +

Cannot find a script for upgrading/downgrading between + CurrentVsn and Vsn.

+ {no_such_directory, Path} +

The directory Pathdoes not exist.

+ {no_such_file, Path} +

The path Path (file or directory) does not + exist.

+ {no_such_file, {Master, Path}} +

The path Path (file or directory) does not exist at + the master node Master.

+ {no_such_release, Vsn} +

The specified release version Vsn does not + exist.

+ {not_a_directory, Path} +

Path exists but is not a directory.

+ {Posix, File} +

Some file operation failed for File. Posix + is an atom named from the Posix error codes, such as + enoent, eacces, or eisdir. See + file(3) + in Kernel.

+ Posix +

Some file operation failed, as for the previous item in + the list.

+
- SEE ALSO -

OTP Design Principles, - config(4), - relup(4), - rel(4), - script(4), - sys(3), - systools(3)

+ See Also +

OTP Design Principles, + config(4), + rel(4), + relup(4), + script(4), + sys(3), + systools(3)

diff --git a/lib/sasl/doc/src/relup.xml b/lib/sasl/doc/src/relup.xml index 8eecf3fce2..58918fc8e8 100644 --- a/lib/sasl/doc/src/relup.xml +++ b/lib/sasl/doc/src/relup.xml @@ -36,59 +36,53 @@

The release upgrade file describes how a release is upgraded in a running system.

This file is automatically generated by - systools:make_relup/3,4, using a release resource file - (.rel), application resource files (.app) and + systools:make_relup/3,4, + using a release resource file + (.rel), application resource files (.app), and application upgrade files (.appup) as input.

- FILE SYNTAX -

In a target system, the release upgrade file should be located in - the OTP_ROOT/erts-EVsn/Vsn directory.

+ File Syntax +

In a target system, the release upgrade file is to be located in + directory $ROOT/releases/Vsn.

The relup file contains one single Erlang term, which defines the instructions used to upgrade the release. The file has the following syntax:

{Vsn, [{UpFromVsn, Descr, Instructions}, ...], - [{DownToVsn, Descr, Instructions}, ...]}. - - - -

Vsn = string() is the current version of the release.

-
- -

UpFromVsn = string() is an earlier version of the release - to upgrade from.

-
- -

Descr = term() is a user defined parameter passed - from the systools:make_relup/3,4 function. It will - be used in the return value of - release_handler:install_release/1,2.

-
- -

Instructions is a list of low-level release upgrade - instructions, see appup(4).

-

It consists of the release upgrade instructions from + [{DownToVsn, Descr, Instructions}, ...]}. + + Vsn = string() +

Current release version.

+ UpFromVsn = string() +

Earlier version of the release to upgrade from.

+ Descr = term() +

A user-defined parameter passed + from the function + systools:make_relup/3,4. + It is used in the return value of + release_handler:install_release/1,2.

+ Instructions +

A list of low-level release upgrade instructions, see + appup(4). + It consists of the release upgrade instructions from the respective application upgrade files (high-level instructions are translated to low-level instructions), in the same order - as in the start script.

-
- -

DownToVsn = string() is an earlier version of the release - to downgrade to.

-
- -

When upgrading from UpFromVsn with - release_handler:install_release/1,2, there does not have to be - an exact match of versions, but UpFromVsn can be a sub-string - of the current release version.

+ as in the start script.

+ DownToVsn = string() +

Earlier version of the release to downgrade to.

+
- SEE ALSO -

app(4), appup(4), rel(4), release_handler(3), systools(3)

+ See Also +

app(4), + appup(4), + rel(4), + release_handler(3), + systools(3)

diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml index fe38e69ce3..8d79251c7e 100644 --- a/lib/sasl/doc/src/sasl_app.xml +++ b/lib/sasl/doc/src/sasl_app.xml @@ -27,12 +27,11 @@ - - sasl - The SASL Application - -

This section describes the SASL (System Architecture Support Libraries) - application which provides the following services:

+ + sasl + The SASL application + +

The SASL application provides the following services:

alarm_handler overload @@ -40,138 +39,147 @@ release_handler systools -

The SASL application also includes error_logger event - handlers for formatting SASL error and crash reports.

- +

The SASL application also includes error_logger event + handlers for formatting SASL error and crash reports.

-

The SASL application in OTP has nothing to do with +

The SASL application in OTP has nothing to do with "Simple Authentication and Security Layer" (RFC 4422).

-
Error Logger Event Handlers

The following error logger event handlers are used by - the SASL application.

+ the SASL application.

sasl_report_tty_h -

Formats and writes supervisor reports, crash reports and progress reports to stdio. - This error logger event handler will use +

Formats and writes supervisor reports, crash + reports, and progress reports to stdio. + This error logger event handler uses error_logger_format_depth - in the Kernel application to limit how much detail are printed to - for crash and supervisor reports.

+ in the Kernel application to limit how much detail is + printed in crash and supervisor reports.

sasl_report_file_h -

Formats and writes supervisor reports, crash report and progress report to a single file. - This error logger event handler will use +

Formats and writes supervisor reports, crash + report, and progress report to a single file. + This error logger event handler uses error_logger_format_depth - in the Kernel application to limit how much detail are printed to - for crash and supervisor reports.

+ in the Kernel application to limit the details + printed in crash and supervisor reports.

log_mf_h -

This error logger writes all events sent to - the error logger to disk.

-

To activate this event handler, the following three sasl - configuration parameters must be set: - error_logger_mf_dir, error_logger_mf_maxbytes - and error_logger_mf_maxfiles. See below for more - information about the configuration parameters.

+

This error logger writes all events sent to the + error logger to disk. Multiple files and log rotation are + used. For efficiency reasons, each event is written as a + binary. For more information about this handler, + see the STDLIB Reference + Manual.

+

To activate this event handler, three SASL + configuration parameters must be set, + error_logger_mf_dir, error_logger_mf_maxbytes, + and error_logger_mf_maxfiles. The next section provides + more information about the configuration parameters.

Configuration -

The following configuration parameters are defined for the SASL - application. See app(4) for more information about - configuration parameters:

+

The following configuration parameters are defined for the SASL + application. For more information about configuration parameters, see + app(4) in Kernel.

+

All configuration parameters are optional.

- ]]> + -

Value is one of:

+

Value is one of the following:

tty - Installs sasl_report_tty_h in the error logger. - This is the default option. +

Installs sasl_report_tty_h in the error logger. + This is the default option.

{file,FileName} - Installs sasl_report_file_h in the error logger. - This makes all reports go to the file FileName. - FileName is a string. +

Installs sasl_report_file_h in the error logger. + All reports go to file FileName, which is a + string.

{file,FileName,Modes} - Same as {file,FileName} except that the Modes - allows to specify the modes used for opening the FileName - given to the file:open/2 - call. When not specified, the Modes defaults to [write]. - Use [append] for having the FileName open in append mode. - FileName is a string. +

Same as {file,FileName}, except that Modes + allows you to specify the modes used for opening the FileName + given to the file:open/2 + call. When not specified, Modes defaults to [write]. + Use [append] to have the FileName open in append mode. + FileName is a string.

false - -

No SASL error logger handler is installed.

-
+

No SASL error logger handler is installed.

- ]]> +

Restricts the error logging performed by the specified - sasl_error_logger to error reports, progress reports, + sasl_error_logger to error reports or progress reports, or both. Default is all.

- ]]> + -

Specifies in which directory the files are stored. If this - parameter is undefined or false, +

Specifies in which directory log_mf_h is to store + its files. If this parameter is undefined or false, the log_mf_h handler is not installed.

- ]]> + -

Specifies how large each individual file can be. If this - parameter is undefined, the log_mf_h handler is not - installed.

+

Specifies the maximum size of each individual file written + by log_mf_h. If this parameter is undefined, + the log_mf_h handler is not installed.

- ]]> + -

Specifies how many files are used. If this parameter is - undefined, the log_mf_h handler is not installed.

+

Specifies the number of files used by log_mf_h. If + this parameter is undefined, the log_mf_h handler is + not installed.

- 0 ]]> + 0 ]]> -

Specifies the maximum intensity for overload. Default +

Specifies the maximum intensity + for overload. Default is 0.8.

- 0 ]]> + 0 ]]> -

Specifies the overload weight. Default is 0.1.

+

Specifies the overload + weight. Default is 0.1.

- ]]> + -

Specifies which program should be used when restarting - the system. Default is $OTP_ROOT/bin/start.

+

Specifies the program to be used when restarting the system + during release installation. Default is + $OTP_ROOT/bin/start.

- ]]> + -

Specifies which nodes this node uses to read/write release - information. This parameter is ignored if - the client_directory parameter is not set.

+

Specifies the nodes used by this node to read/write release + information. This parameter is ignored if parameter + client_directory is not set.

- ]]> +

This parameter specifies the client directory at the master - nodes. Refer to Release Handling in OTP Design Principles for more information. This parameter is - ignored if the masters parameter is not set.

+ nodes. For details, see + Release Handling + in OTP Design Principles. This parameter is + ignored if parameter masters is not set.

- ]]> +

Indicates if the Erlang emulator is statically installed. A node with a static emulator cannot switch dynamically to a - new emulator as the executable files are written into memory - statically. This parameter is ignored if the masters - and client_directory parameters are not set.

+ new emulator, as the executable files are written into memory + statically. This parameter is ignored if parameters masters + and client_directory are not set.

- ]]> +

Indicates where the releases directory is located. The release handler writes all its files to this directory. @@ -179,7 +187,7 @@ RELDIR is used. By default, this is $OTP_ROOT/releases.

- ]]> +

If set to true, all dates in textual log outputs are displayed in Universal Coordinated Time with the string @@ -190,13 +198,13 @@

See Also -

alarm_handler(3), - error_logger(3), - log_mf_h(3), - overload(3), - rb(3), - release_handler(3), - systools(3)

+

alarm_handler(3), + error_logger(3), + log_mf_h(3), + overload(3), + rb(3), + release_handler(3), + systools(3)

diff --git a/lib/sasl/doc/src/sasl_intro.xml b/lib/sasl/doc/src/sasl_intro.xml index 2dc3efebc1..bbc9457103 100644 --- a/lib/sasl/doc/src/sasl_intro.xml +++ b/lib/sasl/doc/src/sasl_intro.xml @@ -31,22 +31,32 @@
- About This Document -

The SASL (System Architecture Support Libraries) - application provides support for:

+ Scope +

The SASL application provides support for:

- error logging - alarm handling - overload regulation - release handling - report browsing. + Error logging + Alarm handling + Overload regulation + Release handling + Report browsing -

In this document, "SASL Error Logging" describes the error - handler which produces the supervisor, progress, and crash - reports which can be written to screen, or to a specified file. - It also describes the report browser rb.

-

The chapters about release structure and release handling have - been moved to OTP Design Principles.

+

Section + SASL Error Logging + describes the error + handler that produces the supervisor, progress, and crash + reports, which can be written to screen or to a specified file. + It also describes the Report Browser (RB).

+

The sections about release structure and release handling have + been moved to section + OTP Design Principles + in System Documentation.

+ +
+ Prerequisites +

It is assumed that the reader is familiar with the Erlang + programming language.

+
+ diff --git a/lib/sasl/doc/src/script.xml b/lib/sasl/doc/src/script.xml index 838efe69bb..db3ea0f487 100644 --- a/lib/sasl/doc/src/script.xml +++ b/lib/sasl/doc/src/script.xml @@ -37,25 +37,21 @@ script Boot script -

The boot script describes how the Erlang runtime system is - started. It contains instructions on which code to load and - which processes and applications to start. -

-

The command erl -boot Name starts the system with a boot +

The boot script describes how the Erlang runtime system + is started. It contains instructions on which code to load and + which processes and applications to start.

+

Command erl -boot Name starts the system with a boot file called Name.boot, which is generated from the - Name.script file, using systools:script2boot/1. -

+ Name.script file, using + systools:script2boot/1.

The .script file is generated by systools from a - .rel file and .app files. -

+ .rel file and from .app files.

- FILE SYNTAX -

The boot script is stored in a file with the extension - .script

-

The file has the following syntax: -

+ File Syntax +

The boot script is stored in a file with extension + .script. The file has the following syntax:

{script, {Name, Vsn}, [ @@ -70,100 +66,97 @@ ... {apply, {Mod, Func, Args}}, ... - {progress, started}]}. - - Name = string() defines the name of the system. - - Vsn = string() defines the version of the system. - - {progress, Term} sets the "progress" of the - initialization program. The function init:get_status() - returns the current value of the progress, which is - {InternalStatus,Term}. - - -

{path, [Dir]} where Dir is a string. This + {progress, started}]}. + + Name = string() +

Defines the system name.

+ Vsn = string() +

Defines the system version.

+ {progress, Term} +

Sets the "progress" of the initialization + program. The + init:get_status/0 + function returns the current value of the progress, which is + {InternalStatus,Term}.

+ {path, [Dir]} +

Dir is a string. This argument sets the load path of the system to [Dir]. The load path used to load modules is obtained from the initial load path, which is given in the script file, together with - any path flags which were supplied in the command line - arguments. The command line arguments modify the path as + any path flags that were supplied in the command-line + arguments. The command-line arguments modify the path as follows:

-pa Dir1 Dir2 ... DirN adds the directories Dir1, Dir2, ..., DirN to the front of the initial - load path. - + load path.
-pz Dir1 Dir2 ... DirN adds the directories Dir1, Dir2, ..., DirN to the end of the initial - load path. - + load path.

-path Dir1 Dir2 ... DirN defines a set of - directories Dir1, Dir2, ..., DirN which replaces + directories Dir1, Dir2, ..., DirN, which replace the search path given in the script file. Directory names in the path are interpreted as follows:

Directory names starting with / are assumed - to be absolute path names. - + to be absolute path names.
Directory names not starting with / are - assumed to be relative the current working directory. - + assumed to be relative the current working directory. The special $ROOT variable can only be used - in the script, not as a command line argument. The + in the script, not as a command-line argument. The given directory is relative the Erlang installation - directory. - + directory.
- - {primLoad, [Mod]} loads the modules [Mod] - from the directories specified in Path. The script - interpreter fetches the appropriate module by calling the - function erl_prim_loader:get_file(Mod). A fatal error - which terminates the system will occur if the module cannot be - located. - - {kernel_load_completed} indicates that all modules - which must be loaded before any processes - are started are loaded. In interactive mode, all - {primLoad,[Mod]} commands interpreted after this - command are ignored, and these modules are loaded on demand. - In embedded mode, kernel_load_completed is ignored, and - all modules are loaded during system start. - - {kernelProcess, Name, {Mod, Func, Args}} starts a - "kernel process". The kernel process Name is started - by evaluating apply(Mod, Func, Args) which is expected - to return {ok, Pid} or ignore. The init - process monitors the behaviour of Pid and terminates - the system if Pid dies. Kernel processes are key - components of the runtime system. Users do not normally add - new kernel processes. - - {apply, {Mod, Func, Args}}. The init process simply - evaluates apply(Mod, Func, Args). The system - terminates if this results in an error. The boot procedure - hangs if this function never returns. - - + + {primLoad, [Mod]} +

Loads the modules [Mod] + from the directories specified in Path. The script + interpreter fetches the appropriate module by calling + + erl_prim_loader:get_file(Mod). A fatal error + that terminates the system occurs if the module cannot be + located.

+ {kernel_load_completed} +

Indicates that all modules + that must be loaded before any processes + are started are loaded. In interactive mode, all + {primLoad,[Mod]} commands interpreted after this + command are ignored, and these modules are loaded on demand. + In embedded mode, kernel_load_completed is ignored, and + all modules are loaded during system start.

+ {kernelProcess, Name, {Mod, Func, Args}} +

Starts the + "kernel process" Name + by evaluating apply(Mod, Func, Args). The start function is + to return {ok, Pid} or ignore. The init + process monitors the behavior of Pid and terminates + the system if Pid dies. Kernel processes are key + components of the runtime system. Users do not normally add + new kernel processes.

+ {apply, {Mod, Func, Args}}. +

The init process + evaluates apply(Mod, Func, Args). The system + terminates if this results in an error. The boot procedure + hangs if this function never returns.

+ -

In the interactive system the code loader provides - demand driven code loading, but in the embedded system - the code loader loads all the code immediately. The same - version of code is used in both cases. The code server - calls init:get_argument(mode) to find out if it should - run in demand mode, or non-demand driven mode. -

+

In an interactive system, the code loader provides + demand-driven code loading, but in an embedded system + the code loader loads all code immediately. The same + version of code + is used in both cases. The code server calls + init:get_argument(mode) + to determine if it is to run in demand mode or non-demand + driven mode.

- SEE ALSO -

systools(3) -

+ See Also +

systools(3)

diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml index 11d99fa595..1a5119a5cf 100644 --- a/lib/sasl/doc/src/systools.xml +++ b/lib/sasl/doc/src/systools.xml @@ -31,17 +31,18 @@ systools - A Set of Release Handling Tools. + A Set of Release Handling Tools

This module contains functions to generate boot scripts - (.boot, .script), release upgrade scripts + (.boot, .script), a release upgrade file (relup), and release packages.

+ make_relup(Name, UpFrom, DownTo) -> Result make_relup(Name, UpFrom, DownTo, [Opt]) -> Result - Generate a release upgrade file relup. + Generates a release upgrade file relup. Name = string() UpFrom = DownTo = [Name | {Name,Descr}] @@ -50,93 +51,94 @@ | warnings_as_errors  Dir = string() Result = ok | error | {ok,Relup,Module,Warnings} | {error,Module,Error} -  Relup - see relup(4) +  Relup, see relup(4)  Module = atom()  Warnings = Error = term() -

Generates a release upgrade file relup containing a - script which describes how to upgrade the system from a number - of previous releases, and how to downgrade to a number of - previous releases. The script is used by - release_handler when installing a new version of a - release in run-time.

-

By default, relup is placed in the current working - directory. If the option {outdir,Dir} is provided, - relup is placed in Dir instead.

+

Generates a release upgrade file relup containing instructions + for upgrading from or downgrading to one or more previous releases. + The instructions are used by + release_handler + when installing a new version of a release in runtime.

+

By default, relup file is located in the current working + directory. If option {outdir,Dir} is specified, + the relup file is located in Dir instead.

The release resource file Name.rel is compared with - all release resource files Name2.rel specified in - UpFrom and DownTo. For each such pair, it is - deducted:

+ all release resource files Name2.rel, specified in + UpFrom and DownTo. For each such pair, the + following is deducted:

-

Which applications should be deleted, that is - applications which are listed in Name.rel but not - in Name2.rel.

+

Which applications to be deleted, that is, + applications listed in Name.rel but not + in Name2.rel

-

Which applications should be added, that is applications - which are listed in Name2.rel but not in - Name.rel.

+

Which applications to be added, that is, applications + listed in Name2.rel but not in Name.rel

-

Which applications should be upgraded/downgraded, that - is applications listed in both Name.rel and - Name2.rel, but with different versions.

+

Which applications to be upgraded/downgraded, that + is, applications listed in both Name.rel and + Name2.rel but with different versions

If the emulator needs to be restarted after upgrading or - downgrading, that is if the ERTS version differs between - Name.rel and Name2.rel.

+ downgrading, that is, if the ERTS version differs + between Name.rel and Name2.rel

-

Instructions for this are added to the relup script in +

Instructions for this are added to the relup file in the above order. Instructions for upgrading or downgrading between application versions are fetched from the relevant application upgrade files App.appup, sorted in the same order as when generating a boot script, see - make_script/1,2. High-level instructions are translated - into low-level instructions and the result is printed to - relup.

-

The optional Descr parameter is included as-is in - the relup script, see relup(4). Defaults to + make_script/1,2. + High-level instructions are translated + into low-level instructions and the result is printed to the + relup file.

+

The optional Descr parameter is included "as is" in + the relup file, see + relup(4). Defaults to the empty list.

All the files are searched for in the code path. It is - assumed that the .app and .appup file for an - application is located in the same directory.

-

If the option {path,[Dir]} is provided, this path is - appended to the current path. The wildcard * is - expanded to all matching directories. - Example: lib/*/ebin.

-

If the restart_emulator option is supplied, a + assumed that the .app and .appup files for an + application are located in the same directory.

+

If option {path,[Dir]} is specified, this path is + appended to the current path. Wildcard * is + expanded to all matching directories, for example, + lib/*/ebin.

+

If option restart_emulator is specified, a low-level instruction to restart the emulator is appended to - the relup scripts. This ensures that a complete reboot of + the relup file. This ensures that a complete reboot of the system is done when the system is upgraded or downgraded.

-

If an upgrade includes a change from an emulator earlier - than OTP R15 to OTP R15 or later, the warning - pre_R15_emulator_upgrade is issued. See Design - Principles for more information about this.

+

If an upgrade includes a change from an emulator earlier + than OTP R15 to OTP R15 or later, the warning + pre_R15_emulator_upgrade is issued. For more information + about this, see + Design + Principles in System Documentation.

By default, errors and warnings are printed to tty and - the function returns ok or error. If the option - silent is provided, the function instead returns - {ok,Relup,Module,Warnings} where Relup is - the release upgrade script, or it returns - {error,Module,Error}. Warnings and errors can be - converted to strings by calling + the function returns ok or error. If option + silent is specified, the function instead either returns + {ok,Relup,Module,Warnings}, where Relup is + the release upgrade file, or {error,Module,Error}. + Warnings and errors can be converted to strings by calling Module:format_warning(Warnings) or Module:format_error(Error).

-

If the option noexec is provided, the function returns +

If option noexec is specified, the function returns the same values as for silent but no relup file is created.

-

If the option warnings_as_errors is provided, warnings - are treated as errors.

+

If option warnings_as_errors is specified, warnings + are treated as errors.

+ make_script(Name) -> Result make_script(Name, [Opt]) -> Result - Generate a boot script .script/.boot. + Generates a boot script .script/.boot. Name = string() Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | @@ -153,114 +155,117 @@

Generates a boot script Name.script and its binary version, the boot file Name.boot. The boot file - specifies which code should be loaded and which applications - should be started when the Erlang runtime system is started. - See script(4).

-

The release resource file Name.rel is read to find - out which applications are included in the release. Then - the relevant application resource files App.app are - read to find out which modules should be loaded and if and - how the application should be started. (Keys modules - and mod, see app(4)).

-

By default, the boot script and boot file are placed in + specifies which code to be loaded and which applications + to be started when the Erlang runtime system is started. + See script(4).

+

The release resource file Name.rel is read to determine + which applications are included in the release. Then + the relevant application resource files App.app are read + to determine which modules to be loaded, and if and + how the applications are to be started. (Keys modules + and mod, see + app(4).

+

By default, the boot script and boot file are located in the same directory as Name.rel. That is, in the current working directory unless Name contains a path. If - the option {outdir,Dir} is provided, they are placed + option {outdir,Dir} is specified, they are located in Dir instead.

-

The correctness of each application is checked:

+

The correctness of each application is checked as follows:

The version of an application specified in - the .rel file should be the same as the version + the .rel file is to be the same as the version specified in the .app file.

-

There should be no undefined applications, that is, - dependencies to applications which are not included in - the release. (Key applications in .app +

There are to be no undefined applications, that is, + dependencies to applications that are not included in + the release. (Key applications in the .app file).

-

There should be no circular dependencies among +

There are to be no circular dependencies among the applications.

-

There should be no duplicated modules, that is, modules with +

There are to be no duplicated modules, that is, modules with the same name but belonging to different applications.

-

If the src_tests option is specified, a +

If option src_tests is specified, a warning is issued if the source code for a module is - missing or newer than the object code.

+ missing or is newer than the object code.

The applications are sorted according to the dependencies between the applications. Where there are no dependencies, the order in the .rel file is kept.

-

The function will fail if the mandatory - applications kernel and stdlib are not - included in the .rel file and have start - type permanent (default).

-

If sasl is not included as an application in - the .rel file, a warning is emitted because such a - release can not be used in an upgrade. To turn off this - warning, add the option no_warn_sasl.

+

The function fails if the mandatory + applications Kernel and STDLIB are not + included in the .rel file and have start + type permanent (which is default).

+

If SASL is not included as an application in + the .rel file, a warning is issued because such a + release cannot be used in an upgrade. To turn off this + warning, add option no_warn_sasl.

All files are searched for in the current path. It is assumed that the .app and .beam files for an - application is located in the same directory. The .erl + application are located in the same directory. The .erl files are also assumed to be located in this directory, unless - it is an ebin directory in which case they may be + it is an ebin directory in which case they can be located in the corresponding src directory.

-

If the option {path,[Dir]} is provided, this path is +

If option {path,[Dir]} is specified, this path is appended to the current path. A directory in the path can be - given with a wildcard *, this is expanded to all + specified with a wildcard *, this is expanded to all matching directories. Example: "lib/*/ebin".

In the generated boot script all application directories are - structured as App-Vsn/ebin and assumed to be located + structured as App-Vsn/ebin. They are assumed to be located in $ROOT/lib, where $ROOT is the root directory - of the installed release. If the local option is - supplied, the actual directories where the applications were + of the installed release. If option local is + specified, the actual directories where the applications were found are used instead. This is a useful way to test a generated boot script locally.

-

The variables option can be used to specify an +

Option variables can be used to specify an installation directory other than $ROOT/lib for some of the applications. If a variable {VarName,Prefix} is specified and an application is found in a directory - Prefix/Rest/App[-Vsn]/ebin, this application will get + Prefix/Rest/App[-Vsn]/ebin, this application gets the path VarName/Rest/App-Vsn/ebin in the boot script. If an application is found in a directory Prefix/Rest, - the path will be VarName/Rest/App-Vsn/ebin. When + the path is VarName/Rest/App-Vsn/ebin. When starting Erlang, all variables VarName are given - values using the boot_var command line flag.

-

Example: If the option {variables,[{"TEST","lib"}]} is - supplied, and myapp.app is found in - lib/myapp/ebin, then the path to this application in - the boot script will be "$TEST/myapp-1/ebin". If - myapp.app is found in lib/test, then the path - will be $TEST/test/myapp-1/ebin.

+ values using command-line flag boot_var.

+

Example: If option {variables,[{"TEST","lib"}]} + is specified and myapp.app is found in + lib/myapp/ebin, the path to this application in + the boot script is "$TEST/myapp-1/ebin". If + myapp.app is found in lib/test, the path + is $TEST/test/myapp-1/ebin.

The checks performed before the boot script is generated can be extended with some cross reference checks by specifying - the exref option. These checks are performed with + option exref. These checks are performed with the Xref tool. All applications, or the applications specified with {exref,[App]}, are checked by Xref and - warnings are generated for calls to undefined functions.

+ warnings are issued for calls to undefined functions.

By default, errors and warnings are printed to tty and - the function returns ok or error. If the option - silent is provided, the function instead returns + the function returns ok or error. If option + silent is specified, the function instead returns {ok,Module,Warnings} or {error,Module,Error}. Warnings and errors can be converted to strings by calling Module:format_warning(Warnings) or Module:format_error(Error).

-

If the option warnings_as_errors is provided, warnings - are treated as errors.

-

If the option no_dot_erlang is provided, the instruction to - load the .erlang file during boot is NOT included.

+

If option warnings_as_errors is specified, warnings + are treated as errors.

+

If option no_dot_erlang is specified, the instruction to + load the .erlang file during boot is not + included.

+ make_tar(Name) -> Result make_tar(Name, [Opt]) -> Result - Create a release package. + Creates a release package. Name = string() Opt = {dirs,[IncDir]} | {path,[Dir]} | {variables,[Var]} | {var_tar,VarTar} | {erts,Dir} | src_tests | exref | {exref,[App]} | silent | {outdir,Dir} @@ -276,90 +281,91 @@  Warning = Error = term() -

Creates a release package file Name.tar.gz. file. +

Creates a release package file Name.tar.gz. This file must be uncompressed and unpacked on the target - system using the release_handler, before the new - release can be installed.

-

The release resource file Name.rel is read to find out + system using + release_handler + before the new release can be installed.

+

The release resource file Name.rel is read to determine which applications are included in the release. Then the relevant application resource files App.app are - read to find out the version and modules of each application. - (Keys vsn and modules, see app(4)).

-

By default, the release package file is placed in the same + read to determine the version and modules of each application + (keys vsn and modules, see + app(4)).

+

By default, the release package file is located in the same directory as Name.rel. That is, in the current working - directory unless Name contains a path. If the option - {outdir,Dir} is provided, it is placed in Dir + directory unless Name contains a path. If option + {outdir,Dir} is specified, it is located in Dir instead.

By default, the release package contains the directories lib/App-Vsn/ebin and lib/App-Vsn/priv for each - included application. If more directories, the option - dirs is supplied. Example: + included application. If more directories are to be included, + option dirs is specified, for example, {dirs,[src,examples]}.

All these files are searched for in the current path. If - the option {path,[Dir]} is provided, this path is - appended to the current path. The wildcard * is + option {path,[Dir]} is specified, this path is + appended to the current path. Wildcard * is expanded to all matching directories. Example: "lib/*/ebin".

-

The variables option can be used to specify an +

Option variables can be used to specify an installation directory other than lib for some of - the applications. If a variable {VarName,Prefix} is - specified and an application is found in a directory - Prefix/Rest/App[-Vsn]/ebin, this application will be + the applications. If variable {VarName,Prefix} is + specified and an application is found in directory + Prefix/Rest/App[-Vsn]/ebin, this application is packed into a separate VarName.tar.gz file as Rest/App-Vsn/ebin.

-

Example: If the option {variables,[{"TEST","lib"}]} is - supplied, and myapp.app is found in - lib/myapp-1/ebin, the the application myapp is +

Example: If option {variables,[{"TEST","lib"}]} + is specified and myapp.app is located in + lib/myapp-1/ebin, application myapp is included in TEST.tar.gz:

 % tar tf TEST.tar
 myapp-1/ebin/myapp.app
-...
-        
-

The {var_tar,VarTar} option can be used to specify if - and where a separate package should be stored. In this option, - VarTar is:

- - -

include. Each separate (variable) package is - included in the main ReleaseName.tar.gz file. This - is the default.

-
- -

ownfile. Each separate (variable) package is - generated as separate files in the same directory as - the ReleaseName.tar.gz file.

-
- -

omit. No separate (variable) packages are - generated and applications which are found underneath a - variable directory are ignored.

-
-
-

A directory called releases is also included in +... +

Option {var_tar,VarTar} can be used to specify if + and where a separate package is to be stored. In this option + VarTar is one of the following:

+ + include +

Each separate (variable) package is included in the + main ReleaseName.tar.gz file. This is the + default.

+ ownfile +

Each separate (variable) package is + generated as a separate file in the same directory as + the ReleaseName.tar.gz file.

+ omit +

No separate (variable) packages are + generated. Applications that are found underneath a + variable directory are ignored.

+
+

A directory releases is also included in the release package, containing Name.rel and a - subdirectory called RelVsn. RelVsn is + subdirectory RelVsn. RelVsn is the release version as specified in Name.rel.

releases/RelVsn contains the boot script Name.boot renamed to start.boot and, if found, the files relup and sys.config. These files are searched for in the same directory as Name.rel, in the current working directory, and in any directories - specified using the path option.

-

If the release package should contain a new Erlang runtime + specified using option path.

+

If the release package is to contain a new Erlang runtime system, the bin directory of the specified runtime system {erts,Dir} is copied to erts-ErtsVsn/bin.

-

All checks performed with the make_script function - are performed before the release package is created. The - src_tests and exref options are also +

All checks with function + make_script + are performed before the release package is created. + Options src_tests and exref are also valid here.

The return value and the handling of errors and warnings - are the same as described for make_script above.

+ are the same as described for + make_script.

+ script2boot(File) -> ok | error - Generate a binary version of a boot script. + Generates a binary version of a boot script. File = string() @@ -367,17 +373,24 @@ myapp-1/ebin/myapp.app

The Erlang runtime system requires that the contents of the script used to boot the system is a binary Erlang term. This function transforms the File.script boot script - to a binary term which is stored in the file File.boot.

-

A boot script generated using the make_script - function is already transformed to the binary form.

+ to a binary term, which is stored in the File.boot + file.

+

A boot script generated using + make_script + is already transformed to the binary form.

- SEE ALSO -

app(4), appup(4), erl(1), rel(4), release_handler(3), relup(4), - script(4)

+ See Also +

app(4), + appup(4), + erl(1), + rel(4), + release_handler(3), + relup(4), + script(4)

-- cgit v1.2.3 From 6d2bac38720ec27763a0cea2ae48060d501fce62 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 24 Nov 2015 00:11:45 +0100 Subject: Let missing suites affect ct:run_test/1 return and ct_run exit status --- lib/common_test/doc/src/run_test_chapter.xml | 16 ++++++++-------- lib/common_test/src/ct_run.erl | 18 ++++++++++++++---- 2 files changed, 22 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index d80453fc98..082a587c8d 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -60,15 +60,15 @@

If compilation should fail for one or more suites, the compilation errors are printed to tty and the operator is asked if the test run should proceed without the missing suites, or be aborted. If the operator chooses to proceed, - it is noted in the HTML log which tests have missing suites. If Common Test is - unable to prompt the user after compilation failure (if Common Test doesn't - control stdin), the test run will proceed automatically without the missing - suites. This behaviour can however be modified with the - flag , + it is noted in the HTML log which tests have missing suites. Also, for each failed + compilation, the failed tests counter in the return value of + is incremented. If Common Test is unable to prompt + the user after compilation failure (if Common Test doesn't control stdin), the test + run will proceed automatically without the missing suites. In order to always + abort the test run (without operator interaction) if one or more suites fail + to compile, the flag , or the option - . If - is set (to true), the test run - will stop immediately if some suites fail to compile.

+ should be set.

Any help module (i.e. regular Erlang module with name not ending with "_SUITE") that resides in the same test object directory as a suite diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 97994d8d6f..0b646ffd07 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -1771,7 +1771,18 @@ compile_and_run(Tests, Skip, Opts, Args) -> {Tests1,Skip1} -> ReleaseSh = proplists:get_value(release_shell, Args), ct_util:set_testdata({release_shell,ReleaseSh}), - possibly_spawn(ReleaseSh == true, Tests1, Skip1, Opts) + TestResult = + possibly_spawn(ReleaseSh == true, Tests1, Skip1, Opts), + case TestResult of + {Ok,Errors,Skipped} -> + NoOfMakeErrors = + lists:foldl(fun({_,BadMods}, X) -> + X + length(BadMods) + end, 0, SuiteMakeErrors), + {Ok,Errors+NoOfMakeErrors,Skipped}; + ErrorResult -> + ErrorResult + end catch _:BadFormat -> {error,BadFormat} @@ -2071,10 +2082,10 @@ final_skip([Skip|Skips], Final) -> final_skip([], Final) -> lists:reverse(Final). -continue(_MakeErrors, true) -> - false; continue([], _) -> true; +continue(_MakeErrors, true) -> + false; continue(_MakeErrors, _AbortIfMissingSuites) -> io:nl(), OldGl = group_leader(), @@ -2107,7 +2118,6 @@ continue(_MakeErrors, _AbortIfMissingSuites) -> end. set_group_leader_same_as_shell() -> - %%! Locate the shell process... UGLY!!! GS2or3 = fun(P) -> case process_info(P,initial_call) of {initial_call,{group,server,X}} when X == 2 ; X == 3 -> -- cgit v1.2.3 From 5f49de9d6e8ae247b10e37c085bf1d1dc9945ac8 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Wed, 28 Oct 2015 17:15:36 +0000 Subject: Save error reasons for TLS distribution connections When establishing an outbound connection for TLS distribution, let's hold on to the failure reasons and use them as exit reasons. These exit reasons are normally invisible, but they can be seen in the logs after calling net_kernel:verbose(1). While there are trace messages in the code already, those require recompiling the module with a special flag, which is more cumbersome than changing the net_kernel verbosity level at run time. --- lib/ssl/src/inet_tls_dist.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl index 7367b5c224..411bb44bdc 100644 --- a/lib/ssl/src/inet_tls_dist.erl +++ b/lib/ssl/src/inet_tls_dist.erl @@ -75,23 +75,23 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> Timer, Version, Ip, TcpPort, Address, Type), dist_util:handshake_we_started(HSData); - _ -> + Other -> %% Other Node may have closed since %% port_please ! ?trace("other node (~p) " "closed since port_please.~n", [Node]), - ?shutdown(Node) + ?shutdown2(Node, {shutdown, {connect_failed, Other}}) end; - _ -> + Other -> ?trace("port_please (~p) " "failed.~n", [Node]), - ?shutdown(Node) + ?shutdown2(Node, {shutdown, {port_please_failed, Other}}) end; - _Other -> + Other -> ?trace("inet_getaddr(~p) " "failed (~p).~n", [Node,Other]), - ?shutdown(Node) + ?shutdown2(Node, {shutdown, {inet_getaddr_failed, Other}}) end. close(Socket) -> -- cgit v1.2.3 From 91006821c6d65708fa05a93ec1edc2372326a3cb Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Mon, 9 Nov 2015 18:25:56 +0000 Subject: Report bad options for outgoing TLS distribution If ssl:connect/3 returns an error related to options, let's log that so we have a chance to see it and fix it. --- lib/ssl/src/ssl_tls_dist_proxy.erl | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index e7f7fa96a1..1f48ce9e8c 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -193,6 +193,11 @@ setup_proxy(Ip, Port, Parent) -> Err -> Parent ! {self(), Err} end; + {error, {options, _}} = Err -> + %% Bad options: that's probably our fault. Let's log that. + error_logger:error_msg("Cannot open TLS distribution connection: ~s~n", + [ssl:format_error(Err)]), + Parent ! {self(), Err}; Err -> Parent ! {self(), Err} end. -- cgit v1.2.3 From 7d585fd4a743b5e5cae56b43c42a062ef72060ca Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Wed, 9 Dec 2015 13:05:20 +0100 Subject: [erl_docgen] Update item element in DTD Allow note, warning, do, dont in item element. --- lib/erl_docgen/priv/dtd/common.dtd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd index a29fc233fa..961bcd3fc2 100644 --- a/lib/erl_docgen/priv/dtd/common.dtd +++ b/lib/erl_docgen/priv/dtd/common.dtd @@ -68,7 +68,7 @@ - + -- cgit v1.2.3 From c88a054f2d9bbcce3902c3d4786bcc2a6b46e803 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 08:02:59 +0100 Subject: [erl_docgen] Update element d in DTD Allow seealso in the d element --- lib/erl_docgen/priv/dtd/common.refs.dtd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd index 6889e990de..1c2e513f15 100644 --- a/lib/erl_docgen/priv/dtd/common.refs.dtd +++ b/lib/erl_docgen/priv/dtd/common.refs.dtd @@ -35,7 +35,7 @@ name CDATA #IMPLIED name_i CDATA #IMPLIED> - + -- cgit v1.2.3 From a676b9a8b1e1154d41219ebfd6d6909f011f5e6e Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 13:01:38 +0100 Subject: [erl_docgen] Update element section in DTD Allow sections in sections for reference manuals. --- lib/erl_docgen/priv/dtd/common.refs.dtd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd index 1c2e513f15..4f87007a09 100644 --- a/lib/erl_docgen/priv/dtd/common.refs.dtd +++ b/lib/erl_docgen/priv/dtd/common.refs.dtd @@ -41,7 +41,7 @@ + warning|note|dont|do|section)*) > -- cgit v1.2.3 From 8edbf8309fe6f095d43cc4bbc3eceaa81823c7f4 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 07:17:20 +0100 Subject: [ssl] Correct the documentation so it follows the DTD --- lib/ssl/doc/src/ssl.xml | 5 ++--- lib/ssl/doc/src/ssl_app.xml | 6 +++--- lib/ssl/doc/src/ssl_crl_cache_api.xml | 6 +++--- lib/ssl/doc/src/ssl_session_cache_api.xml | 10 +++++++--- 4 files changed, 15 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 3a541ed162..32c80b3f00 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -480,8 +480,8 @@ fun(srp, Username :: string(), UserState :: term()) ->

The negotiated protocol can be retrieved using the negotiated_protocol/1 function.

- {client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()]}} - {client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()], Default :: binary()}} + {client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()]}}
+ {client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()], Default :: binary()}}

Indicates that the client is to try to perform Next Protocol Negotiation.

@@ -538,7 +538,6 @@ fun(srp, Username :: string(), UserState :: term()) -> be supported by the server for the prevention to work.

-
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index 24b0f5300e..1e3a1101ed 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -58,7 +58,7 @@

erl -ssl protocol_version "['tlsv1.2', 'tlsv1.1']"

- protocol_version = ssl:protocol() ]]> + protocol_version = ssl:protocol()]]>

Protocol supported by started clients and servers. If this option is not set, it defaults to all protocols currently supported by the SSL application. @@ -78,8 +78,8 @@

List of extra user-defined arguments to the init function in the session cache callback module. Defaults to [].

- ]]> - ]]> + ]]>
+ ]]>

Limits the growth of the clients/servers session cache, if the maximum number of sessions is reached, the current cache entries will be invalidated regardless of their remaining lifetime. Defaults to 1000. diff --git a/lib/ssl/doc/src/ssl_crl_cache_api.xml b/lib/ssl/doc/src/ssl_crl_cache_api.xml index 71c1c61fe8..03ac010bfe 100644 --- a/lib/ssl/doc/src/ssl_crl_cache_api.xml +++ b/lib/ssl/doc/src/ssl_crl_cache_api.xml @@ -84,9 +84,9 @@ CRLs = [public_key:der_encoded()] -

Lookup the CRLs belonging to the distribution point Distributionpoint.

+

Lookup the CRLs belonging to the distribution point Distributionpoint. This function may choose to only look in the cache or to follow distribution point - links depending on how the cache is administrated. + links depending on how the cache is administrated.

@@ -103,4 +103,4 @@ - \ No newline at end of file + diff --git a/lib/ssl/doc/src/ssl_session_cache_api.xml b/lib/ssl/doc/src/ssl_session_cache_api.xml index bd9330056d..b85d8fb284 100644 --- a/lib/ssl/doc/src/ssl_session_cache_api.xml +++ b/lib/ssl/doc/src/ssl_session_cache_api.xml @@ -31,9 +31,13 @@ ssl_session_cache_api TLS session cache API - Defines the API for the TLS session cache so - that the data storage scheme can be replaced by - defining a new callback module implementing this API. + +

+ Defines the API for the TLS session cache so + that the data storage scheme can be replaced by + defining a new callback module implementing this API. +

+
DATA TYPES -- cgit v1.2.3 From 909fa9fc39bee9d12d35bc9a82049b3d940fdd0c Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 09:28:13 +0100 Subject: [ssh] Align documentation to DTD --- lib/ssh/doc/src/ssh.xml | 28 +++++++++++----------- lib/ssh/doc/src/ssh_app.xml | 43 +++++++++++++++++----------------- lib/ssh/doc/src/ssh_connection.xml | 14 +++++------ lib/ssh/doc/src/ssh_server_key_api.xml | 4 ++-- lib/ssh/doc/src/ssh_sftp.xml | 31 +++++++++++++----------- 5 files changed, 62 insertions(+), 58 deletions(-) (limited to 'lib') diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index b3f850fc38..850557444d 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -4,7 +4,7 @@
- 20042014 + 20042015 Ericsson AB. All Rights Reserved. @@ -418,10 +418,10 @@

- -
where: -
PromptTexts = kb_int_tuple() | fun(Peer::{IP::tuple(),Port::integer()}, User::string(), Service::string()) -> kb_int_tuple() -
kb_int_tuple() = {Name::string(), Instruction::string(), Prompt::string(), Echo::boolean()}
+ +
where: +
PromptTexts = kb_int_tuple() | fun(Peer::{IP::tuple(),Port::integer()}, User::string(), Service::string()) -> kb_int_tuple() +
kb_int_tuple() = {Name::string(), Instruction::string(), Prompt::string(), Echo::boolean()}

Sets the text strings that the daemon sends to the client for presentation to the user when using keyboar-interactive authentication. If the fun/3 is used, it is called when the actual authentication occurs and may therefore return dynamic data like time, remote ip etc.

@@ -516,29 +516,29 @@

Provides a function for password validation. This could used for calling an external system or if passwords should be stored as a hash. The fun returns: - - true if the user and password is valid and - false otherwise. -

+ + true if the user and password is valid and + false otherwise. +

This fun can also be used to make delays in authentication tries for example by calling timer:sleep/1. To facilitate counting of failed tries the State variable could be used. This state is per connection only. The first time the pwdfun is called for a connection, the State variable has the value undefined. The pwdfun can return - in addition to the values above - a new state as: - - {true, NewState:any()} if the user and password is valid or - {false, NewState:any()} if the user or password is invalid -

+ + {true, NewState:any()} if the user and password is valid or + {false, NewState:any()} if the user or password is invalid +

A third usage is to block login attempts from a missbehaving peer. The State described above can be used for this. In addition to the responses above, the following return value is introduced: +

disconnect if the connection should be closed immediately after sending a SSH_MSG_DISCONNECT message. -

boolean()}]]> diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml index 79dd1e210e..f6ce44c015 100644 --- a/lib/ssh/doc/src/ssh_app.xml +++ b/lib/ssh/doc/src/ssh_app.xml @@ -4,7 +4,7 @@
- 20122013 + 20122015 Ericsson AB. All Rights Reserved. @@ -214,21 +214,21 @@

The following rfc:s are supported:

RFC 4251, The Secure Shell (SSH) Protocol Architecture. -

Except +

Except

9.4.6 Host-Based Authentication 9.5.2 Proxy Forwarding 9.5.3 X11 Forwarding -

+

RFC 4252, The Secure Shell (SSH) Authentication Protocol. -

Except +

Except

9. Host-Based Authentication: "hostbased" -

+

RFC 4253, The Secure Shell (SSH) Transport Layer Protocol. @@ -236,32 +236,32 @@ RFC 4254, The Secure Shell (SSH) Connection Protocol. -

Except +

Except

6.3. X11 Forwarding 7. TCP/IP Port Forwarding -

+

RFC 4256, Generic Message Exchange Authentication for the Secure Shell Protocol (SSH). -

Except +

Except

num-prompts > 1 password changing other identification methods than userid-password -

+

RFC 4419, Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol. -

+

RFC 4716, The Secure Shell (SSH) Public Key File Format. -

+

RFC 5647, AES Galois Counter Mode for @@ -270,34 +270,35 @@ This is resolved by OpenSSH in the ciphers aes128-gcm@openssh.com and aes256-gcm@openssh.com which are implemented. If the explicit ciphers and macs AEAD_AES_128_GCM or AEAD_AES_256_GCM are needed, they could be enabled with the option preferred_algorithms. +

- If the client or the server is not Erlang/OTP, it is the users responsibility to check that - other implementation has the same interpretation of AEAD_AES_*_GCM as the Erlang/OTP SSH before - enabling them. The aes*-gcm@openssh.com variants are always safe to use since they lack the - ambiguity. +

+ If the client or the server is not Erlang/OTP, it is the users responsibility to check that + other implementation has the same interpretation of AEAD_AES_*_GCM as the Erlang/OTP SSH before + enabling them. The aes*-gcm@openssh.com variants are always safe to use since they lack the + ambiguity. +

-

-

The second paragraph in section 5.1 is resolved as: +

The second paragraph in section 5.1 is resolved as:

If the negotiated cipher is AEAD_AES_128_GCM, the mac algorithm is set to AEAD_AES_128_GCM. If the negotiated cipher is AEAD_AES_256_GCM, the mac algorithm is set to AEAD_AES_256_GCM. If the mac algorithm is AEAD_AES_128_GCM, the cipher is set to AEAD_AES_128_GCM. If the mac algorithm is AEAD_AES_256_GCM, the cipher is set to AEAD_AES_256_GCM. - The first rule that matches when read in order from the top is applied -

+

The first rule that matches when read in order from the top is applied

RFC 5656, Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer. -

Except +

Except

5. ECMQV Key Exchange 6.4. ECMQV Key Exchange and Verification Method Name 7.2. ECMQV Message Numbers 10.2. Recommended Curves -

+

RFC 6668, SHA-2 Data Integrity Verification for diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml index 064a623eb6..150d46a9a2 100644 --- a/lib/ssh/doc/src/ssh_connection.xml +++ b/lib/ssh/doc/src/ssh_connection.xml @@ -5,7 +5,7 @@

2008 - 2014 + 2015 Ericsson AB, All Rights Reserved @@ -31,15 +31,15 @@
ssh_connection - This module provides API functions to send - SSH Connection Protocol - events to the other side of an SSH channel. + + This module provides API functions to send SSH Connection Protocol + events to the other side of an SSH channel. -

The SSH Connection Protocol is used by clients and servers, - that is, SSH channels, to communicate over the SSH connection. The - API functions in this module send SSH Connection Protocol events, +

The SSH Connection Protocol + is used by clients and servers, that is, SSH channels, to communicate over the + SSH connection. The API functions in this module send SSH Connection Protocol events, which are received as messages by the remote channel. If the receiving channel is an Erlang process, the messages have the format diff --git a/lib/ssh/doc/src/ssh_server_key_api.xml b/lib/ssh/doc/src/ssh_server_key_api.xml index efb2c436e8..a0694ca8d9 100644 --- a/lib/ssh/doc/src/ssh_server_key_api.xml +++ b/lib/ssh/doc/src/ssh_server_key_api.xml @@ -5,7 +5,7 @@

2012 - 2013 + 2015 Ericsson AB, All Rights Reserved @@ -75,7 +75,7 @@ Host key algorithm. Is to support 'ssh-rsa' | 'ssh-dss', but more algorithms can be handled. DaemonOptions = proplists:proplist() - Options provided to ssh:daemon/[2,3]. + Options provided to ssh:daemon/[2,3]. Key = private_key() Private key of the host matching the Algorithm. Reason = term() diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml index 17800fac5d..c6ca0f161a 100644 --- a/lib/ssh/doc/src/ssh_sftp.xml +++ b/lib/ssh/doc/src/ssh_sftp.xml @@ -4,7 +4,7 @@
- 20052014 + 20052015 Ericsson AB. All Rights Reserved. @@ -61,20 +61,23 @@ - apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, Error} - ChannelPid = pid() - Handle = term() - Position = integer() - Len = integer() - N = term() - Reason = term() - -

The function reads from a specified position, - combining the and functions.

+ apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, Reason} + Reads asynchronously from an open file. + + ChannelPid = pid() + Handle = term() + Position = integer() + Len = integer() + N = term() + Reason = term() + + +

The function reads from a specified position, + combining the and functions.

ssh_sftp:apread/4

-
- - + + + apwrite(ChannelPid, Handle, Position, Data) -> ok | {error, Reason} Writes asynchronously to an open file. -- cgit v1.2.3 From b1a1b4e8dc1929d438964017cec71869e8e24337 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 09:40:34 +0100 Subject: [ssl] Moved description details to man(6) page --- lib/ssl/doc/src/ssl.xml | 36 ++++++------------------------------ lib/ssl/doc/src/ssl_app.xml | 28 +++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 32c80b3f00..bf87644116 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -31,37 +31,13 @@ ssl Interface Functions for Secure Socket Layer -

This module contains interface functions for the SSL.

+

+ This module contains interface functions for the SSL/TLS protocol. + For detailed information about the supported standards see + ssl(6). +

- -
- SSL - - - For application dependencies see ssl(6) - Supported SSL/TLS-versions are SSL-3.0, TLS-1.0, - TLS-1.1, and TLS-1.2. - For security reasons SSL-2.0 is not supported. - For security reasons SSL-3.0 is no longer supported by default, - but can be configured. - Ephemeral Diffie-Hellman cipher suites are supported, - but not Diffie Hellman Certificates cipher suites. - Elliptic Curve cipher suites are supported if the Crypto - application supports it and named curves are used. - - Export cipher suites are not supported as the - U.S. lifted its export restrictions in early 2000. - IDEA cipher suites are not supported as they have - become deprecated by the latest TLS specification so it is not - motivated to implement them. - CRL validation is supported. - Policy certificate extensions are not supported. - 'Server Name Indication' extension client side - (RFC 6066, Section 3) is supported. - - -
- +
DATA TYPES

The following data types are used in the functions for SSL:

diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index 1e3a1101ed..6c82e32a74 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -33,7 +33,33 @@ The ssl application provides secure communication over sockets. - + +

+ The ssl application is an implementation of the SSL/TLS protocol in Erlang. +

+ + Supported SSL/TLS-versions are SSL-3.0, TLS-1.0, + TLS-1.1, and TLS-1.2. + For security reasons SSL-2.0 is not supported. + For security reasons SSL-3.0 is no longer supported by default, + but can be configured. + Ephemeral Diffie-Hellman cipher suites are supported, + but not Diffie Hellman Certificates cipher suites. + Elliptic Curve cipher suites are supported if the Crypto + application supports it and named curves are used. + + Export cipher suites are not supported as the + U.S. lifted its export restrictions in early 2000. + IDEA cipher suites are not supported as they have + become deprecated by the latest TLS specification so it is not + motivated to implement them. + CRL validation is supported. + Policy certificate extensions are not supported. + 'Server Name Indication' extension client side + (RFC 6066, Section 3) is supported. + +
+
DEPENDENCIES

The SSL application uses the public_key and -- cgit v1.2.3 From b8f7153606e51517e3d361ebbd1b2a4ff08bb7dd Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 10:06:04 +0100 Subject: [inets] Align documentation to DTD --- lib/inets/doc/src/http_server.xml | 19 +-- lib/inets/doc/src/http_uri.xml | 10 +- lib/inets/doc/src/httpc.xml | 10 +- lib/inets/doc/src/httpd.xml | 245 ++++++++++++++------------------------ lib/inets/doc/src/notes.xml | 64 +++++----- lib/inets/doc/src/tftp.xml | 21 +--- 6 files changed, 136 insertions(+), 233 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml index 4b6d64fc8f..5adae933cd 100644 --- a/lib/inets/doc/src/http_server.xml +++ b/lib/inets/doc/src/http_server.xml @@ -4,7 +4,7 @@

- 20042013 + 20042015 Ericsson AB. All Rights Reserved. @@ -21,18 +21,7 @@ limitations under the License. - HTTP server - Ingela Anderton Andin - - - - - - - http_server.xml - -
@@ -356,9 +345,9 @@ UserName:Password
- CGI Version 1.1, - <url href="http://www.ietf.org/rfc/rfc3875.txt">RFC 3875</url> -

The module mod_cgi enables execution of CGI scripts + CGI Version 1.1, RFC 3875 +

The module mod_cgi enables execution of + CGI scripts on the server. A file matching the definition of a ScriptAlias config directive is treated as a CGI script. A CGI script is executed by the server and its output is returned to diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml index 64e6c7a6cc..8e0301c520 100644 --- a/lib/inets/doc/src/http_uri.xml +++ b/lib/inets/doc/src/http_uri.xml @@ -4,7 +4,7 @@

- 20122013 + 20122015 Ericsson AB. All Rights Reserved. @@ -142,14 +142,14 @@

If the fragment option is true, the URI fragment is returned as part of the parsing result, otherwise it is ignored.

-

Scheme validation fun is to be defined as follows: +

Scheme validation fun is to be defined as follows:

- + fun(SchemeStr :: string()) -> valid | {error, Reason :: term()}. - + - It is called before scheme string gets converted into scheme atom and +

It is called before scheme string gets converted into scheme atom and thus possible atom leak could be prevented

diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 31e44f405c..ca9b268a03 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -4,7 +4,7 @@
- 20042013 + 20042015 Ericsson AB. All Rights Reserved. @@ -554,8 +554,8 @@ IpDesc = string() Example: "134.138" or "[FEDC:BA98" (all IP addresses starting with 134.138 or FEDC:BA98), - "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP address). - proxy defaults to {undefined, []}, + "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP address). + proxy defaults to {undefined, []}, that is, no proxy is configured and https_proxy defaults to the value of proxy. MaxSessions = integer() @@ -597,8 +597,8 @@ for details. socket_opts() = [socket_opt()] The options are appended to the socket options used by the - client. - These are the default values when a new request handler + client. + These are the default values when a new request handler is started (for the initial connect). They are passed directly to the underlying transport (gen_tcp or SSL) without verification. diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml index 0fc3cb1ce7..62b92b8356 100644 --- a/lib/inets/doc/src/httpd.xml +++ b/lib/inets/doc/src/httpd.xml @@ -30,13 +30,14 @@ httpd.sgml
httpd - An implementation of an HTTP - 1.1 compliant web server, as defined in RFC 2616 + + HTTP server API -

This module provides the HTTP server start options, some administrative - functions, and specifies the Erlang web server callback - API.

+

An implementation of an HTTP 1.1 compliant web server, as defined in + RFC 2616. + Provides web server start options, administrative functions, and + an Erlang callback API.

@@ -78,8 +79,7 @@ list.

- - {proplist_file, path()} + {proplist_file, path()}

If this property is defined, Inets expects to find all other properties defined in this file. The @@ -87,8 +87,7 @@ properties.

- - {file, path()} + {file, path()}

If this property is defined, Inets expects to find all other properties defined in this file, which uses Apache-like @@ -121,8 +120,7 @@

Mandatory Properties

- - {port, integer()} + {port, integer()}

The port that the HTTP server listen to. If zero is specified as port, an arbitrary available port @@ -130,22 +128,19 @@ determine which port was picked.

- - {server_name, string()} + {server_name, string()}

The name of your server, normally a fully qualified domain name.

- - {server_root, path()} + {server_root, path()}

Defines the home directory of the server, where log files, and so on, can be stored. Relative paths specified in other properties refer to this directory.

- - {document_root, path()} + {document_root, path()}

Defines the top directory for the documents that are available on the HTTP server.

@@ -155,15 +150,13 @@

Communication Properties

- - {bind_address, ip_address() | hostname() | any} + {bind_address, ip_address() | hostname() | any}

Default is any. any is denoted * in the Apache-like configuration file.

- - {profile, atom()} + {profile, atom()}

Used together with bind_address and port to uniquely identify @@ -176,8 +169,7 @@

- - {socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}} + {socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}}

For ip_comm configuration options, see gen_tcp:listen/2, some options @@ -187,15 +179,13 @@

Default is ip_comm.

- - {ipfamily, inet | inet6} + {ipfamily, inet | inet6}

Default is inet, legacy option inet6fb4 no longer makes sense and will be translated to inet.

- - {minimum_bytes_per_second, integer()} + {minimum_bytes_per_second, integer()}

If given, sets a minimum of bytes per second value for connections.

If the value is unreached, the socket closes for that connection.

@@ -206,8 +196,7 @@

Erlang Web Server API Modules

- - {modules, [atom()]} + {modules, [atom()]}

Defines which modules the HTTP server uses when handling requests. Default is [mod_alias, mod_auth, mod_esi, @@ -224,60 +213,52 @@

Limit properties

- - {customize, atom()} + {customize, atom()}

A callback module to customize the inets HTTP servers behaviour see httpd_custom_api

- - {disable_chunked_transfer_encoding_send, boolean()} + {disable_chunked_transfer_encoding_send, boolean()}

Allows you to disable chunked transfer-encoding when sending a response to an HTTP/1.1 client. Default is false.

- - {keep_alive, boolean()} + {keep_alive, boolean()}

Instructs the server whether to use persistent connections when the client claims to be HTTP/1.1 compliant. Default is true.

- - {keep_alive_timeout, integer()} + {keep_alive_timeout, integer()}

The number of seconds the server waits for a subsequent request from the client before closing the connection. Default is 150.

- - {max_body_size, integer()} + {max_body_size, integer()}

Limits the size of the message body of an HTTP request. Default is no limit.

- - {max_clients, integer()} + {max_clients, integer()}

Limits the number of simultaneous requests that can be supported. Default is 150.

- - {max_header_size, integer()} + {max_header_size, integer()}

Limits the size of the message header of an HTTP request. Default is 10240.

- - {max_content_length, integer()} + {max_content_length, integer()}

Maximum content-length in an incoming request, in bytes. Requests with content larger than this are answered with status 413. @@ -285,15 +266,13 @@

- - {max_uri_size, integer()} + {max_uri_size, integer()}

Limits the size of the HTTP request URI. Default is no limit.

- - {max_keep_alive_request, integer()} + {max_keep_alive_request, integer()}

The number of requests that a client can do on one connection. When the server has responded to the number of @@ -306,8 +285,7 @@

Administrative Properties

- - {mime_types, [{MimeType, Extension}] | path()} + {mime_types, [{MimeType, Extension}] | path()}

MimeType = string() and Extension = string(). Files delivered to the client are MIME typed according to RFC @@ -323,24 +301,21 @@ text/plain asc txt

Default is [{"html","text/html"},{"htm","text/html"}].

- - {mime_type, string()} + {mime_type, string()}

When the server is asked to provide a document type that cannot be determined by the MIME Type Settings, the server uses this default type.

- - {server_admin, string()} + {server_admin, string()}

Defines the email-address of the server administrator to be included in any error messages returned by the server.

- - {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}} + {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}

Defines the look of the value of the server header.

Example: Assuming the version of Inets is 5.8.1, @@ -367,8 +342,7 @@ text/plain asc txt

By default, the value is as before, that is, minimal.

- - {log_format, common | combined} + {log_format, common | combined}

Defines if access logs are to be written according to the common log format or the extended common log format. @@ -411,8 +385,7 @@ text/plain asc txt

- - {error_log_format, pretty | compact} + {error_log_format, pretty | compact}

Default is pretty. If the error log is meant to be read directly by a human, pretty is the best option.

@@ -434,60 +407,57 @@ text/plain asc txt

URL Aliasing Properties - Requires mod_alias

- - {alias, {Alias, RealName}} + {alias, {Alias, RealName}}

Alias = string() and RealName = string(). alias allows documents to be stored in the local file system instead of the document_root location. URLs with a path beginning with url-path is mapped to local files beginning with - directory-filename, for example: + directory-filename, for example:

{alias, {"/image", "/ftp/pub/image"}} - Access to http://your.server.org/image/foo.gif would refer to +

Access to http://your.server.org/image/foo.gif would refer to the file /ftp/pub/image/foo.gif.

- - {re_write, {Re, Replacement}} + {re_write, {Re, Replacement}}

Re = string() and Replacement = string(). re_write allows documents to be stored in the local file system instead of the document_root location. URLs are rewritten by re:replace/3 to produce a path in the local file-system, - for example: + for example:

{re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}} - Access to http://your.server.org/~bob/foo.gif would refer to +

Access to http://your.server.org/~bob/foo.gif would refer to the file /home/bob/public/foo.gif. In an Apache-like configuration file, Re is separated from Replacement with one single space, and as expected backslashes do not need to be backslash escaped, the - same example would become: + same example would become:

ReWrite ^/[~]([^/]+)(.*)$ /home/\1/public\2 - Beware of trailing space in Replacement to be used. +

Beware of trailing space in Replacement to be used. If you must have a space in Re, use, for example, the character encoding \040, see re(3).

- - {directory_index, [string()]} + {directory_index, [string()]}

directory_index specifies a list of resources to look for if a client requests a directory using a / at the end of the directory name. file depicts the name of a file in the directory. Several files can be given, in which case the server - returns the first it finds, for example: + returns the first it finds, for example:

{directory_index, ["index.hml", "welcome.html"]} - Access to http://your.server.org/docs/ would return +

Access to http://your.server.org/docs/ would return http://your.server.org/docs/index.html or http://your.server.org/docs/welcome.html if index.html does not exist.

@@ -497,38 +467,35 @@ text/plain asc txt

CGI Properties - Requires mod_cgi

- - {script_alias, {Alias, RealName}} + {script_alias, {Alias, RealName}}

Alias = string() and RealName = string(). Have the same behavior as property alias, except that they also mark the target directory as containing CGI scripts. URLs with a path beginning with url-path are mapped to - scripts beginning with directory-filename, for example: + scripts beginning with directory-filename, for example:

{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}} - Access to http://your.server.org/cgi-bin/foo would cause +

Access to http://your.server.org/cgi-bin/foo would cause the server to run the script /web/cgi-bin/foo.

- - {script_re_write, {Re, Replacement}} + {script_re_write, {Re, Replacement}}

Re = string() and Replacement = string(). Have the same behavior as property re_write, except that they also mark the target directory as containing CGI scripts. URLs with a path beginning with url-path are mapped to - scripts beginning with directory-filename, for example: + scripts beginning with directory-filename, for example:

{script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}} - Access to http://your.server.org/cgi-bin/17/foo would cause +

Access to http://your.server.org/cgi-bin/17/foo would cause the server to run the script /web/17/cgi-bin/foo.

- - {script_nocache, boolean()} + {script_nocache, boolean()}

If script_nocache is set to true, the HTTP server by default adds the header fields necessary to prevent proxies from @@ -536,8 +503,7 @@ text/plain asc txt Default to false.

- - {script_timeout, integer()} + {script_timeout, integer()}

The time in seconds the web server waits between each chunk of data from the script. If the CGI script does not deliver @@ -545,8 +511,7 @@ text/plain asc txt closed. Default is 15.

- - {action, {MimeType, CgiScript}} - requires mod_action + {action, {MimeType, CgiScript}} - requires mod_action

MimeType = string() and CgiScript = string(). action adds an action activating a CGI script @@ -559,8 +524,7 @@ text/plain asc txt {action, {"text/plain", "/cgi-bin/log_and_deliver_text"}} - - {script, {Method, CgiScript}} - requires mod_action + {script, {Method, CgiScript}} - requires mod_action

Method = string() and CgiScript = string(). script adds an action activating a CGI script @@ -579,17 +543,16 @@ text/plain asc txt

ESI Properties - Requires mod_esi

- - {erl_script_alias, {URLPath, [AllowedModule]}} + {erl_script_alias, {URLPath, [AllowedModule]}}

URLPath = string() and AllowedModule = atom(). erl_script_alias marks all URLs matching url-path as erl scheme scripts. A matching URL is mapped into a specific module - and function, for example: + and function, for example:

{erl_script_alias, {"/cgi-bin/example", [httpd_example]}} - A request to +

A request to http://your.server.org/cgi-bin/example/httpd_example:yahoo would refer to httpd_example:yahoo/3 or, if that does not exist, httpd_example:yahoo/2 and @@ -597,8 +560,7 @@ text/plain asc txt not be allowed to execute.

- - {erl_script_nocache, boolean()} + {erl_script_nocache, boolean()}

If erl_script_nocache is set to true, the server adds HTTP header fields preventing proxies from caching the @@ -607,8 +569,7 @@ text/plain asc txt Default is false.

- - {erl_script_timeout, integer()} + {erl_script_timeout, integer()}

If erl_script_timeout sets the time in seconds the server waits between each chunk of data to be delivered through @@ -616,8 +577,7 @@ text/plain asc txt for scripts that use the erl scheme.

- - {eval_script_alias, {URLPath, [AllowedModule]}} + {eval_script_alias, {URLPath, [AllowedModule]}}

URLPath = string() and AllowedModule = atom(). Same as erl_script_alias but for scripts @@ -629,24 +589,21 @@ text/plain asc txt

Log Properties - Requires mod_log

- - {error_log, path()} + {error_log, path()}

Defines the filename of the error log file to be used to log server errors. If the filename does not begin with a slash (/), it is assumed to be relative to the server_root.

- - {security_log, path()} + {security_log, path()}

Defines the filename of the access log file to be used to log security events. If the filename does not begin with a slash (/), it is assumed to be relative to the server_root.

- - {transfer_log, path()} + {transfer_log, path()}

Defines the filename of the access log file to be used to log incoming requests. If the filename does not begin with a @@ -657,8 +614,7 @@ text/plain asc txt

Disk Log Properties - Requires mod_disk_log

- - {disk_log_format, internal | external} + {disk_log_format, internal | external}

Defines the file format of the log files. See disk_log for details. If the internal file format is used, the @@ -668,16 +624,14 @@ text/plain asc txt external.

- - {error_disk_log, path()} + {error_disk_log, path()}

Defines the filename of the (disk_log(3)) error log file to be used to log server errors. If the filename does not begin with a slash (/), it is assumed to be relative to the server_root.

- - {error_disk_log_size, {MaxBytes, MaxFiles}} + {error_disk_log_size, {MaxBytes, MaxFiles}}

MaxBytes = integer() and MaxFiles = integer(). Defines the properties of the (disk_log(3)) error log @@ -686,8 +640,7 @@ text/plain asc txt used before the first file is truncated and reused.

- - {security_disk_log, path()} + {security_disk_log, path()}

Defines the filename of the (disk_log(3)) access log file logging incoming security events, that is, authenticated @@ -695,8 +648,7 @@ text/plain asc txt is assumed to be relative to the server_root.

- - {security_disk_log_size, {MaxBytes, MaxFiles}} + {security_disk_log_size, {MaxBytes, MaxFiles}}

MaxBytes = integer() and MaxFiles = integer(). Defines the properties of the disk_log(3) access log @@ -705,8 +657,7 @@ text/plain asc txt used before the first file is truncated and reused.

- - {transfer_disk_log, path()} + {transfer_disk_log, path()}

Defines the filename of the (disk_log(3)) access log file logging incoming requests. If the filename does not begin @@ -714,8 +665,7 @@ text/plain asc txt server_root.

- - {transfer_disk_log_size, {MaxBytes, MaxFiles}} + {transfer_disk_log_size, {MaxBytes, MaxFiles}}

MaxBytes = integer() and MaxFiles = integer(). Defines the properties of the disk_log(3) access log @@ -735,32 +685,29 @@ text/plain asc txt

The properties for directories are as follows:

- - {allow_from, all | [RegxpHostString]} + {allow_from, all | [RegxpHostString]}

Defines a set of hosts to be granted access to a - given directory, for example: + given directory, for example:

{allow_from, ["123.34.56.11", "150.100.23"]} - The host 123.34.56.11 and all machines on the 150.100.23 +

The host 123.34.56.11 and all machines on the 150.100.23 subnet are allowed access.

- - {deny_from, all | [RegxpHostString]} + {deny_from, all | [RegxpHostString]}

Defines a set of hosts - to be denied access to a given directory, for example: + to be denied access to a given directory, for example:

{deny_from, ["123.34.56.11", "150.100.23"]} - The host 123.34.56.11 and all machines on the 150.100.23 +

The host 123.34.56.11 and all machines on the 150.100.23 subnet are not allowed access.

- - {auth_type, plain | dets | mnesia} + {auth_type, plain | dets | mnesia}

Sets the type of authentication database that is used for the directory. The key difference between the different methods is @@ -770,8 +717,7 @@ text/plain asc txt configuration files.

- - {auth_user_file, path()} + {auth_user_file, path()}

Sets the name of a file containing the list of users and passwords for user authentication. The filename can be either @@ -795,8 +741,7 @@ text/plain asc txt clients can download it.

- - {auth_group_file, path()} + {auth_group_file, path()}

Sets the name of a file containing the list of user groups for user authentication. The filename can be either @@ -818,16 +763,14 @@ text/plain asc txt can download it.

- - {auth_name, string()} + {auth_name, string()}

Sets the name of the authorization realm (auth-domain) for a directory. This string informs the client about which username and password to use.

- - {auth_access_password, string()} + {auth_access_password, string()}

If set to other than "NoPassword", the password is required for all API calls. If the password is set to "DummyPassword", the @@ -837,15 +780,13 @@ text/plain asc txt text in the configuration file.

- - {require_user, [string()]} + {require_user, [string()]}

Defines users to grant access to a given directory using a secret password.

- - {require_group, [string()]} + {require_group, [string()]}

Defines users to grant access to a given directory using a secret password.

@@ -856,8 +797,7 @@ text/plain asc txt

Htaccess Authentication Properties - Requires mod_htaccess

- - {access_files, [path()]} + {access_files, [path()]}

Specifies the filenames that are used for access files. When a request comes, every directory in the path @@ -877,16 +817,14 @@ text/plain asc txt

The properties for the security directories are as follows:

- - {data_file, path()} + {data_file, path()}

Name of the security data file. The filename can either be absolute or relative to the server_root. This file is used to store persistent data for module mod_security.

- - {max_retries, integer()} + {max_retries, integer()}

Specifies the maximum number of attempts to authenticate a user before the user is blocked out. If a user @@ -898,16 +836,14 @@ text/plain asc txt Default is 3. Can be set to infinity.

- - {block_time, integer()} + {block_time, integer()}

Specifies the number of minutes a user is blocked. After this timehas passed, the user automatically regains access. Default is 60.

- - {fail_expire_time, integer()} + {fail_expire_time, integer()}

Specifies the number of minutes a failed user authentication is remembered. If a user authenticates after this @@ -916,8 +852,7 @@ text/plain asc txt Default is 30.

- - {auth_timeout, integer()} + {auth_timeout, integer()} Specifies the number of seconds a successful user authentication is remembered. After this time has passed, the diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 8c4fdfdf70..7ebb3ddffa 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -4,7 +4,7 @@
- 20022014 + 20022015 Ericsson AB. All Rights Reserved. @@ -1807,23 +1807,21 @@

[httpd] - Issues with ESI erl_script_timeout.

-

- - -

The erl_script_timeout config option is ducumented - as a number of seconds. But when parsing the config, in the - new format (not a config file), it was handled as if in - number of milliseconds.

-
- -

When the erl-script-timeout time was exceeded, the server - incorrectly marked the answer as sent, thereby leaving - client hanging (with an incomplete answer). - This has been changed, so that now the socket will be - closed.

-
- -

+ + +

The erl_script_timeout config option is ducumented + as a number of seconds. But when parsing the config, in the + new format (not a config file), it was handled as if in + number of milliseconds.

+
+ +

When the erl-script-timeout time was exceeded, the server + incorrectly marked the answer as sent, thereby leaving + client hanging (with an incomplete answer). + This has been changed, so that now the socket will be + closed.

+
+

Own Id: OTP-8509

@@ -1899,20 +1897,19 @@

[httpc] Several more or less critical fixes:

-

- - -

Initial call between the httpc manager and request - handler was synchronous.

-

When the manager starts a new request handler, - this is no longer a synchronous operation. Previously, - the new request handler made the connection to the - server and issuing of the first request (the reason - for starting it) in the gen_server init function. - If the connection for some reason "took some time", - the manager hanged, leaving all other activities by - that manager also hanging.

-
+ + +

Initial call between the httpc manager and request + handler was synchronous.

+

When the manager starts a new request handler, + this is no longer a synchronous operation. Previously, + the new request handler made the connection to the + server and issuing of the first request (the reason + for starting it) in the gen_server init function. + If the connection for some reason "took some time", + the manager hanged, leaving all other activities by + that manager also hanging.

+
-
-

+

As a side-effect of these changes, some modules was also renamed, and a new api module, httpc, has been introduced diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml index 00d9d53376..10398f5088 100644 --- a/lib/inets/doc/src/tftp.xml +++ b/lib/inets/doc/src/tftp.xml @@ -4,7 +4,7 @@

- 20062013 + 20062015 Ericsson AB. All Rights Reserved. @@ -216,12 +216,9 @@ five times when the time-out expires.

- -
- change_config(daemons, Options) -> [{Pid, Result}] Changes configuration for all daemons. @@ -234,8 +231,6 @@

Changes configuration for all TFTP daemon processes.

- -
@@ -251,8 +246,6 @@

Changes configuration for all TFTP server processes.

- -
@@ -268,7 +261,6 @@

Changes configuration for a TFTP daemon, server, or client process.

-
@@ -282,8 +274,6 @@

Returns information about all TFTP daemon processes.

- -
@@ -297,8 +287,6 @@

Returns information about all TFTP server processes.

- -
@@ -341,9 +329,7 @@ the regexps of these and the callback module corresponding to the first match is used, or an error tuple is returned if no matching regexp is found.

- - - + @@ -359,8 +345,6 @@ port. When it receives a request for read or write, it spawns a temporary server process handling the actual transfer of the (virtual) file.

- -
@@ -393,7 +377,6 @@ matching regexp is found.

-
-- cgit v1.2.3 From 39d2ece8440c94539f1875695bd5a7f2f2b5f654 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 10:30:55 +0100 Subject: [orber] Align documentation to DTD --- lib/orber/doc/src/notes.xml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml index 3f7d4121fd..7b5d0f96ca 100644 --- a/lib/orber/doc/src/notes.xml +++ b/lib/orber/doc/src/notes.xml @@ -169,11 +169,9 @@
Known Bugs and Problems -

-

-

- Own Id: OTP-10675 Aux Id: seq12154

+ Own Id: OTP-10675 Aux Id: seq12154 +

-- cgit v1.2.3 From 545b938fb12396c9e1313a4bacf68f5307941be5 Mon Sep 17 00:00:00 2001 From: Lars Thorsen Date: Thu, 10 Dec 2015 13:21:13 +0100 Subject: [inets] Correct broken links --- lib/inets/doc/src/http_server.xml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml index 5adae933cd..aeda961714 100644 --- a/lib/inets/doc/src/http_server.xml +++ b/lib/inets/doc/src/http_server.xml @@ -22,6 +22,7 @@ HTTP server + http_server.xml
@@ -54,12 +55,9 @@

As of Inets 5.0 the HTTP server is an easy to start/stop and customize web server providing the most basic - web server functionality. Depending on your needs, there - are also other Erlang-based web servers that can be of interest - such as Yaws, which, - for example, has its own - markup support to generate HTML and supports certain buzzword - technologies, such as SOAP.

+ web server functionality. Inets is designed for embedded systems + and if you want a full-fledged web server there are exists other + erlang open source alternatives.

Almost all server functionality has been implemented using an especially crafted server API, which is described in the Erlang Web @@ -530,7 +528,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[ mod_action - Filetype/Method-Based Script Execution

This module runs CGI scripts whenever a file of a certain type or HTTP method (see - RFC 1945RFC 1945) + RFC 1945) is requested.

Uses the following Erlang Web Server API interaction data: @@ -557,7 +555,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[ {real_name, PathData} PathData is the argument used for API function - mod_alias:path/3. + mod_alias:path/3.

-- cgit v1.2.3 From c636a384b5375063d92b4ea25c0e646194240b4f Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 11 Dec 2015 11:59:02 +0100 Subject: ssl: Fix typos --- lib/ssl/test/ssl_ECC_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index fd2afc808c..75b639b23b 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -275,8 +275,8 @@ start_server(openssl, CA, OwnCa, Cert, Key, Config) -> Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), Exe = "openssl", Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), - "-verify", "2", "-cert ", Cert, "-CAfile", NewCA, - "-key", Key, "-msg" "-debug"], + "-verify", "2", "-cert", Cert, "-CAfile", NewCA, + "-key", Key, "-msg", "-debug"], OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, "Hello world"), {OpenSslPort, Port}; -- cgit v1.2.3 From 75274f8ccca62b36aebf32040c432de221887867 Mon Sep 17 00:00:00 2001 From: Zandra Date: Fri, 11 Dec 2015 12:19:01 +0100 Subject: correct the snmp app up file --- lib/snmp/src/app/snmp.appup.src | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index f2936c0c1d..77418f920f 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -29,7 +29,7 @@ %% {update, snmpa_local_db, soft, soft_purge, soft_purge, []} %% {add_module, snmpm_net_if_mt} [ - {"5.3", [{load_module, snmp_conf, soft_purge, soft_purge, []}]}, + {"5.2", [{load_module, snmp_conf, soft_purge, soft_purge, []}]}, {"5.1.2", [ % Only runtime dependencies change ]}, {"5.1.1", [{restart_application, snmp}]}, @@ -51,6 +51,7 @@ %% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} [ + {"5.2", [{load_module, snmp_conf, soft_purge, soft_purge, []}]}, {"5.1.2", [ % Only runtime dependencies change ]}, {"5.1.1", [{restart_application, snmp}]}, -- cgit v1.2.3 From 4b45171ef63418a1739238e68d9a95abe14d93fd Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 11 Dec 2015 12:23:42 +0100 Subject: Update appups in kernel, stdlib and sasl for OTP-18.2 --- lib/kernel/src/kernel.appup.src | 4 ++-- lib/sasl/src/sasl.appup.src | 8 ++++---- lib/stdlib/src/stdlib.appup.src | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 3fda55d1a9..860d3640d0 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"4\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + [{<<"4\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"4\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* + [{<<"4\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src index 2c8812f566..8faa0afbd4 100644 --- a/lib/sasl/src/sasl.appup.src +++ b/lib/sasl/src/sasl.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* - {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 + [{<<"2\\.[5-6](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* + {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 %% Down to - max one major revision back - [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.0.* - {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 + [{<<"2\\.[5-6](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* + {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 }. diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 5f61752655..04cdf31ada 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, %% OTP-18.0.* - {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], %% 17.0-17.5 + [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* + {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], % 17.0-17.5 %% Down to - max one major revision back - [{<<"2\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, %% OTP-18.0.* - {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] %% 17.0-17.5 + [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* + {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] % 17.0-17.5 }. -- cgit v1.2.3 From 80757f9491c72ee262a5910e0b3b02e95b1e5f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 4 Dec 2015 12:15:40 +0100 Subject: Use 'rand' instead of the obsolete 'random' module In most cases, we don't have to seed the random number generator, as the rand:uniform/1 takes care about that itself. --- lib/asn1/src/asn1ct_value.erl | 5 +---- lib/asn1/test/testPrimStrings.erl | 2 +- lib/common_test/src/ct_config.erl | 3 +-- lib/compiler/src/rec_env.erl | 11 ++++++++++- lib/kernel/src/global.erl | 20 +++++++------------- lib/mnesia/src/mnesia_lib.erl | 15 +-------------- lib/reltool/src/reltool_fgraph_win.erl | 4 ++-- lib/syntax_tools/src/erl_syntax_lib.erl | 12 +++++++++--- lib/test_server/src/test_server_ctrl.erl | 14 ++++++++++---- lib/test_server/src/test_server_node.erl | 3 +-- 10 files changed, 43 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl index 7f20d57b1e..61a5661a11 100644 --- a/lib/asn1/src/asn1ct_value.erl +++ b/lib/asn1/src/asn1ct_value.erl @@ -353,10 +353,7 @@ random_unnamed_bit_string(M, C) -> %% end. random(Upper) -> - _ = random:seed(erlang:phash2([erlang:node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - random:uniform(Upper). + rand:uniform(Upper). size_random(C) -> case get_constraint(C,'SizeConstraint') of diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index 46793c6bff..c9217d60fa 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -54,7 +54,7 @@ fragmented_strings(Len, Types) -> ok. make_ns_value(0) -> []; -make_ns_value(N) -> [($0 - 1) + random:uniform(10)|make_ns_value(N-1)]. +make_ns_value(N) -> [($0 - 1) + rand:uniform(10)|make_ns_value(N-1)]. fragmented_lengths() -> K16 = 1 bsl 14, diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl index 251204aa75..33efe7a14a 100644 --- a/lib/common_test/src/ct_config.erl +++ b/lib/common_test/src/ct_config.erl @@ -694,11 +694,10 @@ make_crypto_key(String) -> {[K1,K2,K3],IVec}. random_bytes(N) -> - random:seed(os:timestamp()), random_bytes_1(N, []). random_bytes_1(0, Acc) -> Acc; -random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]). +random_bytes_1(N, Acc) -> random_bytes_1(N-1, [rand:uniform(255)|Acc]). check_callback_load(Callback) -> case code:is_loaded(Callback) of diff --git a/lib/compiler/src/rec_env.erl b/lib/compiler/src/rec_env.erl index 0e9e12d1ad..5a4a870769 100644 --- a/lib/compiler/src/rec_env.erl +++ b/lib/compiler/src/rec_env.erl @@ -598,7 +598,16 @@ start_range(Env) -> %% (pseudo-)randomly distributed over the range. generate(_N, Range) -> - random:uniform(Range). % works well + %% We must use the same sequence of random variables to ensure + %% that two compilations of the same source code generates the + %% same BEAM code. + case rand:export_seed() of + undefined -> + rand:seed(exsplus, {1,42,2053}); + _ -> + ok + end, + rand:uniform(Range). % works well %% ===================================================================== diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index dcabeb5e49..0c73ead7c5 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -2068,23 +2068,17 @@ get_known() -> gen_server:call(global_name_server, get_known, infinity). random_sleep(Times) -> - case (Times rem 10) of - 0 -> erase(random_seed); - _ -> ok - end, - case get(random_seed) of - undefined -> - _ = random:seed(erlang:phash2([erlang:node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - ok; - _ -> ok - end, + _ = case Times rem 10 of + 0 -> + _ = rand:seed(exsplus); + _ -> + ok + end, %% First time 1/4 seconds, then doubling each time up to 8 seconds max. Tmax = if Times > 5 -> 8000; true -> ((1 bsl Times) * 1000) div 8 end, - T = random:uniform(Tmax), + T = rand:uniform(Tmax), ?trace({random_sleep, {me,self()}, {times,Times}, {t,T}, {tmax,Tmax}}), receive after T -> ok end. diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl index 77c7a7638d..4e761d2bed 100644 --- a/lib/mnesia/src/mnesia_lib.erl +++ b/lib/mnesia/src/mnesia_lib.erl @@ -921,20 +921,7 @@ random_time(Retries, _Counter0) -> UpperLimit = 500, Dup = Retries * Retries, MaxIntv = trunc(UpperLimit * (1-(50/((Dup)+50)))), - - case get(random_seed) of - undefined -> - _ = random:seed(erlang:unique_integer(), - erlang:monotonic_time(), - erlang:unique_integer()), - Time = Dup + random:uniform(MaxIntv), - %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]), - Time; - _ -> - Time = Dup + random:uniform(MaxIntv), - %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]), - Time - end. + Dup + rand:uniform(MaxIntv). report_system_event(Event0) -> Event = {mnesia_system_event, Event0}, diff --git a/lib/reltool/src/reltool_fgraph_win.erl b/lib/reltool/src/reltool_fgraph_win.erl index 6b58cae187..deab502bfe 100644 --- a/lib/reltool/src/reltool_fgraph_win.erl +++ b/lib/reltool/src/reltool_fgraph_win.erl @@ -220,8 +220,8 @@ graph_add_node_unsure(Key, State, G = #graph{ vs = Vs }) -> graph_add_node(Key, Color, G = #graph{ vs = Vs}) -> Q = 20.0, % repulsive force M = 0.5, % mass - P = {float(450 + random:uniform(100)), - float(450 + random:uniform(100))}, + P = {float(450 + rand:uniform(100)), + float(450 + rand:uniform(100))}, G#graph{ vs = reltool_fgraph:add(Key, #fg_v{ p = P, m = M, q = Q, color = Color}, Vs)}. diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl index 5b5b18d15b..58c4cc5244 100644 --- a/lib/syntax_tools/src/erl_syntax_lib.erl +++ b/lib/syntax_tools/src/erl_syntax_lib.erl @@ -359,9 +359,9 @@ new_variable_name(S) -> %% within a reasonably small range relative to the number of elements in %% the set. %% -%% This function uses the module `random' to generate new +%% This function uses the module `rand' to generate new %% keys. The seed it uses may be initialized by calling -%% `random:seed/0' or `random:seed/3' before this +%% `rand:seed/1' or `rand:seed/2' before this %% function is first called. %% %% @see new_variable_name/1 @@ -404,7 +404,13 @@ start_range(S) -> %% order, but (pseudo-)randomly distributed over the range. generate(_Key, Range) -> - random:uniform(Range). % works well + _ = case rand:export_seed() of + undefined -> + rand:seed(exsplus, {753,8,73}); + _ -> + ok + end, + rand:uniform(Range). % works well %% ===================================================================== diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 0be6e0b4e4..34681876f3 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -3163,11 +3163,17 @@ delete_prop([], Props) -> %% Shuffles the order of Cases. shuffle_cases(Ref, Cases, undefined) -> - shuffle_cases(Ref, Cases, ?now); + shuffle_cases(Ref, Cases, rand:seed_s(exsplus)); -shuffle_cases(Ref, [{conf,Ref,_,_}=Start | Cases], Seed) -> +shuffle_cases(Ref, [{conf,Ref,_,_}=Start | Cases], Seed0) -> {N,CasesToShuffle,Rest} = cases_to_shuffle(Ref, Cases), - ShuffledCases = random_order(N, random:uniform_s(N, Seed), CasesToShuffle, []), + Seed = case Seed0 of + {X,Y,Z} when is_integer(X+Y+Z) -> + rand:seed(exsplus, Seed0); + _ -> + Seed0 + end, + ShuffledCases = random_order(N, rand:uniform_s(N, Seed), CasesToShuffle, []), [Start|ShuffledCases] ++ Rest. cases_to_shuffle(Ref, Cases) -> @@ -3201,7 +3207,7 @@ random_order(1, {_Pos,Seed}, [{_Ix,CaseOrGroup}], Shuffled) -> Shuffled++CaseOrGroup; random_order(N, {Pos,NewSeed}, IxCases, Shuffled) -> {First,[{_Ix,CaseOrGroup}|Rest]} = lists:split(Pos-1, IxCases), - random_order(N-1, random:uniform_s(N-1, NewSeed), + random_order(N-1, rand:uniform_s(N-1, NewSeed), First++Rest, Shuffled++CaseOrGroup). diff --git a/lib/test_server/src/test_server_node.erl b/lib/test_server/src/test_server_node.erl index 4e6839fc6b..3419f3f5d0 100644 --- a/lib/test_server/src/test_server_node.erl +++ b/lib/test_server/src/test_server_node.erl @@ -619,8 +619,7 @@ do_quote_progname([Prog,Arg|Args]) -> end. random_element(L) -> - random:seed(os:timestamp()), - lists:nth(random:uniform(length(L)), L). + lists:nth(rand:uniform(length(L)), L). find_release(latest) -> "/usr/local/otp/releases/latest/bin/erl"; -- cgit v1.2.3 From fcc7aae270464f7328c5ff494d392217267f71cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 9 Dec 2015 15:38:35 +0100 Subject: compiler tests: Replace 'random' with 'rand' --- lib/compiler/test/map_SUITE.erl | 22 +++++++++++----------- lib/compiler/test/misc_SUITE.erl | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index 411b15eebe..b3cafe4ed9 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -1882,7 +1882,7 @@ register_corruption_dummy_call(A,B,C) -> {A,B,C}. t_frequency_table(Config) when is_list(Config) -> - random:seed({13,1337,54}), % pseudo random + rand:seed(exsplus, {13,1337,54}), % pseudo random N = 100000, Ts = rand_terms(N), #{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}), @@ -1925,7 +1925,7 @@ rand_terms(0) -> []; rand_terms(N) -> [rand_term()|rand_terms(N-1)]. rand_term() -> - case random:uniform(6) of + case rand:uniform(6) of 1 -> rand_binary(); 2 -> rand_number(); 3 -> rand_atom(); @@ -1935,21 +1935,21 @@ rand_term() -> end. rand_binary() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> <<>>; 2 -> <<"hi">>; 3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">> end. rand_number() -> - case random:uniform(3) of - 1 -> random:uniform(5); - 2 -> float(random:uniform(5)); - 3 -> 1 bsl (63 + random:uniform(3)) + case rand:uniform(3) of + 1 -> rand:uniform(5); + 2 -> float(rand:uniform(5)); + 3 -> 1 bsl (63 + rand:uniform(3)) end. rand_atom() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> hi; 2 -> some_atom; 3 -> some_other_atom @@ -1957,21 +1957,21 @@ rand_atom() -> rand_tuple() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> {ok, rand_term()}; % careful 2 -> {1, 2, 3}; 3 -> {<<"yep">>, 1337} end. rand_list() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> "hi"; 2 -> [1,rand_term()]; % careful 3 -> [improper|list] end. rand_map() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> #{ hi => 3 }; 2 -> #{ wat => rand_term(), other => 3 }; % careful 3 -> #{ hi => 42, other => 42, yet_anoter => 1337 } diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index c7c20fdbf2..a8b4ed0a24 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -389,9 +389,9 @@ integer_encoding_1(Config) -> do_integer_encoding(0, _, _, _) -> ok; do_integer_encoding(N, I0, Src, Data) -> - I1 = (I0 bsl 5) bor (random:uniform(32) - 1), + I1 = (I0 bsl 5) bor (rand:uniform(32) - 1), do_integer_encoding(I1, Src, Data), - I2 = -(I1 bxor (random:uniform(32) - 1)), + I2 = -(I1 bxor (rand:uniform(32) - 1)), do_integer_encoding(I2, Src, Data), do_integer_encoding(N-1, I1, Src, Data). -- cgit v1.2.3 From d8dab7ad987cb0d57bc2e4b2bbbec7ebe5ef2a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 9 Dec 2015 15:41:28 +0100 Subject: debugger tests: Replace 'random' with 'rand' --- lib/debugger/test/map_SUITE.erl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/debugger/test/map_SUITE.erl b/lib/debugger/test/map_SUITE.erl index 0ef634f7aa..eabcdcbf42 100644 --- a/lib/debugger/test/map_SUITE.erl +++ b/lib/debugger/test/map_SUITE.erl @@ -2219,7 +2219,7 @@ map_guard_sequence_mixed(K1,K2,M) -> t_frequency_table(Config) when is_list(Config) -> - random:seed({13,1337,54}), % pseudo random + rand:seed(exsplus, {13,1337,54}), % pseudo random N = 1000, Ts = rand_terms(N), #{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}), @@ -2262,7 +2262,7 @@ rand_terms(0) -> []; rand_terms(N) -> [rand_term()|rand_terms(N-1)]. rand_term() -> - case random:uniform(6) of + case rand:uniform(6) of 1 -> rand_binary(); 2 -> rand_number(); 3 -> rand_atom(); @@ -2272,21 +2272,21 @@ rand_term() -> end. rand_binary() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> <<>>; 2 -> <<"hi">>; 3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">> end. rand_number() -> - case random:uniform(3) of - 1 -> random:uniform(5); - 2 -> float(random:uniform(5)); - 3 -> 1 bsl (63 + random:uniform(3)) + case rand:uniform(3) of + 1 -> rand:uniform(5); + 2 -> float(rand:uniform(5)); + 3 -> 1 bsl (63 + rand:uniform(3)) end. rand_atom() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> hi; 2 -> some_atom; 3 -> some_other_atom @@ -2294,21 +2294,21 @@ rand_atom() -> rand_tuple() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> {ok, rand_term()}; % careful 2 -> {1, 2, 3}; 3 -> {<<"yep">>, 1337} end. rand_list() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> "hi"; 2 -> [1,rand_term()]; % careful 3 -> [improper|list] end. rand_map() -> - case random:uniform(3) of + case rand:uniform(3) of 1 -> #{ hi => 3 }; 2 -> #{ wat => rand_term(), other => 3 }; % careful 3 -> #{ hi => 42, other => 42, yet_anoter => 1337 } -- cgit v1.2.3 From 51f1e296e7d8709df6324f78e365446a22201cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Dec 2015 14:57:40 +0100 Subject: kernel test: Replace 'random' with 'rand' --- lib/kernel/test/file_name_SUITE.erl | 6 +++--- lib/kernel/test/gen_tcp_echo_SUITE.erl | 9 +-------- lib/kernel/test/global_SUITE.erl | 2 +- lib/kernel/test/inet_SUITE.erl | 3 +-- lib/kernel/test/inet_res_SUITE.erl | 2 +- lib/kernel/test/zlib_SUITE.erl | 6 +++--- 6 files changed, 10 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 32006d893e..4c422c9e0a 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -159,7 +159,7 @@ normalize(suite) -> normalize(doc) -> ["Check that filename normalization works"]; normalize(Config) when is_list(Config) -> - random:seed({1290,431421,830412}), + rand:seed(exsplus, {1290,431421,830412}), try ?line UniMode = file:native_name_encoding() =/= latin1, if @@ -845,7 +845,7 @@ conv(L) -> rand_comp_decomp(Max) -> - N = random:uniform(Max), + N = rand:uniform(Max), L = [ rand_decomp() || _ <- lists:seq(1,N) ], LC = [ A || {A,_} <- L], LD = lists:flatten([B || {_,B} <- L]), @@ -855,7 +855,7 @@ rand_comp_decomp(Max) -> rand_decomp() -> BT = bigtup(), SZ = tuple_size(BT), - element(random:uniform(SZ),BT). + element(rand:uniform(SZ),BT). bigtup() -> {{192,[65,768]}, {200,[69,768]}, diff --git a/lib/kernel/test/gen_tcp_echo_SUITE.erl b/lib/kernel/test/gen_tcp_echo_SUITE.erl index 6dcb21758b..b5ed16ec34 100644 --- a/lib/kernel/test/gen_tcp_echo_SUITE.erl +++ b/lib/kernel/test/gen_tcp_echo_SUITE.erl @@ -442,14 +442,7 @@ random_char(Chars) -> lists:nth(uniform(length(Chars)), Chars). uniform(N) -> - case get(random_seed) of - undefined -> - {X, Y, Z} = time(), - random:seed(X, Y, Z); - _ -> - ok - end, - random:uniform(N). + rand:uniform(N). put_int32(X, big, List) -> [ (X bsr 24) band 16#ff, diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl index 73ee86eba4..c0e24e17fe 100644 --- a/lib/kernel/test/global_SUITE.erl +++ b/lib/kernel/test/global_SUITE.erl @@ -2931,7 +2931,7 @@ sync_until(LogFile) -> timer:sleep(Time). shuffle(L) -> - [E || {_, E} <- lists:keysort(1, [{random:uniform(), E} || E <- L])]. + [E || {_, E} <- lists:keysort(1, [{rand:uniform(), E} || E <- L])]. sync_0(suite) -> []; sync_0(doc) -> diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index 5ba06bb032..d64a52fc2c 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -868,7 +868,6 @@ gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts) -> ?line Lookupers = [spawn_link( fun () -> - random:seed(), lookup_loop(Hosts, Delay, Tag, Parent, Cnt, Hosts) end) || _ <- lists:seq(1, N)], @@ -929,7 +928,7 @@ lookup_loop([H|Hs], Delay, Tag, Parent, Cnt, Hosts) -> Parent ! {Tag,Error} end, receive - after random:uniform(Delay) -> + after rand:uniform(Delay) -> lookup_loop(Hs, Delay, Tag, Parent, Cnt-1, Hosts) end. diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl index ace4ccb8bd..6e575c2f95 100644 --- a/lib/kernel/test/inet_res_SUITE.erl +++ b/lib/kernel/test/inet_res_SUITE.erl @@ -120,7 +120,7 @@ ns_init(ZoneDir, PrivDir, DataDir) -> {unix,_} -> PortNum = case {os:type(),os:version()} of {{unix,solaris},{M,V,_}} when M =< 5, V < 10 -> - 11895 + random:uniform(100); + 11895 + rand:uniform(100); _ -> {ok,S} = gen_udp:open(0, [{reuseaddr,true}]), {ok,PNum} = inet:port(S), diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index 6aaa024a82..77fdabe73c 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -912,7 +912,7 @@ smp(Config) -> FnAList = lists:map(fun(F) -> {F,?MODULE:F({get_arg,Config})} end, Funcs), - Pids = [spawn_link(?MODULE, worker, [random:uniform(9999), + Pids = [spawn_link(?MODULE, worker, [rand:uniform(9999), list_to_tuple(FnAList), self()]) || _ <- lists:seq(1,NumOfProcs)], @@ -925,7 +925,7 @@ smp(Config) -> worker(Seed, FnATpl, Parent) -> io:format("smp worker ~p, seed=~p~n",[self(),Seed]), - random:seed(Seed,Seed,Seed), + rand:seed(exsplus, {Seed,Seed,Seed}), worker_loop(100, FnATpl), Parent ! self(). @@ -933,7 +933,7 @@ worker_loop(0, _FnATpl) -> large_deflate_do(), % the time consuming one as finale ok; worker_loop(N, FnATpl) -> - {F,A} = element(random:uniform(size(FnATpl)),FnATpl), + {F,A} = element(rand:uniform(tuple_size(FnATpl)), FnATpl), ?MODULE:F(A), worker_loop(N-1, FnATpl). -- cgit v1.2.3 From 4145a6e4a5a65b1ba070328b03b8a0c085d9feba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 9 Dec 2015 15:41:28 +0100 Subject: stdlib tests: Replace 'random' with 'rand' --- lib/stdlib/test/base64_SUITE.erl | 2 +- lib/stdlib/test/binary_module_SUITE.erl | 34 +++++++------- lib/stdlib/test/dict_SUITE.erl | 16 +++---- lib/stdlib/test/ets_SUITE.erl | 80 ++++++++++++++++----------------- lib/stdlib/test/ets_tough_SUITE.erl | 10 ++--- lib/stdlib/test/filelib_SUITE.erl | 2 +- lib/stdlib/test/lists_SUITE.erl | 22 +++------ lib/stdlib/test/queue_SUITE.erl | 10 ++--- lib/stdlib/test/random_iolist.erl | 16 +++---- lib/stdlib/test/random_unicode_list.erl | 18 ++++---- lib/stdlib/test/run_pcre_tests.erl | 10 ++--- lib/stdlib/test/select_SUITE.erl | 21 +++++---- lib/stdlib/test/sets_SUITE.erl | 22 ++++----- lib/stdlib/test/timer_SUITE.erl | 24 +++++----- 14 files changed, 134 insertions(+), 153 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl index 75eebba6c6..f750145ef0 100644 --- a/lib/stdlib/test/base64_SUITE.erl +++ b/lib/stdlib/test/base64_SUITE.erl @@ -340,7 +340,7 @@ interleaved_ws_roundtrip_1([], Base64List, Bin, List) -> random_byte_list(0, Acc) -> Acc; random_byte_list(N, Acc) -> - random_byte_list(N-1, [random:uniform(255)|Acc]). + random_byte_list(N-1, [rand:uniform(255)|Acc]). make_big_binary(N) -> list_to_binary(mbb(N, [])). diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl index 933c3ce5a9..8a2df2bf85 100644 --- a/lib/stdlib/test/binary_module_SUITE.erl +++ b/lib/stdlib/test/binary_module_SUITE.erl @@ -716,7 +716,7 @@ do_interesting(Module) -> encode_decode(doc) -> ["test binary:encode_unsigned/1,2 and binary:decode_unsigned/1,2"]; encode_decode(Config) when is_list(Config) -> - ?line random:seed({1271,769940,559934}), + rand:seed(exsplus, {1271,769940,559934}), ?line ok = encode_decode_loop({1,200},1000), % Need to be long enough % to create offheap binaries ok. @@ -823,7 +823,7 @@ copy(Config) when is_list(Config) -> ?line badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>, 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), ?line <<>> = binary:copy(<<>>,10000), - ?line random:seed({1271,769940,559934}), + rand:seed(exsplus, {1271,769940,559934}), ?line ok = random_copy(3000), ?line erts_debug:set_internal_state(available_internal_state,true), ?line io:format("oldlimit: ~p~n", @@ -861,7 +861,7 @@ random_copy(0) -> ok; random_copy(N) -> Str = random_string({0,N}), - Num = random:uniform(N div 10+1), + Num = rand:uniform(N div 10+1), A = ?MASK_ERROR(binary:copy(Str,Num)), B = ?MASK_ERROR(binref:copy(Str,Num)), C = ?MASK_ERROR(binary:copy(make_unaligned(Str),Num)), @@ -902,7 +902,7 @@ bin_to_list(Config) when is_list(Config) -> ?line [5] = lists:nthtail(byte_size(X)-1,LX), ?line [0,5] = lists:nthtail(byte_size(X)-2,LX), ?line [0,5] = lists:nthtail(byte_size(Y)-2,LY), - ?line random:seed({1271,769940,559934}), + rand:seed(exsplus, {1271,769940,559934}), ?line ok = random_bin_to_list(5000), ok. @@ -969,7 +969,7 @@ parts(Config) when is_list(Config) -> ?line badarg = ?MASK_ERROR(binary:part(Simple,{-1,0})), ?line badarg = ?MASK_ERROR(binary:part(Simple,{7,2})), ?line <<8>> = binary:part(Simple,{7,1}), - ?line random:seed({1271,769940,559934}), + rand:seed(exsplus, {1271,769940,559934}), ?line random_parts(5000), ok. @@ -993,15 +993,15 @@ random_parts(N) -> random_parts(0,_) -> []; random_parts(X,N) -> - Pos = random:uniform(N), - Len = random:uniform((Pos * 12) div 10), + Pos = rand:uniform(N), + Len = rand:uniform((Pos * 12) div 10), [{Pos,Len} | random_parts(X-1,N)]. random_ref_comp(doc) -> ["Test pseudorandomly generated cases against reference imlementation"]; random_ref_comp(Config) when is_list(Config) -> put(success_counter,0), - random:seed({1271,769940,559934}), + rand:seed(exsplus, {1271,769940,559934}), Nr = {1,40}, Hr = {30,1000}, I1 = 1500, @@ -1031,7 +1031,7 @@ random_ref_sr_comp(doc) -> ["Test pseudorandomly generated cases against reference imlementation of split and replace"]; random_ref_sr_comp(Config) when is_list(Config) -> put(success_counter,0), - random:seed({1271,769940,559934}), + rand:seed(exsplus, {1271,769940,559934}), Nr = {1,40}, Hr = {30,1000}, I1 = 1500, @@ -1049,7 +1049,7 @@ random_ref_fla_comp(doc) -> ["Test pseudorandomly generated cases against reference imlementation of split and replace"]; random_ref_fla_comp(Config) when is_list(Config) -> ?line put(success_counter,0), - ?line random:seed({1271,769940,559934}), + rand:seed(exsplus, {1271,769940,559934}), ?line do_random_first_comp(5000,{1,1000}), ?line do_random_last_comp(5000,{1,1000}), ?line do_random_at_comp(5000,{1,1000}), @@ -1383,24 +1383,24 @@ one_random(N) -> random_number({Min,Max}) -> % Min and Max are *length* of number in % decimal positions - X = random:uniform(Max - Min + 1) + Min - 1, - list_to_integer([one_random_number(random:uniform(10)) || _ <- lists:seq(1,X)]). + X = rand:uniform(Max - Min + 1) + Min - 1, + list_to_integer([one_random_number(rand:uniform(10)) || _ <- lists:seq(1,X)]). random_length({Min,Max}) -> - random:uniform(Max - Min + 1) + Min - 1. + rand:uniform(Max - Min + 1) + Min - 1. random_string({Min,Max}) -> - X = random:uniform(Max - Min + 1) + Min - 1, - list_to_binary([one_random(random:uniform(68)) || _ <- lists:seq(1,X)]). + X = rand:uniform(Max - Min + 1) + Min - 1, + list_to_binary([one_random(rand:uniform(68)) || _ <- lists:seq(1,X)]). random_substring({Min,Max},Hay) -> - X = random:uniform(Max - Min + 1) + Min - 1, + X = rand:uniform(Max - Min + 1) + Min - 1, Y = byte_size(Hay), Z = if X > Y -> Y; true -> X end, PMax = Y - Z, - Pos = random:uniform(PMax + 1) - 1, + Pos = rand:uniform(PMax + 1) - 1, <<_:Pos/binary,Res:Z/binary,_/binary>> = Hay, Res. diff --git a/lib/stdlib/test/dict_SUITE.erl b/lib/stdlib/test/dict_SUITE.erl index 648154ebbe..aff73b176d 100644 --- a/lib/stdlib/test/dict_SUITE.erl +++ b/lib/stdlib/test/dict_SUITE.erl @@ -108,7 +108,7 @@ iterate_1(M) -> M(empty, []). iterate_2(M) -> - random:seed(1, 2, 42), + rand:seed(exsplus, {1,2,42}), iter_tree(M, 1000). iter_tree(_M, 0) -> @@ -117,7 +117,7 @@ iter_tree(M, N) -> L = [{I, I} || I <- lists:seq(1, N)], T = M(from_list, L), L = lists:reverse(iterate_tree(M, T)), - R = random:uniform(N), + R = rand:uniform(N), KV = lists:reverse(iterate_tree_from(M, R, T)), KV = [P || P={K,_} <- L, K >= R], iter_tree(M, N-1). @@ -156,7 +156,7 @@ test_all(Tester) -> spawn_tester(M, Tester) -> Parent = self(), spawn_link(fun() -> - random:seed(1, 2, 42), + rand:seed(exsplus, {1,2,42}), S = Tester(M), Res = {M(size, S),lists:sort(M(to_list, S))}, Parent ! {result,self(),Res} @@ -194,12 +194,12 @@ rnd_list_1(0, Acc) -> Acc; rnd_list_1(N, Acc) -> Key = atomic_rnd_term(), - Value = random:uniform(100), + Value = rand:uniform(100), rnd_list_1(N-1, [{Key,Value}|Acc]). atomic_rnd_term() -> - case random:uniform(3) of - 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd"); - 2 -> random:uniform(); - 3 -> random:uniform(50)-37 + case rand:uniform(3) of + 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd"); + 2 -> rand:uniform(); + 3 -> rand:uniform(50)-37 end. diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 1b80f555d7..3e63d19213 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -112,9 +112,8 @@ -define(m(A,B), ?line assert_eq(A,B)). init_per_testcase(Case, Config) -> - Seed = {S1,S2,S3} = random:seed0(), %now(), - random:seed(S1,S2,S3), - io:format("*** SEED: ~p ***\n", [Seed]), + rand:seed(exsplus), + io:format("*** SEED: ~p ***\n", [rand:export_seed()]), start_spawn_logger(), wait_for_test_procs(), %% Ensure previous case cleaned up Dog=test_server:timetrap(test_server:minutes(20)), @@ -1330,7 +1329,7 @@ drop_match() -> ets_match(Tab,Expr) -> - case random:uniform(2) of + case rand:uniform(2) of 1 -> ets:match(Tab,Expr); _ -> @@ -1339,14 +1338,14 @@ ets_match(Tab,Expr) -> match_chunked(Tab,Expr) -> match_chunked_collect(ets:match(Tab,Expr, - random:uniform(1999) + 1)). + rand:uniform(1999) + 1)). match_chunked_collect('$end_of_table') -> []; match_chunked_collect({Results, Continuation}) -> Results ++ match_chunked_collect(ets:match(Continuation)). ets_match_object(Tab,Expr) -> - case random:uniform(2) of + case rand:uniform(2) of 1 -> ets:match_object(Tab,Expr); _ -> @@ -1355,7 +1354,7 @@ ets_match_object(Tab,Expr) -> match_object_chunked(Tab,Expr) -> match_object_chunked_collect(ets:match_object(Tab,Expr, - random:uniform(1999) + 1)). + rand:uniform(1999) + 1)). match_object_chunked_collect('$end_of_table') -> []; match_object_chunked_collect({Results, Continuation}) -> @@ -1367,19 +1366,15 @@ random_test() -> ?line ReadDir = get(where_to_read), ?line WriteDir = get(where_to_write), ?line (catch file:make_dir(WriteDir)), - ?line Seed = case file:consult(filename:join([ReadDir, - "preset_random_seed.txt"])) of - {ok,[X]} -> - X; - _ -> - {A,B,C} = erlang:timestamp(), - random:seed(A,B,C), - get(random_seed) - end, - put(random_seed,Seed), - ?line {ok, F} = file:open(filename:join([WriteDir, - "last_random_seed.txt"]), - [write]), + case file:consult(filename:join([ReadDir,"preset_random_seed.txt"])) of + {ok,[X]} -> + rand:seed(X); + _ -> + rand:seed(exsplus) + end, + Seed = rand:export_seed(), + {ok,F} = file:open(filename:join([WriteDir,"last_random_seed.txt"]), + [write]), io:format(F,"~p. ~n",[Seed]), file:close(F), io:format("Random seed ~p written to ~s, copy to ~s to rerun with " @@ -1401,7 +1396,7 @@ do_random_test() -> end, 5000), ?line io:format("~nData inserted~n"), ?line do_n_times(fun() -> - ?line I = random:uniform(25), + I = rand:uniform(25), ?line Key = create_random_string(I) ++ '_', ?line L1 = ets_match_object(OrdSet,{Key,'_'}), ?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})), @@ -1961,7 +1956,7 @@ evil_update_counter(Config) when is_list(Config) -> gb_sets:module_info(), math:module_info(), ordsets:module_info(), - random:module_info(), + rand:module_info(), repeat_for_opts(evil_update_counter_do). @@ -1995,7 +1990,7 @@ evil_counter(I,Opts) -> 1 -> 16#12345678FFFFFFFF; 2 -> 16#7777777777FFFFFFFF863648726743 end, - Start = Start0 + random:uniform(100000), + Start = Start0 + rand:uniform(100000), ets:insert(T, {dracula,Start}), Iter = 40000, End = Start + Iter, @@ -4645,11 +4640,11 @@ create_random_string(0) -> []; create_random_string(OfLength) -> - C = case random:uniform(2) of + C = case rand:uniform(2) of 1 -> - (random:uniform($Z - $A + 1) - 1) + $A; + (rand:uniform($Z - $A + 1) - 1) + $A; _ -> - (random:uniform($z - $a + 1) - 1) + $a + (rand:uniform($z - $a + 1) - 1) + $a end, [C | create_random_string(OfLength - 1)]. @@ -4660,7 +4655,7 @@ create_random_tuple(OfLength) -> end,create_random_string(OfLength))). create_partly_bound_tuple(OfLength) -> - case random:uniform(2) of + case rand:uniform(2) of 1 -> create_partly_bound_tuple1(OfLength); _ -> @@ -4669,14 +4664,14 @@ create_partly_bound_tuple(OfLength) -> create_partly_bound_tuple1(OfLength) -> T0 = create_random_tuple(OfLength), - I = random:uniform(OfLength), + I = rand:uniform(OfLength), setelement(I,T0,'$1'). set_n_random_elements(T0,0,_,_) -> T0; set_n_random_elements(T0,N,OfLength,GenFun) -> - I = random:uniform(OfLength), + I = rand:uniform(OfLength), What = GenFun(I), case element(I,T0) of What -> @@ -4690,12 +4685,12 @@ make_dollar_atom(I) -> list_to_atom([$$] ++ integer_to_list(I)). create_partly_bound_tuple2(OfLength) -> T0 = create_random_tuple(OfLength), - I = random:uniform(OfLength - 1), + I = rand:uniform(OfLength - 1), set_n_random_elements(T0,I,OfLength,fun make_dollar_atom/1). create_partly_bound_tuple3(OfLength) -> T0 = create_random_tuple(OfLength), - I = random:uniform(OfLength - 1), + I = rand:uniform(OfLength - 1), set_n_random_elements(T0,I,OfLength,fun(_) -> '_' end). do_n_times(_,0) -> @@ -5058,11 +5053,12 @@ meta_wb_do(Opts) -> io:format("Colliding names = ~p\n",[Names]), F = fun(0,_,_) -> ok; - (N,Tabs,Me) -> Name1 = lists:nth(random:uniform(Len),Names), - Name2 = lists:nth(random:uniform(Len),Names), - Op = element(random:uniform(3),OpFuns), - NTabs = Op(Name1, Name2, Tabs, Opts), - Me(N-1,NTabs,Me) + (N,Tabs,Me) -> + Name1 = lists:nth(rand:uniform(Len), Names), + Name2 = lists:nth(rand:uniform(Len), Names), + Op = element(rand:uniform(3),OpFuns), + NTabs = Op(Name1, Name2, Tabs, Opts), + Me(N-1, NTabs, Me) end, F(Len*100, [], F), @@ -5328,7 +5324,7 @@ smp_insert(suite) -> []; smp_insert(Config) when is_list(Config) -> ets_new(smp_insert,[named_table,public,{write_concurrency,true}]), InitF = fun(_) -> ok end, - ExecF = fun(_) -> true = ets:insert(smp_insert,{random:uniform(10000)}) + ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)}) end, FiniF = fun(_) -> ok end, run_workers(InitF,ExecF,FiniF,100000), @@ -5579,10 +5575,10 @@ smp_select_delete(Config) when is_list(Config) -> Zeros = erlang:make_tuple(Mod,0), InitF = fun(_) -> Zeros end, ExecF = fun(Diffs0) -> - case random:uniform(20) of + case rand:uniform(20) of 1 -> Mod = 17, - Eq = random:uniform(Mod) - 1, + Eq = rand:uniform(Mod) - 1, Deleted = ets:select_delete(T, [{{'_', '$1'}, [{'=:=', {'rem', '$1', Mod}, Eq}], @@ -5591,7 +5587,7 @@ smp_select_delete(Config) when is_list(Config) -> element(Eq+1,Diffs0) - Deleted), Diffs1; _ -> - Key = random:uniform(10000), + Key = rand:uniform(10000), Eq = Key rem Mod, ?line case ets:insert_new(T,{Key,Key}) of true -> @@ -5795,7 +5791,7 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) -> N when (N > Exclude) -> N - Exclude end, io:format("smp starting ~p workers\n",[NumOfProcs]), - Seeds = [{ProcN,random:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)], + Seeds = [{ProcN,rand:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)], Parent = self(), Pids = [my_spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end) || Seed <- Seeds], @@ -5806,7 +5802,7 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) -> worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) -> io:format("smp worker ~p, seed=~p~n",[self(),Seed]), - random:seed(Seed,Seed,Seed), + rand:seed(exsplus, {Seed,Seed,Seed}), State1 = InitF([ProcN, NumOfProcs]), State2 = worker_loop(Laps, ExecF, State1), Result = FiniF(State2), diff --git a/lib/stdlib/test/ets_tough_SUITE.erl b/lib/stdlib/test/ets_tough_SUITE.erl index c6f24fc670..8a7f2b1ec2 100644 --- a/lib/stdlib/test/ets_tough_SUITE.erl +++ b/lib/stdlib/test/ets_tough_SUITE.erl @@ -92,7 +92,7 @@ ex1_sub(Config) -> ok. prep(Config) -> - random:seed(), + rand:seed(exsplus), put(dump_ticket,none), DumpDir = filename:join(?config(priv_dir,Config), "ets_tough"), file:make_dir(DumpDir), @@ -221,19 +221,19 @@ random_class() -> random_element(Classes). random_key() -> - random:uniform(8). + rand:uniform(8). random_value() -> - case random:uniform(5) of + case rand:uniform(5) of 1 -> ok; 2 -> {data,random_key()}; 3 -> {foo,bar,random_class()}; - 4 -> random:uniform(1000); + 4 -> rand:uniform(1000); 5 -> {recursive,random_value()} end. random_element(T) -> - I = random:uniform(tuple_size(T)), + I = rand:uniform(tuple_size(T)), element(I,T). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl index 01b798faef..c39ff842ee 100644 --- a/lib/stdlib/test/filelib_SUITE.erl +++ b/lib/stdlib/test/filelib_SUITE.erl @@ -318,7 +318,7 @@ same_lists(Expected0, Actual0, BaseDir) -> mkfiles([H|T], Dir) -> Name = filename:join(Dir, H), - Garbage = [31+random:uniform(95) || _ <- lists:seq(1, random:uniform(1024))], + Garbage = [31+rand:uniform(95) || _ <- lists:seq(1, rand:uniform(1024))], file:write_file(Name, Garbage), [Name|mkfiles(T, Dir)]; mkfiles([], _) -> []. diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index a0f7fd2744..bd68c93779 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -1677,8 +1677,7 @@ check_stab(L, U, S, US, SS) -> %%% Element 3 in the tuple is the position of the tuple in the list. biglist(N) -> - {A, B, C} = get_seed(), - random:seed(A, B, C), + rand:seed(exsplus), biglist(N, []). biglist(0, L) -> @@ -1694,8 +1693,7 @@ biglist(N, L) -> %%% No sequence number. ubiglist(N) -> - {A, B, C} = get_seed(), - random:seed(A, B, C), + rand:seed(exsplus), ubiglist(N, []). ubiglist(0, L) -> @@ -1719,8 +1717,7 @@ urandom_tuple(N, I) -> %%% sequence number. bigfunlist(N) -> - {A, B, C} = get_seed(), - random:seed(A, B, C), + rand:seed(exsplus), bigfunlist_1(N). bigfunlist_1(N) when N < 30000 -> % Now (R8) max 32000 different pids. @@ -1754,21 +1751,13 @@ make_fun(Pid) -> fun_pid(Fun) -> erlang:fun_info(Fun, pid). -get_seed() -> - case random:seed() of - undefined -> - erlang:timestamp(); - Tuple -> - Tuple - end. - random_tuple(N, Seq) -> R1 = randint(N), R2 = randint(N), {R1, R2, Seq}. randint(N) -> - trunc(random:uniform() * N). + trunc(rand:uniform() * N). %% The first "duplicate" is kept. no_dups([]) -> @@ -1830,8 +1819,7 @@ sort_loop_1(Pid) -> end. sloop(N) -> - {A, B, C} = get_seed(), - random:seed(A, B, C), + rand:seed(exsplus), sloop(N, #state{}). sloop(N, S) -> diff --git a/lib/stdlib/test/queue_SUITE.erl b/lib/stdlib/test/queue_SUITE.erl index c965a8b218..5165ac3a3a 100644 --- a/lib/stdlib/test/queue_SUITE.erl +++ b/lib/stdlib/test/queue_SUITE.erl @@ -470,7 +470,7 @@ oops(suite) -> oops(Config) when is_list(Config) -> ?line N = 3142, ?line Optab = optab(), - ?line Seed0 = random:seed0(), + ?line Seed0 = rand:seed(exsplus, {1,2,4}), ?line {Is,Seed} = random_list(N, tuple_size(Optab), Seed0, []), ?line io:format("~p ", [Is]), ?line QA = queue:new(), @@ -562,20 +562,20 @@ args([], _, Seed, R) -> args([q|Ts], [Q|Qs]=Qss, Seed, R) -> args(Ts, if Qs =:= [] -> Qss; true -> Qs end, Seed, [Q|R]); args([l|Ts], Qs, Seed0, R) -> - {N,Seed1} = random:uniform_s(17, Seed0), + {N,Seed1} = rand:uniform_s(17, Seed0), {L,Seed} = random_list(N, 4711, Seed1, []), args(Ts, Qs, Seed, [L|R]); args([t|Ts], Qs, Seed0, R) -> - {T,Seed} = random:uniform_s(4711, Seed0), + {T,Seed} = rand:uniform_s(4711, Seed0), args(Ts, Qs, Seed, [T|R]); args([n|Ts], Qs, Seed0, R) -> - {N,Seed} = random:uniform_s(17, Seed0), + {N,Seed} = rand:uniform_s(17, Seed0), args(Ts, Qs, Seed, [N|R]). random_list(0, _, Seed, R) -> {R,Seed}; random_list(N, M, Seed0, R) -> - {X,Seed} = random:uniform_s(M, Seed0), + {X,Seed} = rand:uniform_s(M, Seed0), random_list(N-1, M, Seed, [X|R]). call(Func, As) -> diff --git a/lib/stdlib/test/random_iolist.erl b/lib/stdlib/test/random_iolist.erl index 9a0f034e72..6da7da04de 100644 --- a/lib/stdlib/test/random_iolist.erl +++ b/lib/stdlib/test/random_iolist.erl @@ -36,7 +36,7 @@ run2(Iter,Fun1,Fun2) -> compare2(Iter,Fun1,Fun2). random_byte() -> - random:uniform(256) - 1. + rand:uniform(256) - 1. random_list(0,Acc) -> Acc; @@ -45,7 +45,7 @@ random_list(N,Acc) -> random_binary(N) -> B = list_to_binary(random_list(N,[])), - case {random:uniform(2),size(B)} of + case {rand:uniform(2),size(B)} of {2,M} when M > 1 -> S = M-1, <<_:3,C:S/binary,_:5>> = B, @@ -57,7 +57,7 @@ random_list(N) -> random_list(N,[]). front() -> - case random:uniform(10) of + case rand:uniform(10) of 10 -> false; _ -> @@ -65,7 +65,7 @@ front() -> end. any_type() -> - case random:uniform(10) of + case rand:uniform(10) of 1 -> list; 2 -> @@ -77,7 +77,7 @@ any_type() -> end. tail_type() -> - case random:uniform(5) of + case rand:uniform(5) of 1 -> list; 2 -> @@ -90,9 +90,9 @@ random_length(N) -> UpperLimit = 255, case N of M when M > UpperLimit -> - random:uniform(UpperLimit+1) - 1; + rand:uniform(UpperLimit+1) - 1; _ -> - random:uniform(N+1) - 1 + rand:uniform(N+1) - 1 end. random_iolist(0,Acc) -> @@ -139,7 +139,7 @@ random_iolist(N) -> standard_seed() -> - random:seed(1201,855653,380975). + rand:seed(exsplus, {1201,855653,380975}). do_comp(List,F1,F2) -> X = F1(List), diff --git a/lib/stdlib/test/random_unicode_list.erl b/lib/stdlib/test/random_unicode_list.erl index ecafe42318..3bc86a8430 100644 --- a/lib/stdlib/test/random_unicode_list.erl +++ b/lib/stdlib/test/random_unicode_list.erl @@ -85,7 +85,7 @@ int_to_utf32_little(I) -> id(I) -> I. random_char() -> - case random:uniform(16#10FFFF+1) - 1 of + case rand:uniform(16#10FFFF+1) - 1 of X when X >= 16#D800, X =< 16#DFFF -> random_char(); @@ -116,13 +116,13 @@ random_binary(N,Enc) -> int_to(Enc,X) end, L)), - case {random:uniform(3),size(B)} of + case {rand:uniform(3),size(B)} of {2,M} when M > 1 -> B2 = id(<<1:3,B/binary,1:5>>), <<_:3,C:M/binary,_:5>> = B2, C; {3,M} when M > 1 -> - X = random:uniform(M+1)-1, + X = rand:uniform(M+1)-1, <> = B, [B1,B2]; _ -> @@ -132,7 +132,7 @@ random_list(N) -> random_list(N,[]). front() -> - case random:uniform(10) of + case rand:uniform(10) of 10 -> false; _ -> @@ -140,7 +140,7 @@ front() -> end. any_type() -> - case random:uniform(10) of + case rand:uniform(10) of 1 -> list; 2 -> @@ -152,7 +152,7 @@ any_type() -> end. tail_type() -> - case random:uniform(5) of + case rand:uniform(5) of 1 -> list; 2 -> @@ -165,9 +165,9 @@ random_length(N) -> UpperLimit = 255, case N of M when M > UpperLimit -> - random:uniform(UpperLimit+1) - 1; + rand:uniform(UpperLimit+1) - 1; _ -> - random:uniform(N+1) - 1 + rand:uniform(N+1) - 1 end. random_unicode_list(0,Acc,_Enc) -> @@ -214,7 +214,7 @@ random_unicode_list(N,Enc) -> standard_seed() -> - random:seed(1201,855653,380975). + rand:seed(exsplus, {1201,855653,380975}). do_comp(List,F1,F2) -> X = F1(List), diff --git a/lib/stdlib/test/run_pcre_tests.erl b/lib/stdlib/test/run_pcre_tests.erl index 1fdc777470..b7d1df39b8 100644 --- a/lib/stdlib/test/run_pcre_tests.erl +++ b/lib/stdlib/test/run_pcre_tests.erl @@ -1083,7 +1083,7 @@ dumponesplit(F,{RE,Line,O,TS}) -> %% Generate replacement tests from indatafile, %% you will need perl on the machine gen_repl_test(OneFile) -> - random:seed(1219,687731,62804), + rand:seed(exsplus, {1219,687731,62804}), {ok,Bin} = file:read_file(OneFile), Lines = splitfile(0,Bin,1), Structured = stru(Lines), @@ -1237,15 +1237,15 @@ btr(_) -> ranchar() -> - case random:uniform(10) of + case rand:uniform(10) of 9 -> $&; 10 -> <<"\\1">>; N when N < 5 -> - random:uniform($Z-$A)+$A-1; + rand:uniform($Z-$A)+$A-1; M when M < 9 -> - random:uniform($z-$a)+$a-1 + rand:uniform($z-$a)+$a-1 end. ranstring() -> - iolist_to_binary([ranchar() || _ <- lists:duplicate(random:uniform(20),0) ]). + iolist_to_binary([ranchar() || _ <- lists:duplicate(rand:uniform(20),0) ]). diff --git a/lib/stdlib/test/select_SUITE.erl b/lib/stdlib/test/select_SUITE.erl index ead64ffc75..6796676179 100644 --- a/lib/stdlib/test/select_SUITE.erl +++ b/lib/stdlib/test/select_SUITE.erl @@ -212,11 +212,10 @@ init_random(Config) -> {ok,[X]} -> X; _ -> - {A,B,C} = erlang:timestamp(), - random:seed(A,B,C), - get(random_seed) + rand:seed(exsplus), + rand:export_seed() end, - put(random_seed,Seed), + rand:seed(Seed), {ok, F} = file:open(filename:join([WriteDir, "last_random_seed2.txt"]), [write]), io:format(F,"~p. ~n",[Seed]), @@ -224,11 +223,11 @@ init_random(Config) -> ok. create_random_key(N,Type) -> - gen_key(random:uniform(N),Type). + gen_key(rand:uniform(N),Type). create_pb_key(N,list) -> - X = random:uniform(N), - case random:uniform(4) of + X = rand:uniform(N), + case rand:uniform(4) of 3 -> {[X, X+1, '_'], fun([Z,Z1,P1]) -> [Z,Z1,P1] =:= [X,X+1,P1] end}; 2 -> {[X, '_', '_'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end}; @@ -237,14 +236,14 @@ create_pb_key(N,list) -> _ -> {[X, '$1', '$2'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end} end; create_pb_key(N, tuple) -> - X = random:uniform(N), - case random:uniform(2) of + X = rand:uniform(N), + case rand:uniform(2) of 1 -> {{X, X+1, '$1'},fun({Z,Z1,P1}) -> {Z,Z1,P1} =:= {X,X+1,P1} end}; _ -> {{X, '$1', '$2'},fun({Z,P1,P2}) -> {Z,P1,P2} =:= {X,P1,P2} end} end; create_pb_key(N, complex) -> - X = random:uniform(N), - case random:uniform(2) of + X = rand:uniform(N), + case rand:uniform(2) of 1 -> {{[X, X+1], '$1'}, fun({[Z,Z1],P1}) -> {[Z,Z1],P1} =:= {[X,X+1],P1} end}; _ -> {{[X, '$1'], '$2'},fun({[Z,P1],P2}) -> diff --git a/lib/stdlib/test/sets_SUITE.erl b/lib/stdlib/test/sets_SUITE.erl index 972a812072..e7fc5595a9 100644 --- a/lib/stdlib/test/sets_SUITE.erl +++ b/lib/stdlib/test/sets_SUITE.erl @@ -107,9 +107,9 @@ add_element_del([H|T], M, S, Del, []) -> add_element_del(T, M, M(add_element, {H,S}), Del, [H]); add_element_del([H|T], M, S0, Del, Inserted) -> S1 = M(add_element, {H,S0}), - case random:uniform(3) of + case rand:uniform(3) of 1 -> - OldEl = lists:nth(random:uniform(length(Inserted)), Inserted), + OldEl = lists:nth(rand:uniform(length(Inserted)), Inserted), S = M(del_element, {OldEl,S1}), add_element_del(T, M, S, [OldEl|Del], [H|Inserted]); _ -> @@ -438,7 +438,7 @@ iterate_1(M) -> M(empty, []). iterate_2(M) -> - random:seed(1, 2, 42), + rand:seed(exsplus, {1,2,42}), iter_set(M, 1000). iter_set(_M, 0) -> @@ -447,7 +447,7 @@ iter_set(M, N) -> L = [I || I <- lists:seq(1, N)], T = M(from_list, L), L = lists:reverse(iterate_set(M, T)), - R = random:uniform(N), + R = rand:uniform(N), S = lists:reverse(iterate_set(M, R, T)), S = [E || E <- L, E >= R], iter_set(M, N-1). @@ -481,7 +481,7 @@ sets_mods() -> test_all(Tester) -> Res = [begin - random:seed(1, 2, 42), + rand:seed(exsplus, {1,2,42}), S = Tester(M), {M(size, S),lists:sort(M(to_list, S))} end || M <- sets_mods()], @@ -492,7 +492,7 @@ test_all([{Low,High}|T], Tester) -> test_all([Sz|T], Tester) when is_integer(Sz) -> List = rnd_list(Sz), Res = [begin - random:seed(19, 2, Sz), + rand:seed(exsplus, {19,2,Sz}), S = Tester(List, M), {M(size, S),lists:sort(M(to_list, S))} end || M <- sets_mods()], @@ -512,10 +512,10 @@ rnd_list(Sz) -> rnd_list_1(Sz, []). atomic_rnd_term() -> - case random:uniform(3) of - 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd"); - 2 -> random:uniform(); - 3 -> random:uniform(50)-37 + case rand:uniform(3) of + 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd"); + 2 -> rand:uniform(); + 3 -> rand:uniform(50)-37 end. rnd_list_1(0, Acc) -> Acc; @@ -543,7 +543,7 @@ remove_some(List0, P) -> end. remove_some([H|T], P, Acc) -> - case random:uniform() of + case rand:uniform() of F when F < P -> %Remove. remove_some(T, P, Acc); _ -> diff --git a/lib/stdlib/test/timer_SUITE.erl b/lib/stdlib/test/timer_SUITE.erl index 057d82fb65..10dcfad76f 100644 --- a/lib/stdlib/test/timer_SUITE.erl +++ b/lib/stdlib/test/timer_SUITE.erl @@ -80,8 +80,6 @@ report_result(Error) -> ?line test_server:fail(Error). big_test(N) -> C = start_collect(), system_time(), system_time(), system_time(), - random:seed(erlang:timestamp()), - random:uniform(100),random:uniform(100),random:uniform(100), big_loop(C, N, []), @@ -127,17 +125,17 @@ big_loop(C, N, Pids) -> after 0 -> %% maybe start an interval timer test - Pids1 = maybe_start_i_test(Pids, C, random:uniform(4)), + Pids1 = maybe_start_i_test(Pids, C, rand:uniform(4)), %% start 1-4 "after" tests - Pids2 = start_after_test(Pids1, C, random:uniform(4)), + Pids2 = start_after_test(Pids1, C, rand:uniform(4)), %%Pids2=Pids1, %% wait a little while - timer:sleep(random:uniform(200)*3), + timer:sleep(rand:uniform(200)*3), %% spawn zero, one or two nrev to get some load ;-/ - Pids3 = start_nrev(Pids2, random:uniform(100)), + Pids3 = start_nrev(Pids2, rand:uniform(100)), big_loop(C, N-1, Pids3) end. @@ -148,20 +146,20 @@ start_nrev(Pids, N) when N < 25 -> start_nrev(Pids, N) when N < 75 -> [spawn_link(timer_SUITE, do_nrev, [1])|Pids]; start_nrev(Pids, _N) -> - NrevPid1 = spawn_link(timer_SUITE, do_nrev, [random:uniform(1000)*10]), + NrevPid1 = spawn_link(timer_SUITE, do_nrev, [rand:uniform(1000)*10]), NrevPid2 = spawn_link(timer_SUITE, do_nrev, [1]), [NrevPid1,NrevPid2|Pids]. start_after_test(Pids, C, 1) -> - TO1 = random:uniform(100)*47, + TO1 = rand:uniform(100)*47, [s_a_t(C, TO1)|Pids]; start_after_test(Pids, C, 2) -> - TO1 = random:uniform(100)*47, - TO2 = TO1 div random:uniform(3) + 101, + TO1 = rand:uniform(100)*47, + TO2 = TO1 div rand:uniform(3) + 101, [s_a_t(C, TO1),s_a_t(C, TO2)|Pids]; start_after_test(Pids, C, N) -> - TO1 = random:uniform(100)*47, + TO1 = rand:uniform(100)*47, start_after_test([s_a_t(C, TO1)|Pids], C, N-1). s_a_t(C, TimeOut) -> @@ -187,8 +185,8 @@ a_t(C, TimeOut) -> maybe_start_i_test(Pids, C, 1) -> %% ok do it - TOI = random:uniform(53)*49, - CountI = random:uniform(10) + 3, % at least 4 times + TOI = rand:uniform(53)*49, + CountI = rand:uniform(10) + 3, % at least 4 times [spawn_link(timer_SUITE, i_t, [C, TOI, CountI])|Pids]; maybe_start_i_test(Pids, _C, _) -> Pids. -- cgit v1.2.3 From 9e12af42b3e71df8d812eca96d5f1e0a3c65e4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Dec 2015 12:46:52 +0100 Subject: wx: Replace 'random' with 'rand' --- lib/wx/examples/demo/ex_canvas.erl | 2 +- lib/wx/examples/sudoku/sudoku_game.erl | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl index cdc783055c..acc94743d6 100644 --- a/lib/wx/examples/demo/ex_canvas.erl +++ b/lib/wx/examples/demo/ex_canvas.erl @@ -219,4 +219,4 @@ redraw(DC, Bitmap) -> wxMemoryDC:destroy(MemoryDC). get_pos(W,H) -> - {random:uniform(W), random:uniform(H)}. + {rand:uniform(W), rand:uniform(H)}. diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl index e3c39b4ec9..8bb5fe4d38 100644 --- a/lib/wx/examples/sudoku/sudoku_game.erl +++ b/lib/wx/examples/sudoku/sudoku_game.erl @@ -151,8 +151,7 @@ test() -> %% Known to solvable {{9,2},4}, {{9,4},5}, {{9,6},8}, {{9,8},7}]. new_game(S) -> - {X,Y,Z} = erlang:now(), - random:seed(Y,X,Z), + rand:seed(exsplus), case new_game(1,1,gb_sets:empty(),empty_table(S#s{}),[], 0) of stop -> new_game(S); Game -> Game @@ -171,7 +170,7 @@ new_game(R,C,BT,St,Acc,Cnt) when R < 10, C < 10 -> [{{BR,BC},BVal,BBT,BST}|BAcc] = Acc, new_game(BR,BC,gb_sets:add(BVal,BBT),BST,BAcc,Cnt+1); Size -> - Ind = random:uniform(Size), + Ind = rand:uniform(Size), V = lists:nth(Ind,gb_sets:to_list(S)), new_game(R,C+1,gb_sets:empty(), add({R,C,M},V,St), @@ -207,7 +206,7 @@ pick_shown(Given,Left,S0,Level,Gfx) -> io:format("Below level ~p ~p~n", [GivenSz,Level]), S0; true -> - Ran = random:uniform(LeftSz), + Ran = rand:uniform(LeftSz), V = lists:nth(Ran,gb_sets:to_list(Left)), S1 = rebuild_all(rcm(V),S0#s{v=setelement(V,S0#s.v,0)}), case solve(S1, true) of -- cgit v1.2.3 From 004456821045f0bc158db402fecdb637ccde80ca Mon Sep 17 00:00:00 2001 From: Yuki Ito Date: Fri, 23 Oct 2015 19:07:29 +0900 Subject: Use EVP for AES-GCM This enables the use of hardware acceleration on newer Intel CPUs (AES-NI). --- lib/crypto/c_src/crypto.c | 98 +++++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index bb2771163d..b9684168ba 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -1620,44 +1620,62 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key,Iv,AAD,In) */ #if defined(HAVE_GCM) - GCM128_CONTEXT *ctx = NULL; + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in; - AES_KEY aes_key; - unsigned char *outp; + unsigned char *outp, *tagp; ERL_NIF_TERM out, out_tag; + int len; if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 + || (key.size != 16 && key.size != 24 && key.size != 32) || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || !enif_inspect_iolist_as_binary(env, argv[2], &aad) || !enif_inspect_iolist_as_binary(env, argv[3], &in)) { return enif_make_badarg(env); } - if (!(ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt))) - return atom_error; + if (key.size == 16) + cipher = EVP_aes_128_gcm(); + else if (key.size == 24) + cipher = EVP_aes_192_gcm(); + else if (key.size == 32) + cipher = EVP_aes_256_gcm(); - CRYPTO_gcm128_setiv(ctx, iv.data, iv.size); + if (!(ctx = EVP_CIPHER_CTX_new())) + return atom_error; + if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) + goto out_err; - if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size)) - goto out_err; + EVP_CIPHER_CTX_set_padding(ctx, 0); + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) + goto out_err; + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) + goto out_err; + if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) + goto out_err; outp = enif_make_new_binary(env, in.size, &out); - /* encrypt */ - if (CRYPTO_gcm128_encrypt(ctx, in.data, outp, in.size)) - goto out_err; + if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) + goto out_err; + if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1) + goto out_err; + + tagp = enif_make_new_binary(env, EVP_GCM_TLS_TAG_LEN, &out_tag); - /* calculate the tag */ - CRYPTO_gcm128_tag(ctx, enif_make_new_binary(env, EVP_GCM_TLS_TAG_LEN, &out_tag), EVP_GCM_TLS_TAG_LEN); - CRYPTO_gcm128_release(ctx); + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, tagp) != 1) + goto out_err; + + EVP_CIPHER_CTX_free(ctx); CONSUME_REDS(env, in); return enif_make_tuple2(env, out, out_tag); out_err: - CRYPTO_gcm128_release(ctx); + EVP_CIPHER_CTX_free(ctx); return atom_error; #else @@ -1668,14 +1686,15 @@ out_err: static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key,Iv,AAD,In,Tag) */ #if defined(HAVE_GCM) - GCM128_CONTEXT *ctx; + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in, tag; - AES_KEY aes_key; unsigned char *outp; ERL_NIF_TERM out; + int len; if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 + || (key.size != 16 && key.size != 24 && key.size != 32) || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || !enif_inspect_iolist_as_binary(env, argv[2], &aad) || !enif_inspect_iolist_as_binary(env, argv[3], &in) @@ -1683,32 +1702,43 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM return enif_make_badarg(env); } - if (!(ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt))) - return atom_error; - - CRYPTO_gcm128_setiv(ctx, iv.data, iv.size); - - if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size)) - goto out_err; + if (key.size == 16) + cipher = EVP_aes_128_gcm(); + else if (key.size == 24) + cipher = EVP_aes_192_gcm(); + else if (key.size == 32) + cipher = EVP_aes_256_gcm(); + + if (!(ctx = EVP_CIPHER_CTX_new())) + return atom_error; + if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) + goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) + goto out_err; + if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) + goto out_err; + if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) + goto out_err; outp = enif_make_new_binary(env, in.size, &out); - /* decrypt */ - if (CRYPTO_gcm128_decrypt(ctx, in.data, outp, in.size)) - goto out_err; + if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) + goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag.data) != 1) + goto out_err; + if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) + goto out_err; - /* calculate and check the tag */ - if (CRYPTO_gcm128_finish(ctx, tag.data, EVP_GCM_TLS_TAG_LEN)) - goto out_err; + EVP_CIPHER_CTX_free(ctx); - CRYPTO_gcm128_release(ctx); CONSUME_REDS(env, in); return out; out_err: - CRYPTO_gcm128_release(ctx); + EVP_CIPHER_CTX_free(ctx); return atom_error; + #else return enif_raise_exception(env, atom_notsup); #endif -- cgit v1.2.3 From 91d628d92e49c693e79aee2cafc0032fb84e50a5 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 11 Dec 2015 16:22:06 +0100 Subject: crypto: Optimize AES-GCM cipher to not use dynamic allocation for the EVP_CIPHER_CTX. --- lib/crypto/c_src/crypto.c | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index b9684168ba..9155c928fe 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -1620,7 +1620,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key,Iv,AAD,In) */ #if defined(HAVE_GCM) - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in; unsigned char *outp, *tagp; @@ -1642,40 +1642,40 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM else if (key.size == 32) cipher = EVP_aes_256_gcm(); - if (!(ctx = EVP_CIPHER_CTX_new())) - return atom_error; - if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) + EVP_CIPHER_CTX_init(&ctx); + + if (EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1) goto out_err; - EVP_CIPHER_CTX_set_padding(ctx, 0); + EVP_CIPHER_CTX_set_padding(&ctx, 0); - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) + if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) goto out_err; - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) + if (EVP_EncryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; - if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) + if (EVP_EncryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; outp = enif_make_new_binary(env, in.size, &out); - if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) + if (EVP_EncryptUpdate(&ctx, outp, &len, in.data, in.size) != 1) goto out_err; - if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1) + if (EVP_EncryptFinal_ex(&ctx, outp+len, &len) != 1) goto out_err; tagp = enif_make_new_binary(env, EVP_GCM_TLS_TAG_LEN, &out_tag); - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, tagp) != 1) + if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, tagp) != 1) goto out_err; - EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_CTX_cleanup(&ctx); CONSUME_REDS(env, in); return enif_make_tuple2(env, out, out_tag); out_err: - EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_CTX_cleanup(&ctx); return atom_error; #else @@ -1686,7 +1686,7 @@ out_err: static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key,Iv,AAD,In,Tag) */ #if defined(HAVE_GCM) - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in, tag; unsigned char *outp; @@ -1709,34 +1709,34 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM else if (key.size == 32) cipher = EVP_aes_256_gcm(); - if (!(ctx = EVP_CIPHER_CTX_new())) - return atom_error; - if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) + EVP_CIPHER_CTX_init(&ctx); + + if (EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1) goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) + if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) goto out_err; - if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) + if (EVP_DecryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; - if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) + if (EVP_DecryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; outp = enif_make_new_binary(env, in.size, &out); - if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) + if (EVP_DecryptUpdate(&ctx, outp, &len, in.data, in.size) != 1) goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag.data) != 1) + if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag.data) != 1) goto out_err; - if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) + if (EVP_DecryptFinal_ex(&ctx, outp+len, &len) != 1) goto out_err; - EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_CTX_cleanup(&ctx); CONSUME_REDS(env, in); return out; out_err: - EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_CTX_cleanup(&ctx); return atom_error; #else -- cgit v1.2.3 From d20ffad0455c6b9abf982b16d370e769bd9a8f69 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 11 Dec 2015 16:28:23 +0100 Subject: crypto: Fix potential memory leak in error case for block cipher --- lib/crypto/c_src/crypto.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 9155c928fe..6a41385296 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -1359,6 +1359,7 @@ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM key.data, ivec_size ? ivec.data : NULL, -1) || !EVP_CIPHER_CTX_set_padding(&ctx, 0)) { + EVP_CIPHER_CTX_cleanup(&ctx); return enif_raise_exception(env, atom_notsup); } -- cgit v1.2.3 From 4f13b9838c5f7e182661398418065b09716034f2 Mon Sep 17 00:00:00 2001 From: Andrey Mayorov Date: Fri, 11 Dec 2015 03:23:53 +0300 Subject: ssl: fix hibernate_after with instant or near instant timeouts --- lib/ssl/src/tls_connection.erl | 2 +- lib/ssl/test/ssl_basic_SUITE.erl | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index a468c131ce..b2b85eaf8d 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -212,7 +212,7 @@ hello(Hello = #client_hello{client_version = ClientVersion, client_ecc = {EllipticCurves, EcPointFormats}, negotiated_protocol = Protocol}, ?MODULE) end; -hello(Hello, +hello(Hello = #server_hello{}, #state{connection_states = ConnectionStates0, negotiated_version = ReqVersion, role = client, diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 69972c44ed..05b040a2ab 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -136,6 +136,7 @@ api_tests() -> shutdown_both, shutdown_error, hibernate, + hibernate_right_away, listen_socket, ssl_accept_timeout, ssl_recv_timeout, @@ -2922,6 +2923,43 @@ hibernate(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- + +hibernate_right_away() -> + [{doc,"Check that an SSL connection that is configured to hibernate " + "after 0 or 1 milliseconds hibernates as soon as possible and not " + "crashes"}]. + +hibernate_right_away(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + StartServerOpts = [{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ServerOpts}], + StartClientOpts = [return_socket, + {node, ClientNode}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}], + + Server1 = ssl_test_lib:start_server(StartServerOpts), + Port1 = ssl_test_lib:inet_port(Server1), + {Client1, #sslsocket{}} = ssl_test_lib:start_client(StartClientOpts ++ + [{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]), + ssl_test_lib:close(Server1), + ssl_test_lib:close(Client1), + + Server2 = ssl_test_lib:start_server(StartServerOpts), + Port2 = ssl_test_lib:inet_port(Server2), + {Client2, #sslsocket{}} = ssl_test_lib:start_client(StartClientOpts ++ + [{port, Port2}, {options, [{hibernate_after, 1}|ClientOpts]}]), + ssl_test_lib:close(Server2), + ssl_test_lib:close(Client2). + %%-------------------------------------------------------------------- listen_socket() -> [{doc,"Check error handling and inet compliance when calling API functions with listen sockets."}]. -- cgit v1.2.3 From 32eb9d7d9f680d320f42186de67db65688cdd53f Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 11 Dec 2015 18:07:47 +0100 Subject: crypto: Support 192-bit keys for AES CBC and deprecate aes_cbc128 and aes_cbc256 in favor of aes_cbc. This commit is pr 832 squashed, rebased and made work on master https://github.com/erlang/otp/pull/832/commits --- lib/crypto/c_src/crypto.c | 4 +++ lib/crypto/doc/src/crypto.xml | 10 +++--- lib/crypto/src/crypto.erl | 4 +++ lib/crypto/test/crypto_SUITE.erl | 76 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index bb2771163d..850d5bc31f 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -447,6 +447,9 @@ struct cipher_type_t cipher_types[] = {"blowfish_cfb64", &EVP_bf_cfb64}, {"blowfish_ofb64", &EVP_bf_ofb}, {"blowfish_ecb", &EVP_bf_ecb}, + {"aes_cbc", &EVP_aes_128_cbc, 16}, + {"aes_cbc", &EVP_aes_192_cbc, 24}, + {"aes_cbc", &EVP_aes_256_cbc, 32}, {"aes_cbc128", &EVP_aes_128_cbc}, {"aes_cbc256", &EVP_aes_256_cbc}, {"aes_cfb8", &EVP_aes_128_cfb8}, @@ -757,6 +760,7 @@ static void init_algorithms_types(ErlNifEnv* env) #ifdef HAVE_DES_ede3_cfb_encrypt algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbf"); #endif + algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc128"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128"); diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 563a090e98..d3e827b3e6 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -135,9 +135,8 @@ stream_cipher() = rc4 | aes_ctr - block_cipher() = aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc | - blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf - | des_ede3 | rc2_cbc + block_cipher() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc | + blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | rc2_cbc aead_cipher() = aes_gcm | chacha20_poly1305 @@ -160,8 +159,9 @@ hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512

md4 is also supported for hash_init/1 and hash/2. Note that both md4 and md5 are recommended only for compatibility with existing applications.

- cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | - blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128| aes_cbc256 | aes_ige256 | aes_gcm | chacha20_poly1305 | rc2_cbc | aes_ctr| rc4 + cipher_algorithms() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ctr | aes_gcm | + aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20_poly1305 | des_cbc | des_cfb | + des3_cbc | des3_cbf | des_ede3 | rc2_cbc | rc4 public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m

Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported with ecdsa and ecdh. diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 8722e801a6..3e24ff2b0a 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -274,6 +274,7 @@ hmac_final_n(Context, HashLen) -> des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 | + aes_cbc | rc2_cbc, Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(); (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()}. @@ -287,6 +288,7 @@ block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc; Type =:= aes_cfb8; Type =:= aes_cfb128; Type =:= aes_cbc256; + Type =:= aes_cbc; Type =:= rc2_cbc -> block_crypt_nif(Type, Key, Ivec, Data, true); block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc; @@ -307,6 +309,7 @@ block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) -> des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 | + aes_cbc | rc2_cbc, Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(); (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), @@ -316,6 +319,7 @@ block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc; Type =:= blowfish_cbc; Type =:= blowfish_cfb64; Type =:= blowfish_ofb64; + Type =:= aes_cbc; Type =:= aes_cbc128; Type =:= aes_cfb8; Type =:= aes_cfb128; diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 0b955c0965..70cf801516 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -66,6 +66,7 @@ all() -> {group, aes_ctr}, {group, aes_gcm}, {group, chacha20_poly1305}, + {group, aes_cbc}, mod_pow, exor, rand_uniform @@ -107,7 +108,8 @@ groups() -> {rc4, [], [stream]}, {aes_ctr, [], [stream]}, {aes_gcm, [], [aead]}, - {chacha20_poly1305, [], [aead]} + {chacha20_poly1305, [], [aead]}, + {aes_cbc, [], [block]} ]. %%------------------------------------------------------------------- @@ -363,6 +365,21 @@ block_cipher({Type, Key, IV, PlainText}) -> ok; Other -> ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other}}) + end; + +block_cipher({Type, Key, IV, PlainText, CipherText}) -> + Plain = iolist_to_binary(PlainText), + case crypto:block_encrypt(Type, Key, IV, Plain) of + CipherText -> + ok; + Other0 -> + ct:fail({{crypto, block_encrypt, [Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}}) + end, + case crypto:block_decrypt(Type, Key, IV, CipherText) of + Plain -> + ok; + Other1 -> + ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other1}}) end. block_cipher_increment({Type, Key, IV, PlainTexts}) when Type == des_cbc; @@ -370,7 +387,11 @@ block_cipher_increment({Type, Key, IV, PlainTexts}) when Type == des_cbc; Type == aes_cbc; Type == des_cbf -> - block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []); + block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []); +block_cipher_increment({Type, Key, IV, PlainTexts, _CipherText}) when Type == aes_cbc -> + Plain = iolist_to_binary(PlainTexts), + Blocks = [iolistify(Block) || << Block:128/bitstring >> <= Plain], + block_cipher_increment(Type, Key, IV, IV, Blocks, Plain, []); block_cipher_increment({_Type, _, _, _}) -> ok; block_cipher_increment({_,_,_}) -> @@ -552,7 +573,9 @@ do_block_iolistify({des_ede3 = Type, Key, IV, PlainText}) -> do_block_iolistify({Type, Key, PlainText}) -> {Type, iolistify(Key), iolistify(PlainText)}; do_block_iolistify({Type, Key, IV, PlainText}) -> - {Type, iolistify(Key), IV, iolistify(PlainText)}. + {Type, iolistify(Key), IV, iolistify(PlainText)}; +do_block_iolistify({Type, Key, IV, PlainText, CipherText}) -> + {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}. iolistify(<<"Test With Truncation">>)-> %% Do not iolistify as it spoils this special case @@ -803,6 +826,9 @@ group_config(aes_gcm, Config) -> group_config(chacha20_poly1305, Config) -> AEAD = chacha20_poly1305(), [{aead, AEAD} | Config]; +group_config(aes_cbc, Config) -> + Block = aes_cbc(), + [{block, Block} | Config]; group_config(_, Config) -> Config. @@ -1166,6 +1192,50 @@ rc2_cbc() -> <<72,91,135,182,25,42,35,210>>, <<36,245,206,158,168,230,58,69,148,137,32,192,250,41,237,181,181,251, 192,2,175,135,177,171,57,30,111,117,159,149,15,28,88,158,28,81,28,115, 85,219,241,82,117,222,91,85,73,117,164,25,182,52,191,64,123,57,26,19, 211,27,253,31,194,219,231,104,247,240,172,130,119,21,225,154,101,247, 32,216,42,216,133,169,78,22,97,27,227,26,196,224,172,168,17,9,148,55, 203,91,252,40,61,226,236,221,215,160,78,63,13,181,68,57,196,241,185, 207, 116,129,152,237,60,139,247,153,27,146,161,246,222,98,185,222,152, 187,135, 236,86,34,7,110,91,230,173,34,160,242,202,222,121,127,181,140, 101,203,195, 190,88,250,86,147,127,87,72,126,171,16,71,47,110,248,88, 14,29,143,161,152, 129,236,148,22,152,186,208,119,70,8,174,193,203,100, 193,203,200,117,102,242, 134,142,96,125,135,200,217,190,76,117,50,70, 209,186,101,241,200,91,40,193,54, 90,195,38,47,59,197,38,234,86,223,16, 51,253,204,129,20,171,66,21,241,26,135,216, 196,114,110,91,15,53,40, 164,201,136,113,95,247,51,181,208,241,68,168,98,151,36, 155,72,24,57, 42,191,14,125,204,10,167,214,233,138,115,125,234,121,134,227,26,247, 77,200,117,110,117,111,168,156,206,67,159,149,189,173,150,193,91,199, 216,153,22, 189,137,185,89,160,13,131,132,58,109,28,110,246,252,251,14, 232,91,38,52,29,101,188,69,123,50,0,130,178,93,73,239,118,7,77,35,59, 253,10,159,45,86,142,37,78,232,48>> }]. + +%% AES CBC test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +aes_cbc() -> + [ + %% F.2.1 CBC-AES128.Encrypt, F.2.2 CBC-AES128.Decrypt + {aes_cbc, + hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), %% Key + hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"), + hexstr2bin("7649abac8119b246cee98e9b12e9197d" %% CipherText + "5086cb9b507219ee95db113a917678b2" + "73bed6b8e3c1743b7116e69e22229516" + "3ff1caa1681fac09120eca307586e1a7")}, + %% F.2.3 CBC-AES192.Encrypt, F.2.4 CBC-AES192.Decrypt + {aes_cbc, + hexstr2bin("8e73b0f7da0e6452c810f32b809079e5" %% Key + "62f8ead2522c6b7b"), + hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"), + hexstr2bin("4f021db243bc633d7178183a9fa071e8" %% CipherText + "b4d9ada9ad7dedf4e5e738763f69145a" + "571b242012fb7ae07fa9baac3df102e0" + "08b0e27988598881d920a9e64f5615cd")}, + %% F.2.5 CBC-AES256.Encrypt, F.2.6 CBC-AES256.Decrypt + {aes_cbc, + hexstr2bin("603deb1015ca71be2b73aef0857d7781" %% Key + "1f352c073b6108d72d9810a30914dff4"), + hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"), + hexstr2bin("f58c4c04d6e5f1ba779eabfb5f7bfbd6" %% CipherText + "9cfc4e967edb808d679f777bc6702c7d" + "39f23369a9d9bacfa530e26304231461" + "b2eb05e2c39be9fcda6c19078c6a9d1b")} + ]. + aes_cbc128() -> [{aes_cbc128, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), -- cgit v1.2.3 From dc5fa98e2ce79e072a748142e1f5911f926f93fc Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Sat, 12 Dec 2015 17:24:36 +0100 Subject: wx: Revert part of 617387025b698c Causes issues on mac and observer --- lib/wx/c_src/wxe_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index c5bad41573..f81d0bbbd9 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -225,9 +225,9 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process) if(driver_monitor_process(port, process, &monitor) == 0) { // Should we be able to handle commands when recursing? probably // fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr); - app->recurse_level += 2; + app->recurse_level++; app->dispatch_cb(wxe_queue, process); - app->recurse_level -= 2; + app->recurse_level--; // fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr); driver_demonitor_process(port, &monitor); } -- cgit v1.2.3 From 798caecb0ea5d19d4d5f011755941dec136e1c31 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 11 Dec 2015 15:13:24 +0100 Subject: ssl: Do not use environment variables in openSSL config file LibreSSL does not allow it. --- lib/ssl/test/make_certs.erl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl index 7215a59823..5eebf773a7 100644 --- a/lib/ssl/test/make_certs.erl +++ b/lib/ssl/test/make_certs.erl @@ -116,16 +116,16 @@ do_append_files([F|Fs], RF) -> do_append_files(Fs, RF). rootCA(Root, Name, C) -> - create_ca_dir(Root, Name, ca_cnf(C#config{commonName = Name})), - create_self_signed_cert(Root, Name, req_cnf(C#config{commonName = Name}), C), + create_ca_dir(Root, Name, ca_cnf(Root, C#config{commonName = Name})), + create_self_signed_cert(Root, Name, req_cnf(Root, C#config{commonName = Name}), C), file:copy(filename:join([Root, Name, "cert.pem"]), filename:join([Root, Name, "cacerts.pem"])), gencrl(Root, Name, C). intermediateCA(Root, CA, ParentCA, C) -> - create_ca_dir(Root, CA, ca_cnf(C#config{commonName = CA})), + create_ca_dir(Root, CA, ca_cnf(Root, C#config{commonName = CA})), CARoot = filename:join([Root, CA]), CnfFile = filename:join([CARoot, "req.cnf"]), - file:write_file(CnfFile, req_cnf(C#config{commonName = CA})), + file:write_file(CnfFile, req_cnf(Root, C#config{commonName = CA})), KeyFile = filename:join([CARoot, "private", "key.pem"]), ReqFile = filename:join([CARoot, "req.pem"]), create_req(Root, CnfFile, KeyFile, ReqFile, C), @@ -147,7 +147,7 @@ enduser(Root, CA, User, C) -> UsrRoot = filename:join([Root, User]), file:make_dir(UsrRoot), CnfFile = filename:join([UsrRoot, "req.cnf"]), - file:write_file(CnfFile, req_cnf(C#config{commonName = User})), + file:write_file(CnfFile, req_cnf(Root, C#config{commonName = User})), KeyFile = filename:join([UsrRoot, "key.pem"]), ReqFile = filename:join([UsrRoot, "req.pem"]), create_req(Root, CnfFile, KeyFile, ReqFile, C), @@ -337,10 +337,10 @@ eval_cmd(Port, Cmd) -> %% Contents of configuration files %% -req_cnf(C) -> +req_cnf(Root, C) -> ["# Purpose: Configuration for requests (end users and CAs)." "\n" - "ROOTDIR = $ENV::ROOTDIR\n" + "ROOTDIR = " ++ Root ++ "\n" "\n" "[req]\n" @@ -371,10 +371,10 @@ req_cnf(C) -> "subjectKeyIdentifier = hash\n" "subjectAltName = email:copy\n"]. -ca_cnf(C = #config{issuing_distribution_point = true}) -> +ca_cnf(Root, C = #config{issuing_distribution_point = true}) -> ["# Purpose: Configuration for CAs.\n" "\n" - "ROOTDIR = $ENV::ROOTDIR\n" + "ROOTDIR = " ++ Root ++ "\n" "default_ca = ca\n" "\n" @@ -450,10 +450,10 @@ ca_cnf(C = #config{issuing_distribution_point = true}) -> "crlDistributionPoints=@crl_section\n" ]; -ca_cnf(C = #config{issuing_distribution_point = false}) -> +ca_cnf(Root, C = #config{issuing_distribution_point = false}) -> ["# Purpose: Configuration for CAs.\n" "\n" - "ROOTDIR = $ENV::ROOTDIR\n" + "ROOTDIR = " ++ Root ++ "\n" "default_ca = ca\n" "\n" -- cgit v1.2.3 From 389834628ef9b199d6ce1ab721a20737acb014d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Dec 2015 13:02:00 +0100 Subject: gs: Remove the contribs directory Some of the games no longer work. For example, when calling cols:start/0, there will be a 'badfun' exception because of an attempt to apply a tuple fun. There are also calls to the deprecated now/0 function and to the deprecated 'random' module. Since the entire gs application is deprecated and scheduled to be removed any release now, there is no need to keep the contribs directory. --- lib/gs/Makefile | 2 +- lib/gs/contribs/Makefile | 32 -- lib/gs/contribs/bonk/Makefile | 109 ----- lib/gs/contribs/bonk/bitmaps/bonkbomb | 66 --- lib/gs/contribs/bonk/bitmaps/bonkface | 66 --- lib/gs/contribs/bonk/bitmaps/bonklogo | 320 -------------- lib/gs/contribs/bonk/bitmaps/bonkmiss | 66 --- lib/gs/contribs/bonk/bitmaps/bonktom | 66 --- lib/gs/contribs/bonk/bitmaps/bonkx | 66 --- lib/gs/contribs/bonk/bitmaps/erl-e | 106 ----- lib/gs/contribs/bonk/bitmaps/erl-text | 106 ----- lib/gs/contribs/bonk/bonk.erl | 584 -------------------------- lib/gs/contribs/bonk/bonk.gif | Bin 196 -> 0 bytes lib/gs/contribs/bonk/bonk.tool | 6 - lib/gs/contribs/bonk/bonk.txt | 30 -- lib/gs/contribs/bonk/bonk_sound.erl | 82 ---- lib/gs/contribs/bonk/bonk_square.erl | 146 ------- lib/gs/contribs/bonk/sounder.erl | 160 ------- lib/gs/contribs/bonk/sounds/bonk.au | Bin 2008 -> 0 bytes lib/gs/contribs/bonk/sounds/damn.au | Bin 3744 -> 0 bytes lib/gs/contribs/bonk/sounds/explosion.au | Bin 7708 -> 0 bytes lib/gs/contribs/bonk/sounds/gameover.au | Bin 5986 -> 0 bytes lib/gs/contribs/bonk/sounds/hehee.au | Bin 3772 -> 0 bytes lib/gs/contribs/bonk/sounds/level.au | Bin 5360 -> 0 bytes lib/gs/contribs/bonk/sounds/missedme.au | Bin 2735 -> 0 bytes lib/gs/contribs/bonk/sounds/music.au | Bin 48072 -> 0 bytes lib/gs/contribs/bonk/sounds/ouch!!!.au | Bin 2342 -> 0 bytes lib/gs/contribs/bonk/sounds/praisejesus.au | Bin 16730 -> 0 bytes lib/gs/contribs/bonk/sounds/trumpet.au | Bin 49332 -> 0 bytes lib/gs/contribs/bonk/sounds/yes.au | Bin 4400 -> 0 bytes lib/gs/contribs/cols/Makefile | 103 ----- lib/gs/contribs/cols/cols.erl | 625 --------------------------- lib/gs/contribs/cols/cols.gif | Bin 185 -> 0 bytes lib/gs/contribs/cols/cols.tool | 5 - lib/gs/contribs/cols/help.gif | Bin 172 -> 0 bytes lib/gs/contribs/cols/highscore.erl | 103 ----- lib/gs/contribs/ebin/.gitignore | 0 lib/gs/contribs/mandel/Makefile | 101 ----- lib/gs/contribs/mandel/mandel.erl | 351 ---------------- lib/gs/contribs/mandel/mandel.gif | Bin 394 -> 0 bytes lib/gs/contribs/mandel/mandel.html | 74 ---- lib/gs/contribs/mandel/mandel.tool | 6 - lib/gs/contribs/othello/Makefile | 101 ----- lib/gs/contribs/othello/othello.erl | 237 ----------- lib/gs/contribs/othello/othello.gif | Bin 148 -> 0 bytes lib/gs/contribs/othello/othello.tool | 6 - lib/gs/contribs/othello/othello_adt.erl | 540 ------------------------ lib/gs/contribs/othello/othello_board.erl | 649 ----------------------------- lib/gs/contribs/othello/priv/marker.bm | 43 -- lib/gs/contribs/othello/priv/square.bm | 43 -- 50 files changed, 1 insertion(+), 4999 deletions(-) delete mode 100644 lib/gs/contribs/Makefile delete mode 100644 lib/gs/contribs/bonk/Makefile delete mode 100644 lib/gs/contribs/bonk/bitmaps/bonkbomb delete mode 100644 lib/gs/contribs/bonk/bitmaps/bonkface delete mode 100644 lib/gs/contribs/bonk/bitmaps/bonklogo delete mode 100644 lib/gs/contribs/bonk/bitmaps/bonkmiss delete mode 100644 lib/gs/contribs/bonk/bitmaps/bonktom delete mode 100644 lib/gs/contribs/bonk/bitmaps/bonkx delete mode 100644 lib/gs/contribs/bonk/bitmaps/erl-e delete mode 100644 lib/gs/contribs/bonk/bitmaps/erl-text delete mode 100644 lib/gs/contribs/bonk/bonk.erl delete mode 100644 lib/gs/contribs/bonk/bonk.gif delete mode 100644 lib/gs/contribs/bonk/bonk.tool delete mode 100644 lib/gs/contribs/bonk/bonk.txt delete mode 100644 lib/gs/contribs/bonk/bonk_sound.erl delete mode 100644 lib/gs/contribs/bonk/bonk_square.erl delete mode 100644 lib/gs/contribs/bonk/sounder.erl delete mode 100644 lib/gs/contribs/bonk/sounds/bonk.au delete mode 100644 lib/gs/contribs/bonk/sounds/damn.au delete mode 100644 lib/gs/contribs/bonk/sounds/explosion.au delete mode 100644 lib/gs/contribs/bonk/sounds/gameover.au delete mode 100644 lib/gs/contribs/bonk/sounds/hehee.au delete mode 100644 lib/gs/contribs/bonk/sounds/level.au delete mode 100644 lib/gs/contribs/bonk/sounds/missedme.au delete mode 100644 lib/gs/contribs/bonk/sounds/music.au delete mode 100644 lib/gs/contribs/bonk/sounds/ouch!!!.au delete mode 100644 lib/gs/contribs/bonk/sounds/praisejesus.au delete mode 100644 lib/gs/contribs/bonk/sounds/trumpet.au delete mode 100644 lib/gs/contribs/bonk/sounds/yes.au delete mode 100644 lib/gs/contribs/cols/Makefile delete mode 100644 lib/gs/contribs/cols/cols.erl delete mode 100644 lib/gs/contribs/cols/cols.gif delete mode 100644 lib/gs/contribs/cols/cols.tool delete mode 100644 lib/gs/contribs/cols/help.gif delete mode 100644 lib/gs/contribs/cols/highscore.erl delete mode 100644 lib/gs/contribs/ebin/.gitignore delete mode 100644 lib/gs/contribs/mandel/Makefile delete mode 100644 lib/gs/contribs/mandel/mandel.erl delete mode 100644 lib/gs/contribs/mandel/mandel.gif delete mode 100644 lib/gs/contribs/mandel/mandel.html delete mode 100644 lib/gs/contribs/mandel/mandel.tool delete mode 100644 lib/gs/contribs/othello/Makefile delete mode 100644 lib/gs/contribs/othello/othello.erl delete mode 100644 lib/gs/contribs/othello/othello.gif delete mode 100644 lib/gs/contribs/othello/othello.tool delete mode 100644 lib/gs/contribs/othello/othello_adt.erl delete mode 100644 lib/gs/contribs/othello/othello_board.erl delete mode 100644 lib/gs/contribs/othello/priv/marker.bm delete mode 100644 lib/gs/contribs/othello/priv/square.bm (limited to 'lib') diff --git a/lib/gs/Makefile b/lib/gs/Makefile index 02c8fc3467..b95d435461 100644 --- a/lib/gs/Makefile +++ b/lib/gs/Makefile @@ -26,7 +26,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # -SUB_DIRECTORIES = src tcl contribs examples doc/src +SUB_DIRECTORIES = src tcl examples doc/src include vsn.mk VSN = $(GS_VSN) diff --git a/lib/gs/contribs/Makefile b/lib/gs/contribs/Makefile deleted file mode 100644 index 061fae86c1..0000000000 --- a/lib/gs/contribs/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2009. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -SUB_DIRECTORIES = bonk cols mandel othello -SPECIAL_TARGETS = - -# -# Default Subdir Targets -# -include $(ERL_TOP)/make/otp_subdir.mk - diff --git a/lib/gs/contribs/bonk/Makefile b/lib/gs/contribs/bonk/Makefile deleted file mode 100644 index b7508a97c9..0000000000 --- a/lib/gs/contribs/bonk/Makefile +++ /dev/null @@ -1,109 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../../vsn.mk -VSN=$(GS_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - bonk \ - bonk_sound \ - bonk_square \ - sounder - -HRL_FILES= -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES) - -BITMAPS= bitmaps/bonkbomb bitmaps/bonkface bitmaps/bonklogo bitmaps/bonkmiss \ - bitmaps/bonktom bitmaps/bonkx bitmaps/erl-e bitmaps/erl-text -SOUNDS= sounds/bonk.au sounds/damn.au sounds/explosion.au sounds/gameover.au \ - sounds/hehee.au sounds/level.au sounds/missedme.au sounds/music.au \ - sounds/ouch!!!.au sounds/praisejesus.au sounds/trumpet.au sounds/yes.au - -TOOLNAME = bonk - -EXTRA_FILES= $(TOOLNAME).txt -TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif -TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) - -docs: - -clean: - rm -f $(TARGET_FILES) - rm -f core - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).gif $@ - -$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).tool $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" - $(INSTALL_DIR) "$(RELSYSDIR)/bonk/bitmaps" - $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/bonk/bitmaps" - $(INSTALL_DIR) "$(RELSYSDIR)/bonk/sounds" - $(INSTALL_DATA) $(SOUNDS) "$(RELSYSDIR)/bonk/sounds" - $(INSTALL_DIR) "$(RELSYSDIR)/bonk" - $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/bonk" - - -release_docs_spec: - diff --git a/lib/gs/contribs/bonk/bitmaps/bonkbomb b/lib/gs/contribs/bonk/bitmaps/bonkbomb deleted file mode 100644 index 8b121db9e8..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/bonkbomb +++ /dev/null @@ -1,66 +0,0 @@ -#define bonkbomb_width 75 -#define bonkbomb_height 75 -static char bonkbomb_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x10, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x21, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x11, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x90, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x51, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x12, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x94, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xbb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x99, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x19, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x62, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, - 0x3b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1f, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xb8, 0x0e, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x5c, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xaf, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, - 0xff, 0x57, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xaf, - 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x5f, 0x1d, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xbf, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, - 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x7f, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x3f, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x0f, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xc0, - 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0xf0, 0xff, 0xff, - 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf8, 0xff, 0xff, 0x07, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, - 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/bonk/bitmaps/bonkface b/lib/gs/contribs/bonk/bitmaps/bonkface deleted file mode 100644 index 964fb93098..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/bonkface +++ /dev/null @@ -1,66 +0,0 @@ -#define bonkface_width 75 -#define bonkface_height 75 -static char bonkface_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x60, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x03, 0x06, 0x00, 0x0f, 0x00, 0x00, - 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x40, - 0xfe, 0x1f, 0x00, 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x20, 0xf8, 0xff, - 0x03, 0xfe, 0xff, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0xff, 0xff, - 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0xff, 0xdf, 0xff, 0x1f, 0x20, - 0x00, 0x00, 0x00, 0x20, 0x00, 0xff, 0xdf, 0xff, 0x07, 0x20, 0x00, 0x00, - 0x00, 0x10, 0x00, 0xfe, 0x8f, 0xff, 0x03, 0x40, 0x00, 0x00, 0x00, 0x10, - 0x00, 0xf8, 0x8f, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xf0, - 0x07, 0x7f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc0, 0x07, 0x1f, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x06, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xe0, - 0x00, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0xf0, 0x01, 0x7c, - 0x40, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x06, 0x03, 0x40, 0x40, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0xf8, 0x00, 0x40, 0x40, 0x00, 0x00, - 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x60, 0x40, 0x00, 0x00, 0x00, 0x10, - 0x70, 0x00, 0x00, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x10, 0xf0, 0x01, - 0x00, 0x00, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x20, 0xf0, 0x0f, 0x00, 0x80, - 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x03, 0xfe, 0x7f, 0x20, - 0x00, 0x00, 0x00, 0x20, 0xf0, 0x7f, 0xfe, 0xff, 0x7f, 0x20, 0x00, 0x00, - 0x00, 0x20, 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x40, - 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x40, 0xc0, 0xff, - 0xff, 0xff, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xff, 0xff, 0xff, - 0x1f, 0x08, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0xff, 0xff, 0x0f, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x07, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xfe, 0xff, 0xff, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xfc, 0xff, 0xfc, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf0, - 0xff, 0x7c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xff, 0x1c, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xff, 0x07, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/bonk/bitmaps/bonklogo b/lib/gs/contribs/bonk/bitmaps/bonklogo deleted file mode 100644 index 3adc59984a..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/bonklogo +++ /dev/null @@ -1,320 +0,0 @@ -#define bonklogo_width 300 -#define bonklogo_height 100 -static char bonklogo_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0x83, 0xff, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0xf8, 0xff, 0x7f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x87, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xf9, 0xff, 0xff, 0xff, 0x13, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x27, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, - 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, - 0xff, 0xff, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, - 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, - 0xff, 0x2f, 0xf8, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xdf, 0xff, 0x2f, 0xf0, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xc3, 0xff, 0x2f, 0xf0, 0xff, 0x09, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xff, 0x2f, 0xe0, 0xff, 0x0b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x80, 0xff, 0x09, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x2f, 0xc0, 0xff, - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, - 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x27, - 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x01, - 0x00, 0xc0, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0xff, 0x17, 0xc0, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x7f, 0x01, 0x00, 0xe0, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xe0, 0xff, 0x17, 0xc0, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x7f, 0x01, 0x00, 0xe0, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xff, 0x3f, 0xe0, 0x7f, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xc0, - 0xff, 0x7f, 0xe0, 0xff, 0x3f, 0xfc, 0x7f, 0x00, 0x20, 0xe0, 0x7f, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, - 0x17, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0xfc, 0x7f, 0xfe, 0x2f, 0xf0, - 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, - 0x80, 0xff, 0x17, 0xe0, 0xff, 0x1f, 0xe1, 0xff, 0x2f, 0xfc, 0x7f, 0xfe, - 0x2f, 0xf0, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, - 0xff, 0x17, 0x80, 0xff, 0x17, 0xf0, 0xff, 0x7f, 0xe6, 0xff, 0x4f, 0xfc, - 0x7f, 0xfe, 0x2f, 0xf0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xf8, 0xff, 0xff, 0xe8, 0xff, - 0x4f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xfe, 0xff, 0xff, - 0xeb, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x9f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xfe, - 0xff, 0xff, 0xe3, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x5f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0xc0, 0xff, - 0x17, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xfc, - 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, - 0xc0, 0xff, 0x93, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, - 0x2f, 0xfc, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, - 0xff, 0x17, 0xc0, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xfc, - 0x7f, 0xfe, 0x2f, 0xfc, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xe0, 0xff, 0x13, 0xe0, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xcf, 0xff, - 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfc, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0b, 0xf2, 0xff, 0xcd, 0xff, 0xff, 0xff, - 0xcf, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe, 0x17, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0b, 0xf9, 0xff, 0xd9, 0xff, - 0xff, 0xff, 0x1f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe, 0x13, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xcb, 0xfc, 0xff, - 0xc0, 0xff, 0x8f, 0xff, 0x1f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x2b, - 0xfe, 0xff, 0x87, 0xff, 0x03, 0xff, 0x3f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, - 0x2f, 0xff, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xff, 0x9b, 0xff, 0xff, 0x3f, 0xff, 0x01, 0xfe, 0x3f, 0xff, 0x3f, 0xfd, - 0x7f, 0xfe, 0x2f, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0xff, 0xc3, 0xff, 0xff, 0x7f, 0xfe, 0x05, 0xfc, 0x3f, 0xff, - 0x7f, 0xfd, 0x7f, 0xfe, 0x2f, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfc, 0x04, 0xfc, - 0x3f, 0xff, 0x7f, 0xfd, 0x7f, 0xfe, 0x2f, 0xff, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfd, 0x7f, 0xfe, 0xaf, 0xff, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfc, 0x7f, 0xfe, 0xaf, 0xff, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf9, 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfc, 0x7f, 0xfe, - 0x8f, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc, - 0x7f, 0xfe, 0xcf, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x02, 0xf8, 0x3f, 0xff, - 0xff, 0xfc, 0x7f, 0xfe, 0xcf, 0x7f, 0x01, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x02, 0xf8, - 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xcf, 0x3f, 0x01, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xf7, - 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xef, 0x3f, 0x01, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x80, 0xff, - 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xef, 0x9f, - 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, - 0x00, 0xff, 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, - 0xef, 0xdf, 0x00, 0x00, 0x00, 0x30, 0xd8, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xff, 0x05, 0x00, 0xff, 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, - 0x7f, 0xfe, 0xef, 0x9f, 0x00, 0x00, 0x00, 0x38, 0xfc, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0x05, 0x00, 0xff, 0xff, 0xef, 0x02, 0xf8, 0x3f, 0xff, - 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x38, 0x7c, 0x0e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xef, 0x02, 0xf8, - 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x38, - 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xef, - 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0x7f, 0x02, 0x00, - 0x00, 0x38, 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfc, - 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0xff, - 0x02, 0x00, 0x00, 0x38, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x04, - 0x00, 0xfc, 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x7f, 0xfe, - 0xff, 0xff, 0x04, 0x00, 0x00, 0xb8, 0x39, 0x2e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xff, - 0x7f, 0xfe, 0xff, 0xff, 0x05, 0x00, 0x00, 0xf0, 0x39, 0x3c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x04, 0xf8, 0x3f, 0xff, - 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x09, 0x00, 0x00, 0xf0, 0x38, 0x1c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x05, 0xf8, - 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x13, 0x00, 0x00, 0x60, - 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, - 0x0d, 0xf8, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x17, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe, - 0xff, 0xcf, 0x09, 0xfd, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, - 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, - 0x00, 0xfe, 0xff, 0xcf, 0xcb, 0xfc, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, - 0xff, 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0x33, 0xfe, 0x3f, 0xff, 0xf9, 0xff, - 0x7f, 0xfe, 0xff, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0x07, 0xff, 0x3f, 0xff, - 0xf9, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0xcf, 0xff, - 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xff, 0x3f, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x40, 0xfe, 0xff, 0xcf, - 0xff, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x3c, 0xff, - 0xff, 0xc7, 0xff, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, - 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x82, - 0x87, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x3f, 0xff, 0xf1, 0xff, 0x7f, 0xfe, - 0x3f, 0xfc, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0xff, 0x72, 0xf0, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x3f, 0xff, 0xf1, 0xff, - 0x7f, 0xfe, 0xbf, 0xf8, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0xff, 0x0e, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x9f, 0xff, - 0xf5, 0xff, 0x7f, 0xfe, 0xbf, 0xf8, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, - 0x9f, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x9f, 0xf0, 0xff, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, - 0xff, 0xff, 0x9f, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x5f, 0xf0, 0xff, 0x13, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf3, 0xff, 0xff, 0xdf, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x4f, 0xe0, - 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xcf, 0xff, 0xe5, 0xff, 0x7f, 0xfe, - 0x2f, 0xe0, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xcf, 0xff, 0xe5, 0xff, - 0x7f, 0xfe, 0x2f, 0xc0, 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xe7, 0xff, - 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0xc0, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, - 0xe7, 0xff, 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0x80, 0xff, 0x9f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, - 0xff, 0xff, 0xf7, 0xff, 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xff, 0x3f, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x1f, 0xfe, 0xff, 0xff, 0xf3, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, - 0xff, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xc5, 0xff, 0x7f, 0xfe, - 0x2f, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x23, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xc5, 0xff, - 0x7f, 0xfe, 0x2f, 0x00, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0xfe, 0xff, 0xff, 0xf5, 0xff, - 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x0c, 0xfc, 0xff, 0xff, - 0xf4, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xfc, 0xff, 0x09, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x02, 0xfc, - 0xff, 0x7f, 0xf2, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xf8, 0xff, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x00, 0xe0, 0xff, 0x3f, 0xf1, 0xff, 0x85, 0xff, 0x7f, 0xfe, 0x2f, 0x00, - 0xf8, 0xff, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, - 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x85, 0xff, 0x7f, 0xfe, - 0x2f, 0x00, 0xf0, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, - 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x85, 0xff, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/bonk/bitmaps/bonkmiss b/lib/gs/contribs/bonk/bitmaps/bonkmiss deleted file mode 100644 index 862e4839fc..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/bonkmiss +++ /dev/null @@ -1,66 +0,0 @@ -#define bonkmiss_width 75 -#define bonkmiss_height 75 -static char bonkmiss_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0x80, 0x19, 0x3c, 0xc0, 0x83, 0xff, 0xf9, 0x01, 0x00, 0x60, 0x80, - 0x19, 0x7e, 0xe0, 0x87, 0xff, 0xf9, 0x03, 0x00, 0xe0, 0xc0, 0x19, 0xe7, - 0x70, 0x8e, 0x01, 0x18, 0x07, 0x00, 0xe0, 0xc0, 0x99, 0xc3, 0x39, 0x9c, - 0x01, 0x18, 0x0e, 0x00, 0xe0, 0xe1, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, - 0x0c, 0x00, 0xe0, 0xe1, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x1c, 0x00, - 0xe0, 0xf3, 0x99, 0x01, 0x18, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0xb3, - 0x99, 0x01, 0x18, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0xb3, 0x99, 0x03, - 0x38, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0x9e, 0x19, 0x07, 0x70, 0x80, - 0x01, 0x18, 0x18, 0x00, 0x60, 0x9e, 0x19, 0x3e, 0xe0, 0x83, 0x1f, 0x18, - 0x18, 0x00, 0x60, 0x8c, 0x19, 0x7c, 0xc0, 0x87, 0x1f, 0x18, 0x18, 0x00, - 0x60, 0x80, 0x19, 0xe0, 0x00, 0x8e, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, - 0x19, 0xc0, 0x01, 0x9c, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80, - 0x01, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80, 0x01, 0x98, - 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80, 0x01, 0x98, 0x01, 0x18, - 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, - 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, - 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, - 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, - 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, - 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x1c, 0x00, - 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x0c, 0x00, 0x60, 0x80, - 0x99, 0xc3, 0x39, 0x9c, 0x01, 0x18, 0x0e, 0x00, 0x60, 0x80, 0x19, 0xe7, - 0x70, 0x8e, 0x01, 0x18, 0x07, 0x00, 0x60, 0x80, 0x19, 0x7e, 0xe0, 0x87, - 0xff, 0xf9, 0x03, 0x00, 0x60, 0x80, 0x19, 0x3c, 0xc0, 0x83, 0xff, 0xf9, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1c, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1c, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, - 0x3c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x3e, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6c, 0x36, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xcc, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, - 0x33, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x31, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0x30, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/bonk/bitmaps/bonktom b/lib/gs/contribs/bonk/bitmaps/bonktom deleted file mode 100644 index defbc32cc9..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/bonktom +++ /dev/null @@ -1,66 +0,0 @@ -#define bonktom_width 75 -#define bonktom_height 75 -static char bonktom_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/bonk/bitmaps/bonkx b/lib/gs/contribs/bonk/bitmaps/bonkx deleted file mode 100644 index 70cd89bdb7..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/bonkx +++ /dev/null @@ -1,66 +0,0 @@ -#define bonkx_width 75 -#define bonkx_height 75 -static char bonkx_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x3e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, - 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xf0, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xe0, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xfe, 0x03, - 0x00, 0xc0, 0x1f, 0x00, 0x80, 0x3f, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0xe0, - 0x0f, 0x00, 0x00, 0x7f, 0x00, 0x18, 0x00, 0xc0, 0x00, 0xf0, 0x07, 0x00, - 0x00, 0xfe, 0x00, 0x06, 0x00, 0x00, 0x03, 0xf8, 0x03, 0x00, 0x00, 0xfc, - 0x81, 0x01, 0x00, 0x00, 0x0c, 0xfc, 0x01, 0x00, 0x00, 0xf8, 0x43, 0x00, - 0x00, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x00, 0xf0, 0x27, 0x00, 0x00, 0x00, - 0x20, 0x7f, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0x3f, - 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, - 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, - 0x00, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x31, 0x00, 0x60, - 0xfc, 0x05, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xc3, 0x00, 0x18, 0xfe, 0x08, - 0x00, 0x00, 0x00, 0x80, 0xf7, 0x07, 0x03, 0x06, 0x7f, 0x0f, 0x00, 0x00, - 0x00, 0x40, 0xff, 0x0f, 0x00, 0x80, 0xff, 0x17, 0x00, 0x00, 0x00, 0x40, - 0xfe, 0x1f, 0x00, 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x20, 0xf8, 0xff, - 0x03, 0xfe, 0xff, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0xff, 0xff, - 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0xff, 0xdf, 0xff, 0x1f, 0x20, - 0x00, 0x00, 0x00, 0x20, 0x00, 0xff, 0xdf, 0xff, 0x07, 0x20, 0x00, 0x00, - 0x00, 0x10, 0x00, 0xfe, 0x8f, 0xff, 0x03, 0x40, 0x00, 0x00, 0x00, 0x10, - 0x00, 0xf8, 0x8f, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xf0, - 0x8f, 0x7f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc0, 0xdf, 0x1f, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0xff, 0x0f, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xff, 0x07, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0xfc, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xe0, - 0xfe, 0x3b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0xf0, 0xff, 0x7f, - 0x40, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x80, 0xff, 0x0f, 0x40, 0x40, - 0x00, 0x00, 0x00, 0x10, 0x10, 0xc0, 0xff, 0x1f, 0x40, 0x40, 0x00, 0x00, - 0x00, 0x10, 0x30, 0xe0, 0x8f, 0x3f, 0x60, 0x40, 0x00, 0x00, 0x00, 0x10, - 0x70, 0xf0, 0x07, 0x7f, 0x70, 0x40, 0x00, 0x00, 0x00, 0x10, 0xf0, 0xf9, - 0x03, 0xfe, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x01, 0xfc, - 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x03, 0xfe, 0x7f, 0x20, - 0x00, 0x00, 0x00, 0x20, 0xf0, 0x7f, 0xfe, 0xff, 0x7f, 0x20, 0x00, 0x00, - 0x00, 0x20, 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x40, - 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x40, 0xe0, 0xff, - 0xff, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xff, 0xff, 0xff, - 0x7f, 0x08, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x08, - 0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0xfc, 0xff, 0xfc, 0xf1, 0x07, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xf0, - 0xff, 0x7c, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xc0, 0xff, 0x1c, - 0xc0, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xff, 0x07, 0xc0, 0x3f, - 0x00, 0x00, 0x00, 0xf0, 0x27, 0x00, 0x00, 0x00, 0x20, 0x7f, 0x00, 0x00, - 0x00, 0xf8, 0x43, 0x00, 0x00, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x00, 0xfc, - 0x81, 0x01, 0x00, 0x00, 0x0c, 0xfc, 0x01, 0x00, 0x00, 0xfe, 0x00, 0x06, - 0x00, 0x00, 0x03, 0xf8, 0x03, 0x00, 0x00, 0x7f, 0x00, 0x18, 0x00, 0xc0, - 0x00, 0xf0, 0x07, 0x00, 0x80, 0x3f, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0xe0, - 0x0f, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xfe, 0x03, 0x00, 0xc0, 0x1f, 0x00, - 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0xf0, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xf8, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, - 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x1e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/bonk/bitmaps/erl-e b/lib/gs/contribs/bonk/bitmaps/erl-e deleted file mode 100644 index 41ad14f404..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/erl-e +++ /dev/null @@ -1,106 +0,0 @@ -#define erl-e_width 108 -#define erl-e_height 88 -static char erl-e_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe0, 0xff, 0xf7, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf7, 0xfc, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x80, 0xff, 0xf7, 0xfc, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf7, - 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, - 0x01, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0xe0, - 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xf7, 0xfc, 0x0f, 0x00, 0x00, - 0x00, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfc, 0xf7, 0xfc, 0x07, - 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xf8, 0xf7, - 0xfc, 0x07, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, - 0xf8, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x00, - 0x00, 0x00, 0xf8, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, - 0x0f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x01, 0x00, 0x00, 0x00, 0xfc, - 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x01, 0x00, 0x00, - 0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7, - 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf7, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xfe, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xc0, 0xff, 0xf7, 0xfc, 0x01, - 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0xf7, - 0xfc, 0x01, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, - 0xf8, 0xf7, 0xfc, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0x03, 0x00, 0xe0, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0xc0, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x80, 0xf7, 0xfc, 0x07, 0x00, 0x00, - 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xf7, 0xfc, 0x07, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x80, 0xf7, - 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x1f, 0x00, 0x00, - 0xc0, 0xf7, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f, - 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0x07, 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x3f, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xf8, 0xf7, 0xfc, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0xfc, 0xf7, - 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfc, 0xf7, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xf7, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xf7, 0xfc, 0xff, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf7, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0}; diff --git a/lib/gs/contribs/bonk/bitmaps/erl-text b/lib/gs/contribs/bonk/bitmaps/erl-text deleted file mode 100644 index e20a9e5a28..0000000000 --- a/lib/gs/contribs/bonk/bitmaps/erl-text +++ /dev/null @@ -1,106 +0,0 @@ -#define erl-text_width 108 -#define erl-text_height 88 -static char erl-text_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xfc, 0x03, 0xf8, 0x00, 0x70, 0x00, 0x80, 0x03, 0x80, 0x03, 0x07, 0x00, - 0x3e, 0xf0, 0xfc, 0x03, 0xf8, 0x03, 0x70, 0x00, 0x80, 0x03, 0x80, 0x07, - 0x07, 0x80, 0xff, 0xf0, 0xfc, 0x03, 0xf8, 0x07, 0x70, 0x00, 0xc0, 0x07, - 0x80, 0x07, 0x07, 0xe0, 0xff, 0xf1, 0x1c, 0x00, 0x38, 0x07, 0x70, 0x00, - 0xc0, 0x07, 0x80, 0x0f, 0x07, 0xe0, 0xc1, 0xf3, 0x1c, 0x00, 0x38, 0x0e, - 0x70, 0x00, 0xe0, 0x0f, 0x80, 0x1f, 0x07, 0xf0, 0x80, 0xf3, 0x1c, 0x00, - 0x38, 0x0f, 0x70, 0x00, 0xe0, 0x0e, 0x80, 0x1f, 0x07, 0x78, 0x00, 0xf0, - 0xfc, 0x03, 0xf8, 0x07, 0x70, 0x00, 0xe0, 0x0e, 0x80, 0x3f, 0x07, 0x78, - 0x00, 0xf0, 0xfc, 0x03, 0xf8, 0x03, 0x70, 0x00, 0x70, 0x1c, 0x80, 0x7b, - 0x07, 0x38, 0x00, 0xf0, 0xfc, 0x03, 0xf8, 0x01, 0x70, 0x00, 0x70, 0x1c, - 0x80, 0xf3, 0x07, 0x38, 0xf8, 0xf7, 0x1c, 0x00, 0xf8, 0x01, 0x70, 0x00, - 0x70, 0x1c, 0x80, 0xe3, 0x07, 0x78, 0xf8, 0xf7, 0x1c, 0x00, 0xf8, 0x03, - 0x70, 0x00, 0xf8, 0x3f, 0x80, 0xe3, 0x07, 0x70, 0x80, 0xf7, 0x1c, 0x00, - 0xb8, 0x03, 0x70, 0x00, 0xf8, 0x3f, 0x80, 0xc3, 0x07, 0xf0, 0x80, 0xf3, - 0xfc, 0x03, 0x38, 0x07, 0xf0, 0x07, 0x38, 0x38, 0x80, 0x83, 0x07, 0xe0, - 0xe3, 0xf3, 0xfc, 0x03, 0x38, 0x07, 0xf0, 0x07, 0x1c, 0x70, 0x80, 0x83, - 0x07, 0xc0, 0xff, 0xf1, 0xfc, 0x03, 0x38, 0x0e, 0xf0, 0x07, 0x1c, 0x70, - 0x80, 0x03, 0x07, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0}; diff --git a/lib/gs/contribs/bonk/bonk.erl b/lib/gs/contribs/bonk/bonk.erl deleted file mode 100644 index bbbc656b34..0000000000 --- a/lib/gs/contribs/bonk/bonk.erl +++ /dev/null @@ -1,584 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(bonk). --compile([{nowarn_deprecated_function,{gs,config,2}}, - {nowarn_deprecated_function,{gs,create,3}}, - {nowarn_deprecated_function,{gs,create,4}}, - {nowarn_deprecated_function,{gs,destroy,1}}, - {nowarn_deprecated_function,{gs,start,0}}]). - --export([run/0, run/1,bonk_dir/0,start/0]). - --record(colors, {miss, x, bomb, face}). --record(scores, {points, level, bombs, hits, showed, bonus}). - -start() -> - spawn(bonk, run, []). - -run() -> - run(color). - -run([ColorMode]) -> % This is for the start script... - run(ColorMode); - -run(ColorMode) when is_atom(ColorMode) -> - GS = gs:start(), - SoundPid = spawn_link(bonk_sound,start,[]), - {H,M,S} = time(), - random:seed(H*13,M*7,S*3), - {SqrPids, Bmps, Colors} = create_board(GS, ColorMode), - {ScoreL,_File} = get_highscore(), - display_highscore(ScoreL), - put(colormode, ColorMode), - SoundPid ! music, - sleep(6500), - gs:config(aboutButton, [{enable,true}]), - gs:config(newButton, [{enable,true}]), - gs:config(quitButton, [{enable,true}]), - idle(SoundPid, SqrPids, Bmps, Colors). - -%% This is not an application so we don't have their way of knowing -%% a private data directory where the GIF files are located (this directory). -%% We can find GS and makes it relative from there /kgb -%% -%% Note the silly slash that is added. The rest of the code uses -%% append to contruct file names and assumes that the directory ends -%% in slash. If filename:join was used and the problem is gone. - --define(EbinFromGsPriv,"../contribs/bonk"). - -bonk_dir() -> - GsPrivDir = code:priv_dir(gs), - filename:join(GsPrivDir,?EbinFromGsPriv) ++ "/". - - -idle(SoundPid, SqrPids, Bmps, Colors) -> - receive - {gs, newButton, click, _Data, _Args} -> - init(SoundPid, SqrPids, Bmps, Colors); - {gs, aboutButton, click, _Data, _Args} -> - display_about(), - idle(SoundPid, SqrPids, Bmps, Colors); - {gs, quitButton, click, _Data, _Args} -> - SoundPid ! quit, - send_to_all(SqrPids, quit); - _Other -> - %%io:format("Got ~w in idle~n", [_Other]), - idle(SoundPid, SqrPids, Bmps, Colors) - end. - - - -init(SoundPid, SqrPids, Bmps, Colors) -> - clear_board(Bmps), - SoundPid ! start, - gs:config(newButton, [{enable,false}]), - gs:config(endButton, [{enable,true}]), - gs:config(aboutButton, [{enable,false}]), - Scores = #scores{points=0, level=1, bombs=0, hits=0, showed=0, bonus=10}, - clear_scores(Scores), - flush(), - send_to_all(SqrPids, start), - game(SoundPid, SqrPids, Bmps, Colors, Scores). - - -game(SoundPid, SqrPids, Bmps, Colors, Scores) -> - receive - {gs, _Square, buttonpress, SqrPid, [1 | _Rest]} when is_pid(SqrPid) -> - SqrPid ! bonk, - game(SoundPid, SqrPids, Bmps, Colors, Scores); - {gs, _Id, buttonpress, _Data, [Butt | _Rest]} when Butt =/= 1 -> - NewScores = bomb(SoundPid, SqrPids, Scores), - game(SoundPid, SqrPids, Bmps, Colors, NewScores); - {show, Square, Rect} -> - NewScores = show_face(Square, Rect, Colors, Scores), - game(SoundPid, SqrPids, Bmps, Colors, NewScores); - {hide, Square, Rect} -> - NewScores = hide_face(Square, Rect, Colors, Scores), - game(SoundPid, SqrPids, Bmps, Colors, NewScores); - {missed, Square, Rect} -> - case miss_face(SoundPid, Square, Rect, Colors, Scores) of - {continue, NewScores} -> - game(SoundPid, SqrPids, Bmps, Colors, NewScores); - {game_over, NewScores} -> - game_over(SoundPid, SqrPids, Bmps, Colors, NewScores) - end; - {bonked, Square, Rect} -> - NewScores = bonked(SoundPid, SqrPids, Square, Rect, Scores, Colors), - game(SoundPid, SqrPids, Bmps, Colors, NewScores); - {bombed, Square, Rect} -> - NewScores = bombed(SoundPid, SqrPids, Square, Rect, Scores, Colors), - game(SoundPid, SqrPids, Bmps, Colors, NewScores); - {gs, endButton, click, _Data, _Args} -> - game_over(SoundPid, SqrPids, Bmps, Colors, Scores); - {gs, quitButton, click, _Data, _Args} -> - quit(SoundPid, SqrPids, Bmps, Colors, Scores); - _Other -> - game(SoundPid, SqrPids, Bmps, Colors, Scores) - end. - - - -game_over(SoundPid, SqrPids, Bmps, Colors, Scores) -> - SoundPid ! game_over, - send_to_all(SqrPids, stop), - flush(), - sleep(2000), - update_scorelist(SoundPid, Scores), - gs:config(newButton, [{enable,true}]), - gs:config(endButton, [{enable,false}]), - gs:config(aboutButton, [{enable,true}]), - idle(SoundPid, SqrPids, Bmps, Colors). - - -quit(SoundPid, SqrPids, _Bmps, _Colors, _Scores) -> - SoundPid ! quit, - send_to_all(SqrPids, quit), - true. - - - -bomb(SoundPid, SqrPids, Scores) -> - case Scores#scores.bombs of - Bombs when Bombs > 0 -> - send_to_all(SqrPids, bomb), - SoundPid ! bomb, - gs:config(bombOut,[{text,integer_to_list(Bombs-1)}]), - Scores#scores{bombs=Bombs-1}; - _Other -> - Scores - end. - -show_face(Square, Rect, Colors, Scores) -> - Showed = Scores#scores.showed, - if - Showed == Scores#scores.level+1 -> - Square ! sleep, - Scores; - true -> - FaceColors = Colors#colors.face, - FaceColor = lists:nth(random:uniform(length(FaceColors)), FaceColors), - gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkface")},{fg, FaceColor}]), - Scores#scores{showed=Showed+1} - end. - -hide_face(_Square, Rect, _Colors, Scores) -> - Showed = Scores#scores.showed, - gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonktom")}]), - Scores#scores{showed=Showed-1}. - - -miss_face(SoundPid, _Square, Rect, Colors, Scores) -> - SoundPid ! missed, - gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkmiss")}, {fg, Colors#colors.miss}]), - Bonus = Scores#scores.bonus, - if - Bonus > 1 -> - gs:config(bonusOut, [{text,integer_to_list(Bonus-1)}]), - {continue, Scores#scores{bonus=Bonus-1}}; - true -> - gs:config(bonusOut, [{text,"0"}]), - {game_over, Scores} - end. - -bonked(SoundPid, SqrPids, _Square, Rect, Scores, Colors) -> - gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkx")}, {fg, Colors#colors.x}]), - SoundPid ! bonk, - update_score(SoundPid, SqrPids, Scores). - -bombed(SoundPid, SqrPids, _Square, Rect, Scores, Colors) -> - gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkbomb")}, {fg, Colors#colors.bomb}]), - update_score(SoundPid, SqrPids, Scores). - - -update_score(SoundPid, SqrPids, Scores) -> - Points = Scores#scores.points, - Level = Scores#scores.level, - NewPoints = Points+Level, - gs:config(scoreOut,[{text,integer_to_list(NewPoints)}]), - case Scores#scores.hits of - 24 -> - SoundPid ! new_level, - NewLevel = Level+1, - NewBombs = Scores#scores.bombs+1, - send_to_all(SqrPids, {new_level, NewLevel}), - gs:config(levelOut,[{text,integer_to_list(NewLevel)}]), - gs:config(bombOut,[{text,integer_to_list(NewBombs)}]), - Scores#scores{points=NewPoints, level=NewLevel, hits=0, bombs=NewBombs}; - Hits -> - Scores#scores{points=NewPoints, hits=Hits+1} - end. - - -send_to_all([], _Msg) -> - true; -send_to_all([Pid|Rest],Msg) when is_pid(Pid) -> - Pid ! Msg, - send_to_all(Rest,Msg); -send_to_all([_Else|Rest],Msg) -> - send_to_all(Rest,Msg). - - -create_board(GS, ColorMode) -> - Colors = - case ColorMode of - bw -> #colors{miss=white, x=white, bomb=white, face=[white]}; - _Color -> #colors{miss=red, x=green, bomb=white, - face=[lightblue, orange, magenta, peachpuff, pink]} - end, - BGCol = if ColorMode==bw -> black; true -> black end, % background color - TextCol = if ColorMode==bw -> white; true -> pink end, % status texts - NrCol = if ColorMode==bw -> white; true -> purple end, % status figures - LogoCol = if ColorMode==bw -> white; true -> green end, % bonk logo - BLineCol = if ColorMode==bw -> white; true -> grey end, % button line - SLineCol = if ColorMode==bw -> white; true -> red end, % status line - BTextCol = if ColorMode==bw -> white; true -> orange end, % button text - HiHeadCol = if ColorMode==bw -> white; true -> red end, % high score label - HiCol = if ColorMode==bw -> white; true -> cyan end, % high scores - SquareCol = if ColorMode==bw -> white; true -> yellow end, % game squares - ErlFgCol = if ColorMode==bw -> white; true -> red end, % - ErlBGCol = if ColorMode==bw -> black; true -> white end, % - ErlTxtCol = if ColorMode==bw -> white; true -> black end, % - - Width = 550, % width of bonk window - Height = 550, % Height of bonk window - - BX = 0, % x-pos for first button - DBX = 100, % space between buttons - BY = 0, % y-pos for buttons - BLineY = 30, % y-pos of button line - LogoX = (Width-320) div 2, % x-pos of bonk logo (logo is 320 pix wide) - LogoY = BLineY+2, % y-pos of bonk logo - ErlLogoX = LogoX + 200, % x-pos of Erlang e - ErlLogoY = LogoY + 10, % y-pos of Erlang e - SLineY = Height-22, % status line position - TextWidth = 50, % text width of status items - SX = 2, % x-pos for first status item - DSX = TextWidth+94, % pixels between status items - SY = SLineY+2, % y-pos status items - HiWidth = 100, % width of high score field - _HiHeight = 180, % height of the same - HiX = Width-HiWidth, % high score text position - HiY = BLineY+10, - DHY = 20, % space between title & scores - SquareSize = 76, % size of each game square - SquareSpace = 1, % space between game squares - SquareX = 40, - SquareY = 65, - - gs:create(window, bonkWin, GS, [{width, Width}, {height, Height}, - {bg, BGCol}, - {title, "Bonk the game"}, - {iconname, "Bonk!"}, - {map, false}]), - gs:create(canvas, bonkCanvas, bonkWin, [{width, Width}, - {height, Height}, - {bg, BGCol}]), - gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/bonklogo")}, - {coords, [{LogoX, LogoY}]}, - {fg, LogoCol}, - {bg, BGCol}]), - gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/erl-e")}, - {coords, [{ErlLogoX, ErlLogoY}]}, - {fg, ErlFgCol}, - {bg, ErlBGCol}]), - gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/erl-text")}, - {coords, [{ErlLogoX, ErlLogoY}]}, - {fg, ErlTxtCol}]), - gs:create(line, bLine, bonkCanvas, [{coords, [{0,BLineY}, {Width,BLineY}]}, - {fg, BLineCol}, - {width, 2}]), - gs:create(line, bLine, bonkCanvas, [{coords, [{0,SLineY}, {Width, SLineY}]}, - {fg, SLineCol}, - {width, 2}]), - gs:create(text, scoreText, bonkCanvas, [{coords, [{SX, SY}]}, - {fg, TextCol}, - {text, "Score:"}]), - gs:create(text, scoreOut, bonkCanvas, [{coords, [{SX+TextWidth, SY}]}, - {fg, NrCol}, - {width, DSX-TextWidth}, - {text, ""}]), - gs:create(text, bombText, bonkCanvas, [{coords, [{SX+DSX, SY}]}, - {fg, TextCol}, - {text, "Bombs:"}]), - gs:create(text, bombOut, bonkCanvas, [{coords, [{SX+DSX+TextWidth, SY}]}, - {fg, NrCol}, - {width, DSX-TextWidth}, - {text, ""}]), - gs:create(text, bonusText, bonkCanvas, [{coords, [{SX+2*DSX, SY}]}, - {fg, TextCol}, - {text, "Bonus:"}]), - gs:create(text, bonusOut, bonkCanvas, [{coords, [{SX+2*DSX+TextWidth, SY}]}, - {fg, NrCol}, - {width, DSX-TextWidth}, - {text, ""}]), - gs:create(text, levelText,bonkCanvas, [{coords, [{SX+3*DSX, SY}]}, - {fg, TextCol}, - {text, "Level:"}]), - gs:create(text, levelOut, bonkCanvas, [{coords, [{SX+3*DSX+TextWidth, SY}]}, - {fg, NrCol}, - {width, DSX-TextWidth}, - {text, ""}]), - gs:create(text, hiScoreText, bonkCanvas, [{coords, [{HiX, HiY}]}, - {fg, HiHeadCol}, - {text, "High Scores"}]), - gs:create(text, hiScoreOut, bonkCanvas, [{coords, [{HiX, HiY+DHY}]}, - {fg, HiCol}, - {justify, left}, - {width, HiWidth}]), - gs:create(button, newButton,bonkWin, [{x, BX},{y, BY}, - {enable,false}, - {label, {text, "New Game"}}, - {click, true}, - {fg, BTextCol}, - {bg, BGCol}, - {relief, flat}, - {activefg, BTextCol}, - {activebg, BGCol}, - {align, center}]), - gs:create(button, endButton,bonkWin, [{x, BX+DBX},{y, BY}, - {enable,false}, - {label, {text, "End Game"}}, - {click, true}, - {fg, BTextCol}, - {bg, BGCol}, - {relief, flat}, - {activefg, BTextCol}, - {activebg, BGCol}, - {align, center}]), - gs:create(button, aboutButton,bonkWin, [{x, BX+2*DBX},{y, BY}, - {enable,false}, - {label, {text, "About"}}, - {click, true}, - {fg, BTextCol}, - {bg, BGCol}, - {relief, flat}, - {activefg, BTextCol}, - {activebg, BGCol}, - {align, center}]), - gs:create(button, quitButton, bonkWin, [{x, BX+3*DBX},{y, BY}, - {enable,false}, - {label, {text, "Quit"}}, - {click, true}, - {fg, BTextCol}, - {bg, BGCol}, - {relief, flat}, - {activefg, BTextCol}, - {activebg, BGCol}, - {align, center}]), - - {SqrPids, Bmps} = - create_squares(SquareX, SquareY, SquareSize, SquareCol, SquareSpace), - gs:config(bonkWin, [{map, true}]), - {SqrPids, Bmps, Colors}. - - - -create_squares(X, Y, Size, Color, Spc) -> - create_squares(X, Y, Size, Color, Spc, 1, 1, [], []). - - -create_squares(_X, _Y, _Size, _Color, _Spc, 4, 5, Pids, Bmps) -> - {Pids, Bmps}; - -create_squares(X, Y, Size, Color, Spc, Row, 5, Pids, Bmps) -> - create_squares(X, Y, Size, Color, Spc, Row+1, 1, Pids, Bmps); - -create_squares(X, Y, Size, Color, Spc, Row, Col, Pids, Bmps) -> - Xpos = X+Col*Size+(Col-1)*Spc, - Ypos = Y+Row*Size+(Row-1)*Spc, - gs:create(rectangle, bonkCanvas, - [{coords, [{Xpos,Ypos},{Xpos+Size, Ypos+Size}]}, - {bw, 2},{fg, Color},{buttonpress,true}]), - Bmp = gs:create(image, bonkCanvas, - [{coords, [{Xpos+1, Ypos+1}]}, - {bitmap,lists:append(bonk_dir(), "bitmaps/bonktom")}, - {buttonpress, true},{fg, Color}]), - Pid = bonk_square:start(Bmp), - gs:config(Bmp, [{data, Pid}]), - create_squares(X, Y, Size, Color, Spc, Row, Col+1, [Pid|Pids], [Bmp|Bmps]). - - - -clear_board([]) -> - true; -clear_board([Square | Rest]) -> - gs:config(Square, [{bitmap,lists:append(bonk_dir(), "bitmaps/bonktom")}]), - clear_board(Rest). - - -%% Prints the list on the screen. -%% The list is on the form [[Score,Name],[Score,Name]..]. - -display_highscore(ScoreList) -> - display_highscore("",ScoreList,0). - -display_highscore(Scores,[],_N) -> - gs:config(hiScoreOut,[{text,Scores}]); - -display_highscore(Scores,_ScoreList,10) -> % This is max number of items. - display_highscore(Scores,[], 10); - -display_highscore(Scores,[[Score,Name]|Rest],N) -> - NewScores = lists:append(Scores,lists:append(lists:append(Score, [32 | Name]), [10])), - display_highscore(NewScores,Rest,N+1). - - -%% Reads the highscorelist from the file "bonk.score". -%% The list should be an sorted erlang-list. - -get_highscore() -> - case file:consult("bonk.score") of - {ok,[Score_list]} -> - {Score_list,"./bonk.score"}; - {error,_} -> - {[],"./bonk.score"} - end. - - -%% Prints out the highscorelist and places the new score in the -%% list if it is high enough. - -update_scorelist(SoundPid, Scores) -> - case Scores#scores.points of - 0 -> true; - Score -> - {ScoreL,FileName} = get_highscore(), - New_scorelist=update_scorelist_2(ScoreL, Score, 0, SoundPid), - display_highscore(New_scorelist), - case file:open(FileName, [write]) of - {error,_} -> - true; - {ok,FD} -> - io:format(FD,"~w~s~n",[New_scorelist,"."]), - file:close(FD) - end - end. - - -update_scorelist_2([], Score, N, _SoundPid) when N < 10 -> - [[integer_to_list(Score),getuser()]]; - -update_scorelist_2(_, _, N, _SoundPid) when N >= 10 -> - []; - -update_scorelist_2([[Sc, Name] | Rest], Score, N, SoundPid) -> - case list_to_integer(Sc) of - Sc_int when Sc_int < Score -> - if - N == 0 -> SoundPid ! best_score; - true -> SoundPid ! high_score - end, - lists:append([[integer_to_list(Score),getuser()]], - update_scorelist_3([[Sc,Name]|Rest],N+1)); - _Other -> - lists:append([[Sc,Name]],update_scorelist_2(Rest, Score, N+1, SoundPid)) - end. - - -update_scorelist_3([],_) -> - []; - -update_scorelist_3(_,N) when N >= 10 -> - []; - -update_scorelist_3([Item|Rest],N) -> - lists:append([Item],update_scorelist_3(Rest,N+1)). - -getuser() -> - case os:type() of - {unix,_} -> - lists:delete(10,os:cmd("whoami")); - _ -> - "Unknown" - end. - -%% Prints out the initial values of scores, bonus, level and bombs. - -clear_scores(Scores) -> - Score = integer_to_list(Scores#scores.points), - Bombs = integer_to_list(Scores#scores.bombs), - Bonus = integer_to_list(Scores#scores.bonus), - Level = integer_to_list(Scores#scores.level), - gs:config(scoreOut,{text,Score}), - gs:config(bombOut,{text,Bombs}), - gs:config(bonusOut,{text,Bonus}), - gs:config(levelOut,{text,Level}). - - -%% Removes everything that is present in the message-que. - -flush() -> - receive - _X -> - flush() - after - 0 -> - true - end. - -sleep(X) -> - receive after X -> true end. - -%% Opens a window and shows the contents of the file: "bonk.txt". -%% The window will be removed before the function ends. - -display_about() -> - {BGColor,TextColor,Bfg} = - case get(colormode) of - bw -> {black, white, white}; - _Color -> {black, peachpuff1, orange} - end, - Wid = 500, Hei = 635, - GS = gs:start(), - gs:create(window, aboutWin, GS, [{width, Wid}, {height,Hei}, - {map, false}, - {bg, BGColor}, - {title, "About Bonk!"}]), - gs:create(canvas, aboutCan, aboutWin, [{width, Wid},{height, Hei}, - {bg, black}]), - gs:create(button, okButton, aboutWin, [{x, Wid div 2 - 50},{y, Hei - 40}, - {label,{text, "Ok"}}, {click, true}, - {fg, Bfg}, {bg, BGColor}, - {relief, flat}, - {activefg, Bfg}, - {activebg, BGColor}]), - gs:create(text, aboutText, aboutCan, [{width, Wid-30}, {coords, [{15, 0}]}, - {fg, TextColor}, {justify, center}]), - case file:open(lists:append(bonk_dir(),"bonk.txt"), [read]) of - {ok, Fd} -> - write_text(Fd, "", io:get_line(Fd, "")), - file:close(Fd); - {error, _Reason} -> - gs:config(aboutText, {text, "Error: could not read the about file"}) - end, - - gs:config(aboutWin, [{map,true}]), - receive - {gs, okButton, click, _, _} -> - gs:destroy(aboutWin) - end. - -write_text(_Fd, Text, eof) -> - gs:config(aboutText, {text, Text}); -write_text(Fd, Text, More) -> - write_text(Fd, lists:append(Text, More), io:get_line(Fd, "")). diff --git a/lib/gs/contribs/bonk/bonk.gif b/lib/gs/contribs/bonk/bonk.gif deleted file mode 100644 index 3c2299686b..0000000000 Binary files a/lib/gs/contribs/bonk/bonk.gif and /dev/null differ diff --git a/lib/gs/contribs/bonk/bonk.tool b/lib/gs/contribs/bonk/bonk.tool deleted file mode 100644 index 79ad8f6701..0000000000 --- a/lib/gs/contribs/bonk/bonk.tool +++ /dev/null @@ -1,6 +0,0 @@ -{version,"0.1"}. -{{tool,"Bonk"}, - {start,{bonk,start,[]}}, - {icon,"bonk.gif"}, - {message,"Bonk - The Game"}, - {html,"../bonk/bonk.txt"}}. diff --git a/lib/gs/contribs/bonk/bonk.txt b/lib/gs/contribs/bonk/bonk.txt deleted file mode 100644 index 69c912dbee..0000000000 --- a/lib/gs/contribs/bonk/bonk.txt +++ /dev/null @@ -1,30 +0,0 @@ -BONK! In Erlang for You -by -LENNART OHMAN & MARCUS ARENDT - -After an idea of Mike Darweesh. -Special thanks to Peter Jansson for creating the bitmaps. -Ported to GS 1.1 by Markus Torpvret and Anders Dahlin. - - -INSTRUCTIONS -- Hit as many creatures as possible using the left mouse-button. -- After every 25 hits You will advance one level. For each level You get one bomb. -- Pushing the middle or right mouse-button, in any square, drops a bomb which -wipes out everything. -- The game ends when 10 creatures has escaped from beeing bonked. - - -ABOUT ERLANG -Erlang is a programming language for building robust concurrent systems. It is a single assignment, symbolic language with built in concurrency. It provides unique facilities for error handling and for reloading updated modules in running systems. Erlang was designed and implemented by Joe Armstrong, Robert Virding, and Mike Williams at Ellemtel (now Ericsson Utvecklings AB). - -Please make enquiries about Erlang to: - -Ericsson Software Technology AB -Erlang Systems -Torshamnsgatan 39B -Box 1214 -164 28 Kista -Sweden - -http://www.ericsson.se/erlang \ No newline at end of file diff --git a/lib/gs/contribs/bonk/bonk_sound.erl b/lib/gs/contribs/bonk/bonk_sound.erl deleted file mode 100644 index 9a0db80e5d..0000000000 --- a/lib/gs/contribs/bonk/bonk_sound.erl +++ /dev/null @@ -1,82 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(bonk_sound). --export([start/0]). - -start() -> - random:seed(), - sounder:start(), - {ok,Bonk}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/bonk.au")), - {ok,Ouch}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/ouch!!!.au")), - {ok,Damn}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/damn.au")), - {ok,Bomb}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/explosion.au")), - {ok,Missed}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/missedme.au")), - {ok,Game_over}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/gameover.au")), - {ok,New_level}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/level.au")), - {ok,Music}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/trumpet.au")), - {ok,Start}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/hehee.au")), - {ok,BestS}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/praisejesus.au")), - {ok,HighS}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/yes.au")), - loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level, - Music, Start, BestS, HighS). - - -loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level, Music, Start, BestS, HighS) -> - R=random:uniform(1000), - receive - bonk -> - if - R < 75 -> play_sound(Damn); - R < 275 -> play_sound(Ouch); - true -> play_sound(Bonk) - end; - bomb -> play_sound(Bomb); - missed -> play_sound(Missed); - game_over -> play_sound(Game_over); - new_level -> play_sound(New_level); - music -> play_sound(Music); - start -> play_sound(Start); - best_score -> play_sound(BestS); - high_score -> play_sound(HighS); - quit -> - sounder:stop(), - exit(normal) - end, - loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level, Music, Start, BestS, HighS). - -play_sound(Snd) -> - case catch sounder:play(Snd) of - {'EXIT', _Reason} -> - io:format("Cannot use audio device!\n"), - sounder:stop(), - silent_loop(); - _Other -> - true - end. - -silent_loop() -> - receive - quit -> - exit(normal); - _Other -> - silent_loop() - end. diff --git a/lib/gs/contribs/bonk/bonk_square.erl b/lib/gs/contribs/bonk/bonk_square.erl deleted file mode 100644 index 98af91944b..0000000000 --- a/lib/gs/contribs/bonk/bonk_square.erl +++ /dev/null @@ -1,146 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(bonk_square). --export([start/1,init/5,alarm/3]). - - - -start(Bmp) -> - spawn_link(bonk_square, init, [Bmp, self(), - random:uniform(10000), - random:uniform(10000), - random:uniform(10000)]). - -init(Bmp, BoardPid, Seed1, Seed2, Seed3) -> - random:seed(Seed1,Seed2,Seed3), - idle(Bmp, BoardPid). - - -idle(Bmp, BoardPid) -> - receive - start -> - Level = 1, - sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up)); - quit -> - exit(normal); - _Other -> - idle(Bmp, BoardPid) - end. - - -sleep(Level, Bmp, BoardPid, Alarm) -> - receive - stop -> - Alarm ! quit, - idle(Bmp, BoardPid); - quit -> - Alarm ! quit, - exit(normal); - {new_level, NewLevel} -> - sleep(NewLevel, Bmp, BoardPid, Alarm); - {Alarm, wake_up} -> - show_me(BoardPid, Bmp), - show(Level, Bmp, BoardPid, alarm(2500, missed)); - _Other -> - sleep(Level, Bmp, BoardPid, Alarm) - end. - - -show(Level, Bmp, BoardPid, Alarm) -> - receive - stop -> - Alarm ! quit, - idle(Bmp, BoardPid); - quit -> - Alarm ! quit, - exit(normal); - {new_level, NewLevel} -> - show(NewLevel, Bmp, BoardPid, Alarm); - sleep -> % The board was too crowded. - Alarm ! quit, - sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up)); - bonk -> - bonk_me(BoardPid, Bmp), - Alarm ! quit, - bbmed(Level, Bmp, BoardPid, alarm(1500, hide)); - bomb -> - bomb_me(BoardPid, Bmp), - Alarm ! quit, - bbmed(Level, Bmp, BoardPid, alarm(1000, hide)); - {Alarm, missed} -> - missed_me(BoardPid, Bmp), - bbmed(Level, Bmp, BoardPid, alarm(1500, hide)); - _Other -> - show(Level, Bmp, BoardPid, Alarm) - end. - -%% bonked, bombed or missed -bbmed(Level, Bmp, BoardPid, Alarm) -> - receive - stop -> - Alarm ! quit, - idle(Bmp, BoardPid); - quit -> - Alarm ! quit, - exit(normal); - {new_level, NewLevel} -> - bbmed(NewLevel, Bmp, BoardPid, Alarm); - {Alarm, hide} -> - hide_me(BoardPid, Bmp), - sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up)); - _Other -> - bbmed(Level, Bmp, BoardPid, Alarm) - end. - - -show_me(BoardPid, Bmp) -> - BoardPid ! {show, self(), Bmp}. - -hide_me(BoardPid, Bmp) -> - BoardPid ! {hide, self(), Bmp}. - -bonk_me(BoardPid, Bmp) -> - BoardPid ! {bonked, self(), Bmp}. - -bomb_me(BoardPid, Bmp) -> - BoardPid ! {bombed, self(), Bmp}. - -missed_me(BoardPid, Bmp) -> - BoardPid ! {missed, self(), Bmp}. - - -%% Count sleep time - -sleep_time(Level) -> - random:uniform((19000 div (Level+1))*2+1500). - -%% Set an alarm - -alarm(Time, Msg) -> - spawn(bonk_square, alarm, [Time, Msg, self()]). - -alarm(Time, Msg, Pid) -> - receive - quit -> exit(normal) - after - Time -> Pid ! {self(), Msg} - end. diff --git a/lib/gs/contribs/bonk/sounder.erl b/lib/gs/contribs/bonk/sounder.erl deleted file mode 100644 index aabcaa1950..0000000000 --- a/lib/gs/contribs/bonk/sounder.erl +++ /dev/null @@ -1,160 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(sounder). --export([start/0,play/1,new/1,go/0,stop/0,nosound/0,silent/0]). --include_lib("kernel/include/file.hrl"). -%%---------------------------------------------------------------------- -%% sounder.erl - An interface to /dev/audio -%% -%% Created by: {lennarto,mike}@erix.ericsson.se -%% Modified by: EV,tobbe@erix.ericsson.se -%% -%% Mod: 6 Jun 1996 by tobbe@erix.ericsson.se -%% The executable sounder will no be looked for in the -%% same directory as from where sounder.jam is loaded. -%% -%% -%% start() - Returns either: ok ,or: silent ,where silent means -%% that no audio capabilities exists but the sounder -%% will work "silently" in order to not break any code. -%% -%% stop() - Returns: ok -%% -%% new(File) - Tries to load the File. At success, a number refering -%% to the File is returned that shall be used with send/1. -%% Otherwise {error,Reason} is returned. -%% -%% play(No) - Tries to execute the sound registered with the number No -%% Returns: ok , or: {error,Reason} -%% -%% silent() - Returns: true ,if no audio capabilities exists, else: false -%% -%% Note: It is also possible to receive: {error,sounder_not_started} -%% -%%---------------------------------------------------------------------- - -start() -> - case whereis(sounder) of - undefined -> - %% first we check if the workstation has audio capabilities - case file:read_file_info('/dev/audio') of - {ok, FI} when FI#file_info.access==read_write -> - register(sounder, spawn(sounder,go,[])), - ok; - _Other -> - register(sounder, spawn(sounder,nosound,[])), - silent - end; - _Pid -> - ok - end. - -stop() -> - catch begin check(), - sounder ! {stop}, - ok end. - -new(File) when is_list(File) -> new(list_to_atom(File)); -new(File) when is_atom(File) -> - catch begin check(), - sounder ! {new,File,self()}, - wait_for_ack(sounder) end. - -play(No) when is_integer(No) -> - catch begin check(), - sounder ! {play, No, self()}, - wait_for_ack(sounder) end. - -silent() -> - catch begin check(), - sounder ! {play,silent,self()}, - receive {sounder,Answer} -> Answer end end. - -go() -> - Port = open_port({spawn,lists:append(bonk:bonk_dir(), "sounder")},[{packet, 2}]), - loop(Port). - -loop(Port) -> - receive - {new, File, From} when is_atom(File) -> - Port ! {self(),{command,lists:append([0],atom_to_list(File))}}, - From ! {sounder,wait_for_ack(Port)}, - loop(Port); - {play,silent,From} -> - From ! {sounder,false}, - loop(Port); - {play,No,From} when is_integer(No) -> - Port ! {self(),{command,[No]}}, - From ! {sounder,wait_for_ack(Port)}, - loop(Port); - {stop} -> - Port ! {self(),close}, - exit(normal); - _ -> - loop(Port) - end. - -%% The application using sounds can check on silence itself -%% and refrain from playing sounds. -%% Or it can try to play sounds that will be "consumed in silence" - -nosound() -> - receive - {new,File,From} when is_atom(File) -> - From ! {sounder,{ok,silent}}, - nosound(); - {play,silent,From} -> - From ! {sounder,true}, - nosound(); - {play,No,From} when is_integer(No) -> - From ! {sounder,{error,no_audio_cap}}, - nosound(); - {stop} -> - exit(normal); - _ -> - nosound() - end. - -wait_for_ack(sounder) -> - receive {sounder,Res} -> Res end; -wait_for_ack(Port) when is_port(Port) -> - receive - {Port,{data,"ok"}} -> - ok; - {Port,{data,[No]}} -> - {ok,No}; - {Port,{data,Msg}} -> - {error,list_to_atom(Msg)}; - {'EXIT',Port,_} -> - exit(port_exited) - end. - -check() -> - case whereis(sounder) of - Pid when is_pid(Pid) -> - ok; - undefined -> - throw({error,sounder_not_started}) - end. - - - diff --git a/lib/gs/contribs/bonk/sounds/bonk.au b/lib/gs/contribs/bonk/sounds/bonk.au deleted file mode 100644 index 5e6518898b..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/bonk.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/damn.au b/lib/gs/contribs/bonk/sounds/damn.au deleted file mode 100644 index 6117506fb4..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/damn.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/explosion.au b/lib/gs/contribs/bonk/sounds/explosion.au deleted file mode 100644 index 78a6964f1a..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/explosion.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/gameover.au b/lib/gs/contribs/bonk/sounds/gameover.au deleted file mode 100644 index ca7628f3c6..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/gameover.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/hehee.au b/lib/gs/contribs/bonk/sounds/hehee.au deleted file mode 100644 index 10cd16b596..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/hehee.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/level.au b/lib/gs/contribs/bonk/sounds/level.au deleted file mode 100644 index 0508c2a6ae..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/level.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/missedme.au b/lib/gs/contribs/bonk/sounds/missedme.au deleted file mode 100644 index 4c07c9d428..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/missedme.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/music.au b/lib/gs/contribs/bonk/sounds/music.au deleted file mode 100644 index ead6ec79b2..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/music.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/ouch!!!.au b/lib/gs/contribs/bonk/sounds/ouch!!!.au deleted file mode 100644 index 78bcf48074..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/ouch!!!.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/praisejesus.au b/lib/gs/contribs/bonk/sounds/praisejesus.au deleted file mode 100644 index e299bf66d6..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/praisejesus.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/trumpet.au b/lib/gs/contribs/bonk/sounds/trumpet.au deleted file mode 100644 index 2f551b436a..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/trumpet.au and /dev/null differ diff --git a/lib/gs/contribs/bonk/sounds/yes.au b/lib/gs/contribs/bonk/sounds/yes.au deleted file mode 100644 index c1ce7dfb69..0000000000 Binary files a/lib/gs/contribs/bonk/sounds/yes.au and /dev/null differ diff --git a/lib/gs/contribs/cols/Makefile b/lib/gs/contribs/cols/Makefile deleted file mode 100644 index 34a900e5ab..0000000000 --- a/lib/gs/contribs/cols/Makefile +++ /dev/null @@ -1,103 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../../vsn.mk -VSN=$(GS_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - cols \ - highscore - -HRL_FILES= - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES) - -TOOLNAME = cols - -EXTRA_FILES= -TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif help.gif -TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) - -docs: - -clean: - rm -f $(TARGET_FILES) - rm -f core - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).gif $@ - -$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).tool $@ - -$(EBIN)/help.gif: help.gif - $(gen_verbose)rm -f $@ - $(V_at)cp help.gif $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" - $(INSTALL_DIR) "$(RELSYSDIR)/cols/bitmaps" - $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/cols/bitmaps" - $(INSTALL_DIR) "$(RELSYSDIR)/cols" - $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/cols" - -release_docs_spec: - diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl deleted file mode 100644 index 265f2b6ee8..0000000000 --- a/lib/gs/contribs/cols/cols.erl +++ /dev/null @@ -1,625 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(cols). --compile([{nowarn_deprecated_function,{gs,config,2}}, - {nowarn_deprecated_function,{gs,create,3}}, - {nowarn_deprecated_function,{gs,create,4}}, - {nowarn_deprecated_function,{gs,destroy,1}}, - {nowarn_deprecated_function,{gs,read,2}}, - {nowarn_deprecated_function,{gs,start,0}}]). - --export([start/0, init/0]). - -%% internal export. --export([make_board_elem/3]). - -%%====================================================================== -%% Contents -%%===================== -%% 1. The actual program -%% 2. Graphics -%% 3. Data structures and stuff -%% 4. Lambdas -%%====================================================================== - - --define(COLORS, {red,green,blue,grey,yellow,{66,153,130}}). --define(HIGHFILE, "./cols.high"). --define(HEIGHT, 17). --define(LEFT, 50). --define(SIZE, 15). --define(VERSION, "v0.9"). --define(WIDTH, 8). - --record(state, {bit,board,nextbit,ticks, score=0}). -%%---------------------------------------------------------------------- -%% Consists of three boxes. -%%---------------------------------------------------------------------- --record(bit, {x,y,topColor, middleColor, bottomColor, - top_gsobj,mid_gsobj,bot_gsobj}). - -%%====================================================================== -%% 1. The actual program -%%====================================================================== - -start() -> - spawn_link(cols,init,[]). - -init() -> - make_graphics(), - {A,B,C} = erlang:now(), - random:seed(A,B,C), - NextBit = make_bit(), - Board = make_screen_board(), - S = #state{bit=make_bit(), board=Board, ticks=update_timer(1), - score=make_score(), nextbit=new_bit_xy(NextBit, -2,5)}, - gs:config(win, [{map, true}]), - loop(S). - -make_graphics() -> - G = gs:start(), - H = ?HEIGHT*?SIZE, - W = ?WIDTH*?SIZE, - BotMargin = 100, - gs:create(window, win, G, [{destroy,true},{map, true},{title, "cols"}, - {height, H+BotMargin}, {width, W+?LEFT+10}, - {bg, grey},{keypress,true}]), - gs:create(canvas, can, win, [{bg, black}, - {height, H+BotMargin}, - {width, W+?LEFT+20}]), - gs:create(text, can, [{text, "Next"}, {coords, [{5, 45}]}, {fg, red}]), - gs:create(image, help, can, [{coords,[{5,7}]}, - {load_gif, dir() ++ "/help.gif"}, - {buttonpress,true}]), - draw_borders(). - -loop(State) -> - receive - Event -> loop(update(Event, State)) - end. - -%%---------------------------------------------------------------------- -%% How fast speed should be doubled -%%---------------------------------------------------------------------- --define(DBL_TICKS, 300). - -update_timer(Ticks) -> - K = 0.001/?DBL_TICKS, - M = 1.001-K, - Q = K*Ticks+M, - Timeout = round(1/math:log(Q)), - timer:send_after(Timeout, self(), fall_timeout), - Ticks+1. - -add_score({ScoreObj, NScore}, DScore) -> - NScore2 = NScore + DScore, - gs:config(ScoreObj, [{text, io_lib:format("Score: ~w", [NScore2])}]), - {ScoreObj, NScore2}. - - -update({gs,_Obj,keypress,_Data, ['Left'|_]}, State) -> - #state{bit=Bit, board = Board} = State, - #bit{x=X,y=Y} = Bit, - if X > 0 -> - case is_board_empty(Board, X-1,Y) of - true -> - State#state{bit=new_bit_xy(Bit, X-1, Y)}; - false -> - State - end; - true -> State - end; - -update({gs,_Obj,keypress,_Data, ['Right'|_]}, State) -> - #state{bit=Bit, board = Board} = State, - #bit{x=X,y=Y} = Bit, - if X < ?WIDTH - 1 -> - case is_board_empty(Board, X+1, Y) of - true -> - State#state{bit=new_bit_xy(Bit, X+1, Y)}; - false -> - State - end; - true -> State - end; - -update({gs,_Obj,keypress,_Data, ['Up'|_]}, State) -> - State#state{bit=shift_bits(State#state.bit)}; - -update({gs,_Obj,keypress,_Data, [Key|_]}, State) -> - case drop_key(Key) of - true -> - #state{bit=Bit, board=Board, score=Score} = State, - #bit{x=X,y=Y} = Bit, - {NewX, NewY, NewScore} = drop(X,Y,Score,Board), - fasten_bit(State#state{bit=new_bit_xy(Bit,NewX, NewY), - score=NewScore}); - false -> State - end; - -update(fall_timeout, State) -> - #state{bit=Bit, board=Board, ticks = Ticks, score=Score} = State, - NewY = Bit#bit.y+1, - X = Bit#bit.x, - case is_fall_ok(Board, X, NewY) of - true -> - State#state{bit=new_bit_xy(Bit, X, NewY), - ticks=update_timer(Ticks), score=add_score(Score, 1)}; - false -> - S1 = fasten_bit(State), - S1#state{ticks=update_timer(Ticks)} - end; - -update({gs,_,destroy,_,_}, _State) -> - exit(normal); - -update({gs,help,buttonpress,_,_}, State) -> - show_help(), - State; - -update(OtherEvent, State) -> - ok=io:format("got other! ~w~n", [OtherEvent]), State. - -drop_key('Down') -> true; -drop_key(space) -> true; -drop_key(_) -> false. - -is_board_empty(Board, X, Y) -> - case {color_at(Board, X, Y), - color_at(Board, X, Y + 1), - color_at(Board, X, Y + 2)} of - {black, black, black} -> true; - _ -> false - end. - -%%---------------------------------------------------------------------- -%% Returns: NewState -%%---------------------------------------------------------------------- -fasten_bit(State) -> - #state{board=Board, bit=Bit, nextbit=NextBit, score=Score} = State, - #bit{x=X,y=Y,topColor=C1,middleColor=C2,bottomColor=C3} = Bit, - B1 = update_screen_element(Board, X, Y, C1), - B2 = update_screen_element(B1, X, Y+1, C2), - B3 = update_screen_element(B2, X, Y+2, C3), - destroy_bit(Bit), - #bit{topColor=NC1,middleColor=NC2,bottomColor=NC3} = NextBit, - {B4, ExtraScore} = erase_bits(B3, [{X,Y},{X,Y+1},{X,Y+2}], 0), - NewBit = make_bit(NC1,NC2,NC3), - case is_board_empty(B4, NewBit#bit.x, NewBit#bit.y) of - true -> - State#state{score=add_score(Score, ExtraScore), - bit=NewBit, nextbit=new_colors(NextBit),board=B4}; - false -> - {_GsObj,Score2}=State#state.score, - highscore:run(Score2,?HIGHFILE), - exit(normal) - end. - -%%---------------------------------------------------------------------- -%% Args: Check: list of {X,Y} to check. -%% Returns: {NewBoard, ExtraScore} -%%---------------------------------------------------------------------- -erase_bits(Board, Checks, ExtraScore) -> - ElemsToDelete = elems2del(Checks,Board,[]), - NDel = length(ElemsToDelete), - if - NDel > 0 -> - Board2 = delete_elems(Board, ElemsToDelete), - {NewBoard, NewCheck} = fall_down(Board2, ElemsToDelete), - if NDel > 3 -> - {B,ES}=erase_bits(NewBoard,NewCheck,ExtraScore+2*NDel), - {NewBoard2, NewCheck2} = bonus(B, NewCheck), - erase_bits(NewBoard2, NewCheck2, ES); - true -> - erase_bits(NewBoard, NewCheck, 2*NDel) - end; - true -> {Board, ExtraScore} - end. - -bonus(Board, Check) -> - Cols = collect_bottom_bits(0,Board), - NewBoard = randomize_columns(5, Board, Cols), - NewCheck = update_check(Check, Cols), - {NewBoard, NewCheck}. - -randomize_columns(0, Board, _) -> Board; -randomize_columns(N, Board, Cols) -> - NewBoard = randomize_columns(Cols,Board), - randomize_columns(N-1, NewBoard, Cols). - -randomize_columns([],Board) -> Board; -randomize_columns([X|Xs],Board) -> - flush(), - timer:sleep(50), - randomize_columns(Xs,update_screen_element(Board,X,?HEIGHT-1,rndColor())). - -%%---------------------------------------------------------------------- -%% Returns: NewBoard -%%---------------------------------------------------------------------- -delete_elems(Board, Elems2Del) -> - OrgObjs = org_objs(Elems2Del,Board), - visual_effect(?SIZE, OrgObjs), - NewBoard = update_board(Elems2Del, Board), - put_back(OrgObjs), - NewBoard. - -visual_effect(0,_OrgObjs) -> done; -visual_effect(Size,OrgObjs) -> - set_size(OrgObjs,Size), - flush(), - timer:sleep(20), - visual_effect(Size-1,OrgObjs). - -set_size([],_Size) -> done; -set_size([{GsObj,[{X1,Y1},{_X2,_Y2}]}|T],Size) -> - gs:config(GsObj, [{coords, [{X1,Y1},{X1+Size,Y1+Size}]}]), - set_size(T,Size). - -%%---------------------------------------------------------------------- -%% Note: Loop over columns where something is removed only. (efficiency) -%% Returns: {ReversedNewColumns (perhaps shorter), Checks} -%% cols:fall_column([a,b,black,black,c,f,black,d,black], 3, 15, [], []). -%% should return: {[a,b,c,f,d],[{3,11},{3,12},{3,13}]} -%%---------------------------------------------------------------------- -fall_column([], _X, _Y, ColumnAcc, ChecksAcc) -> - {ColumnAcc, ChecksAcc}; -fall_column([black|Colors], X, Y, ColumnAcc, ChecksAcc) -> - case find_box(Colors) of - false -> {ColumnAcc, ChecksAcc}; - NewColors when is_list(NewColors) -> - fall_one_step(NewColors, X, Y, ColumnAcc, ChecksAcc) - end; -fall_column([Color|Colors], X, Y, ColumnAcc, ChecksAcc) -> - fall_column(Colors, X, Y-1, [Color | ColumnAcc], ChecksAcc). - -find_box([]) -> false; -find_box([black|Colors]) -> - find_box(Colors); -find_box([Color|Colors]) -> [Color|Colors]. - -%%---------------------------------------------------------------------- -%% Enters: ([a,b, , ,c,d], 3, 8, Q) -%% Leaves: ([b,a|Q], [ , , ,c,d], 10, [{3,8},{4,9}]) -%%---------------------------------------------------------------------- -fall_one_step([], X, Y, ColumnAcc, Checks) -> - fall_column([], X, Y, ColumnAcc, Checks); -fall_one_step([black|Colors], X, Y, ColumnAcc, Checks) -> - fall_column([black|Colors], X, Y, ColumnAcc, Checks); -fall_one_step([Color|Colors], X, Y, ColumnAcc, Checks) -> - fall_one_step(Colors, X, Y-1, [Color|ColumnAcc],[{X,Y}|Checks]). - -%%---------------------------------------------------------------------- -%% Returns: {NewBoard, NewChecks} -%%---------------------------------------------------------------------- -fall_down(Board1, Elems2Del) -> - UpDatedCols = updated_cols(Elems2Del, []), - fall_column(UpDatedCols, Board1, []). - -fall_column([], NewBoard, NewChecks) -> {NewBoard, NewChecks}; -fall_column([X|Xs], BoardAcc, ChecksAcc) -> - OrgColumn = boardcolumn_to_tuple(BoardAcc, X), - Column = columntuple_to_list(OrgColumn), - {NewColumn, NewChecksAcc} = fall_column(Column, X,?HEIGHT-1,[],ChecksAcc), - NewBoardAcc = - set_board_column(BoardAcc,X,new_column_list(NewColumn,OrgColumn)), - fall_column(Xs,NewBoardAcc,NewChecksAcc). - -new_column_list(NewColumn, ColumnTuple) -> - Nempty = ?HEIGHT - length(NewColumn), - L = make_list(black, Nempty) ++ NewColumn, - new_column_list(L, 1, ColumnTuple). - -new_column_list([H|T], N, Tuple) -> - {GsObj, Color} = element(N, Tuple), - [update_screen_element({GsObj, Color},H) | new_column_list(T, N+1, Tuple)]; -new_column_list([], _, _) -> []. - - -%%---------------------------------------------------------------------- -%% Returns: a reversed list of colors. -%%---------------------------------------------------------------------- -columntuple_to_list(ColumnTuple) when is_tuple(ColumnTuple) -> - columntuple_to_list(tuple_to_list(ColumnTuple),[]). - -columntuple_to_list([],Acc) -> Acc; -columntuple_to_list([{_GsObj, Color}|T],Acc) -> - columntuple_to_list(T,[Color|Acc]). - -%%====================================================================== -%% 2. Graphics -%%====================================================================== - -make_bit() -> - make_bit(rndColor(),rndColor(),rndColor()). - -make_bit(Tc,Mc,Bc) -> - X = ?WIDTH div 2, - Y = 0, - #bit{x=X,y=Y,topColor= Tc, middleColor=Mc, bottomColor=Bc, - top_gsobj = make_box(X,Y,Tc), mid_gsobj=make_box(X,Y+1,Mc), - bot_gsobj=make_box(X,Y+2,Bc)}. - -new_colors(Bit) -> - #bit{top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit, - Tc = rndColor(), - Mc = rndColor(), - Bc = rndColor(), - gs:config(T, [{fill, Tc}]), - gs:config(M, [{fill, Mc}]), - gs:config(B, [{fill, Bc}]), - Bit#bit{topColor= Tc, middleColor=Mc, bottomColor=Bc}. - -new_bit_xy(Bit, NewX, NewY) -> - #bit{x=X,y=Y,top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit, - Dx = (NewX - X) * ?SIZE, - Dy = (NewY - Y) * ?SIZE, - gs:config(T, [{move, {Dx, Dy}}]), - gs:config(M, [{move, {Dx, Dy}}]), - gs:config(B, [{move, {Dx, Dy}}]), - Bit#bit{x=NewX, y=NewY}. - -destroy_bit(#bit{top_gsobj=T,mid_gsobj=M,bot_gsobj=B}) -> - gs:destroy(T), - gs:destroy(M), - gs:destroy(B). - -shift_bits(Bit) -> - #bit{topColor=C1,middleColor=C2,bottomColor=C3, - top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit, - gs:config(T, {fill,C2}), - gs:config(M, {fill,C3}), - gs:config(B, {fill,C1}), - Bit#bit{topColor=C2, middleColor=C3, bottomColor=C1}. - -rndColor() -> - Siz = size(?COLORS), - element(random:uniform(Siz), ?COLORS). - -make_score() -> - {gs:create(text, can, [{text, "Score: 0"}, {fg, red}, - {coords, [{5,?HEIGHT*?SIZE+10}]}]), 0}. - -make_screen_board() -> - xy_loop({cols,make_board_elem}, make_board(), ?WIDTH, ?HEIGHT). - -make_board_elem(X,Y,Board) -> - set_board_element(Board,X,Y,{make_box(X,Y,black),black}). - -flush() -> gs:read(can, bg). - -draw_borders() -> - BotY = ?HEIGHT*?SIZE, - RightX = ?LEFT + ?SIZE*?WIDTH, - LeftX = ?LEFT - 1, - gs:create(line,can,[{coords,[{LeftX,0},{LeftX,BotY}]},{fg,white}]), - gs:create(line,can,[{coords,[{LeftX,BotY},{RightX,BotY}]},{fg,white}]), - gs:create(line,can,[{coords,[{RightX,0},{RightX, BotY}]}, {fg,white}]). - -update_screen_element(ScrBoard, X, Y, Color) -> - case board_element(ScrBoard,X,Y) of - {_GsObj, Color} -> - ScrBoard; % don't have to update screen - {GsObj, _ScreenColor} -> - gs:config(GsObj, color_args(Color)), - set_board_element(ScrBoard, X, Y, {GsObj, Color}) - end. - -update_screen_element(ScrElem, Color) -> - case ScrElem of - {_GsObj, Color} -> - ScrElem; % don't have to update screen - {GsObj, _ScreenColor} -> - gs:config(GsObj, color_args(Color)), - {GsObj, Color} - end. - - -color_args(black) -> [{fg,black},{fill,black}]; -color_args(Color) -> [{fg,white},{fill,Color}]. - -%%====================================================================== -%% 3. Data structures and stuff -%%====================================================================== - -xy_loop(Fun, Acc, XMax, YMax) -> - xy_loop(Fun, Acc, 0, 0, XMax, YMax). - -xy_loop(_Fun, Acc, _X, YMax, _XMax, YMax) -> Acc; -xy_loop(Fun, Acc, XMax, Y, XMax, YMax) -> - xy_loop(Fun, Acc, 0, Y+1, XMax, YMax); -xy_loop(Fun, Acc, X, Y, XMax, YMax) -> - xy_loop(Fun, apply(Fun, [X, Y,Acc]), X+1,Y,XMax, YMax). - -%%---------------------------------------------------------------------- -%% Returns: a sorted list of {X,Y} to delete. -%% Pre: PrevDelElems is sorted. -%%---------------------------------------------------------------------- -erase_bits_at(Board, PrevDelElems, X,Y) -> - C = color_at(Board, X, Y), - erase_bits_at([vert, horiz, slash, backslash],X,Y,C,Board,PrevDelElems). - -erase_bits_at([], _X,_Y,_C,_Board, Elems2Del) -> Elems2Del; -erase_bits_at([Dir|Ds],X,Y,C,Board, Elems2DelAcc) -> - Dx = dx(Dir), - Dy = dy(Dir), - DelElems = lists:append(check_dir(Board, X-Dx,Y-Dy,-Dx,-Dy,C), - check_dir(Board, X,Y,Dx,Dy,C)), - N_in_a_row = length(DelElems), - if N_in_a_row >= 3 -> - erase_bits_at(Ds,X,Y,C,Board, - ordsets:union(lists:sort(DelElems),Elems2DelAcc)); - true -> erase_bits_at(Ds,X,Y,C,Board,Elems2DelAcc) - end. - -dx(vert) -> 0; -dx(horiz) -> 1; -dx(slash) -> 1; -dx(backslash) -> -1. - -dy(vert) -> -1; -dy(horiz) -> 0; -dy(slash) -> -1; -dy(backslash) -> -1. - - -%%---------------------------------------------------------------------- -%% Returns: list of {X,Y} to delete. -%%---------------------------------------------------------------------- -check_dir(Board, X, Y, Dx, Dy, Color) - when X >= 0, X < ?WIDTH, Y >= 0, Y < ?HEIGHT -> - case color_at(Board, X, Y) of - Color -> - [{X,Y} | check_dir(Board, X+Dx, Y+Dy, Dx, Dy, Color)]; - _OtherColor -> - [] - end; -check_dir(_Board, _X, _Y, _Dx, _Dy, _Color) -> []. - -make_box(X, Y, Color) -> - make_box(X, Y, 1, 1, Color). - -%%---------------------------------------------------------------------- -%% Returns: GsObj -%%---------------------------------------------------------------------- -make_box(X, Y, Height, Width, Color) -> - Opts = if Color == black -> [{fg, black}, {fill, black}]; - true -> [{fill, Color}, {fg, white}] end, - gs:create(rectangle, can, [{coords, [{?LEFT + X * ?SIZE, Y * ?SIZE}, - {?LEFT + X * ?SIZE + (?SIZE*Width)-1, - Y * ?SIZE + (?SIZE*Height)-1}]}|Opts]). - -is_fall_ok(_Board, _NewX, NewY) when NewY+2 >= ?HEIGHT -> false; -is_fall_ok(Board, NewX, NewY) -> - case color_at(Board, NewX, NewY+2) of - black -> - true; - _ -> false - end. - -color_at(Board, X, Y) -> - {_GsObj, Color} = board_element(Board, X, Y), - Color. - - -%%---------------------------------------------------------------------- -%% X:0..?WIDTH-1, Y:0..?HEIGHT -%%---------------------------------------------------------------------- -make_board() -> - list_to_tuple(make_list(make_column(), ?WIDTH)). - -board_element(Board, X, Y) -> - element(Y+1, element(X+1, Board)). - -set_board_element(Board, X, Y, NewValue) -> - Col = element(X+1, Board), - NewCol=setelement(Y+1,Col, NewValue), - setelement(X+1, Board, NewCol). - -make_column() -> - list_to_tuple(make_list(black, ?HEIGHT)). - -make_list(_Elem, 0) -> []; -make_list(Elem, N) -> [Elem|make_list(Elem,N-1)]. - -boardcolumn_to_tuple(Board, X) -> - element(X+1, Board). - -set_board_column(Board, X, NewCol) when length(NewCol) == ?HEIGHT -> - setelement(X+1, Board, list_to_tuple(NewCol)). - -show_help() -> - W = gs:create(window, win, [{title, "cols Help"}, {width, 300}, - {height,300}, {map, true}]), - gs:create(label, W, [{x,0},{y,0},{height, 200},{width,300},{justify,center}, - {label, {text, - "cols $Revision: 1.23 $" - "\nby\n" - "Klas Eriksson, eklas@erlang.ericsson.se\n\n" - "Help: Use arrows and space keys.\n" - " Try to get 3 in-a-row.\n" - " More than 3 gives bonus."}}]), - B=gs:create(button, W, [{x,100},{y,250}, {label, {text, "Dismiss"}}]), - receive - {gs, B, click, _, _} -> ok - end, - gs:destroy(W). - -%%====================================================================== -%% 4. Lambdas -%%====================================================================== - -drop(X,Y,Score,Board) -> - case is_fall_ok(Board, X, Y+1) of - true -> drop(X,Y+1,add_score(Score, 1),Board); - false -> {X,Y, Score} - end. - -elems2del([], _Board,Elems2DelAcc) -> Elems2DelAcc; -elems2del([{X,Y}|Checks],Board,Elems2DelAcc) -> - NewElems2DelAcc = ordsets:union(erase_bits_at(Board,Elems2DelAcc,X,Y), - Elems2DelAcc), - elems2del(Checks,Board,NewElems2DelAcc). - -collect_bottom_bits(?WIDTH,_Board) -> []; -collect_bottom_bits(X,Board) -> - case color_at(Board, X, ?HEIGHT-1) of - black -> collect_bottom_bits(X+1,Board); - _AcolorHere -> [X|collect_bottom_bits(X+1,Board)] - end. - -update_check(_Check,[]) -> []; -update_check(Check,[X|Xs]) -> - case lists:member({X, ?HEIGHT-1}, Check) of - true -> update_check(Check,Xs); - false -> [{X, ?HEIGHT-1}|update_check(Check,Xs)] - end. - -org_objs([],_Board) -> []; -org_objs([{X,Y}|XYs],Board) -> - {GsObj, _Color} = board_element(Board, X, Y), - [{GsObj, lists:sort(gs:read(GsObj, coords))}|org_objs(XYs,Board)]. - -update_board([],Board) -> Board; -update_board([{X,Y}|XYs], Board) -> - update_board(XYs,update_screen_element(Board, X, Y, black)). - -put_back([]) -> done; -put_back([{GsObj, Coords}|Objs]) -> - gs:config(GsObj, [{coords, Coords}]), - put_back(Objs). - -updated_cols([], UpdColsAcc) -> UpdColsAcc; -updated_cols([{X,_Y}|XYs], UpdColsAcc) -> - case lists:member(X,UpdColsAcc) of - true -> updated_cols(XYs,UpdColsAcc); - false -> updated_cols(XYs,[X|UpdColsAcc]) - end. - -%% This is not an application so we don't have their way of knowing -%% a private data directory where the GIF files are located (this directory). -%% We can find GS and makes it relative from there /kgb - --define(EbinFromGsPriv,"../contribs/ebin"). - -dir()-> - GsPrivDir = code:priv_dir(gs), - filename:join(GsPrivDir,?EbinFromGsPriv). diff --git a/lib/gs/contribs/cols/cols.gif b/lib/gs/contribs/cols/cols.gif deleted file mode 100644 index 96e7c1ed4a..0000000000 Binary files a/lib/gs/contribs/cols/cols.gif and /dev/null differ diff --git a/lib/gs/contribs/cols/cols.tool b/lib/gs/contribs/cols/cols.tool deleted file mode 100644 index 673c3d8efa..0000000000 --- a/lib/gs/contribs/cols/cols.tool +++ /dev/null @@ -1,5 +0,0 @@ -{version,"0.1"}. -{{tool,"Cols"}, - {start,{cols,start,[]}}, - {icon,"cols.gif"}, - {message,"Cols - The Game"}}. diff --git a/lib/gs/contribs/cols/help.gif b/lib/gs/contribs/cols/help.gif deleted file mode 100644 index 59baef1fec..0000000000 Binary files a/lib/gs/contribs/cols/help.gif and /dev/null differ diff --git a/lib/gs/contribs/cols/highscore.erl b/lib/gs/contribs/cols/highscore.erl deleted file mode 100644 index 94f68a043a..0000000000 --- a/lib/gs/contribs/cols/highscore.erl +++ /dev/null @@ -1,103 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(highscore). --compile([{nowarn_deprecated_function,{gs,button,2}}, - {nowarn_deprecated_function,{gs,create,3}}, - {nowarn_deprecated_function,{gs,destroy,1}}, - {nowarn_deprecated_function,{gs,grid,2}}, - {nowarn_deprecated_function,{gs,read,2}}, - {nowarn_deprecated_function,{gs,start,0}}, - {nowarn_deprecated_function,{gs,window,2}}]). - --export([run/2]). - -run(NScore, File) -> - Scores = read_scores(File), - case find_pos(NScore, 1, Scores) of - false -> - display(Scores); - Pos -> - NewScores = new_highscore(Scores, Pos, NScore), - write_scores(NewScores,File), - display(NewScores) - end. - - -new_highscore(Scores, Pos, NScore) -> - Txt = io_lib:format("You entered position ~w", [Pos]), - W = gs:create(window, gs:start(), [{width, 200},{height, 110},{map,true}, - {title, "New Highscore!!!"}]), - gs:create(label, W, [{label, {text, Txt}}, {x, 0}, {y,0}, {align, center}, - {width, 190},{height, 30}]), - Entry = gs:create(entry, W, [{x, 0}, {y, 40}, {height, 30}, {width, 200}]), - Ok = gs:create(button, W, [{label, {text, "Ok"}}, {x, 40}, {y, 75}]), - receive - {gs, Ok, click, _,_} -> - T = gs:read(Entry, text), - gs:destroy(W), - lists:sublist(lists:reverse( - lists:keysort(1, [{NScore, T} | Scores])), 1, 10) - end. - - - -read_scores(File) -> - case file:read_file(File) of - {ok, Bin} -> binary_to_term(Bin); - {error, _Reason} -> - mk_empty_high(10) - end. - -mk_empty_high(0) -> []; -mk_empty_high(N) -> [{N,"Erlang"}|mk_empty_high(N-1)]. - -find_pos(_NScore, _N, []) -> false; -find_pos(NScore, N, [{Score, _Name} | Scores]) when Score > NScore -> - find_pos(NScore, N+1, Scores); -find_pos(_NScore, N, _) -> N. - -write_scores(Scores,File) -> - file:write_file(File, term_to_binary(Scores)). - -display(Scores) -> - Win = gs:window(gs:start(), [{width, 300},{height, 250},{map,true}, - {title, "Highscores"}]), - {W,H} = gs:read(Win,{font_wh,{{screen,12},"aaaaaaa"}}), - G = gs:grid(Win,[{rows,{1,11}},{columnwidths,[W,4*W]},{hscroll,false}, - {width, 300},{height, 220},{vscroll,false}, - {cellheight,H+2},{font,{screen,12}}]), - insert_scores(G,2,Scores), - Ok = gs:button(Win, [{label, {text, "OK"}}, {x, 100}, {y, 220}]), - receive - {gs, Ok, click, _,_} -> gs:destroy(Win), - ok - end. - -insert_scores(Grid,_N,[]) -> - gs:create(gridline,Grid,[{row,1},{font,{screen,bold,12}}, - {text,{1,"SCORE"}},{text,{2,"NAME"}}]); - -insert_scores(Grid,Row,[{Score,Name}|Ss]) -> - gs:create(gridline,Grid,[{row,Row},{text,{1,io_lib:format("~w",[Score])}}, - {text,{2,Name}}]), - insert_scores(Grid,Row+1,Ss). - diff --git a/lib/gs/contribs/ebin/.gitignore b/lib/gs/contribs/ebin/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/gs/contribs/mandel/Makefile b/lib/gs/contribs/mandel/Makefile deleted file mode 100644 index b806cc7801..0000000000 --- a/lib/gs/contribs/mandel/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../../vsn.mk -VSN=$(GS_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - mandel - -HRL_FILES= - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES) - -TOOLNAME = mandel - -EXTRA_FILES= $(TOOLNAME).html -TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif -TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%) - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) - -docs: - -clean: - rm -f $(TARGET_FILES) - rm -f core - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).gif $@ - -$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).tool $@ - -$(EBIN)/help.gif: help.gif - $(gen_verbose)rm -f $@ - $(V_at)cp help.gif $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" - $(INSTALL_DIR) "$(RELSYSDIR)/mandel/bitmaps" - $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/mandel/bitmaps" - $(INSTALL_DIR) "$(RELSYSDIR)/mandel" - $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/mandel" - -release_docs_spec: diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl deleted file mode 100644 index e6061ba77d..0000000000 --- a/lib/gs/contribs/mandel/mandel.erl +++ /dev/null @@ -1,351 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(mandel). --compile([{nowarn_deprecated_function,{gs,assq,2}}, - {nowarn_deprecated_function,{gs,config,2}}, - {nowarn_deprecated_function,{gs,create,4}}, - {nowarn_deprecated_function,{gs,image,2}}, - {nowarn_deprecated_function,{gs,start,0}}]). --author('(mbj,eklas)@erlang.ericsson.se'). - -%% User's interface --export([start/0,start/1]). - -%% Internal exports: --export([start_client/2,refresher/1,start_server/1,respond/2]). - -%%%----------------------------------------------------------------- -%%% Distributed Mandelbrot program. -%%% Originally written i C++/rpc/lwp/interviews by Klas Eriksson.(1200 lines) -%%% Rewritten in Erlang by Klas Eriksson and Martin Björklund. -%%%----------------------------------------------------------------- - -%% unix>erl -sname foo (all nodes will get the same name) -%% (foo@data)1>mandel:start([{hosts,["computer1","computer2"]},{window,400}]). - -%% unix>erl -%% 1> mandel:start(). - --record(state,{image,width,height,xmax,ymax,range, - maxiter,colortable,zoomstep}). --record(job,{left,right,ymin,ymax,height,width,maxiter,data=[]}). --define(JOBWIDTH,10). - -%%----------------------------------------------------------------- -%% This is the client start function. -%%----------------------------------------------------------------- -start() -> - start([]). - -%%---------------------------------------------------------------------- -%% Option is list of Option. Option is: -%% {xmax,float()}|{ymax,float()}|{range,float()}| -%% {maxiter,integer()}|{window,integer()}|{zoomstep,float()}| -%% {hosts,(list of string())|all_found_nodes} -%%---------------------------------------------------------------------- -start(Opts) -> - Nodes1 = nodes(), - Nodes = case get_option(hosts,Opts,all_found_nodes) of - all_found_nodes when Nodes1 == [] -> - N = [node()], - spawn(mandel,start_server,[N]), - N; - all_found_nodes -> - start_nodes(dir(),Nodes1), - Nodes1; - Hosts -> - start_slaves(Hosts), - start_nodes(dir(),Nodes1), - Nodes1 - end, - spawn(mandel,start_client,[Opts,Nodes]). - -%% This is not an application so we don't have their way of knowing -%% a private data directory where the GIF files are located (this directory). -%% We can find GS and makes it relative from there /kgb - --define(EbinFromGsPriv,"../contribs/ebin"). - -dir()-> - GsPrivDir = code:priv_dir(gs), - filename:join(GsPrivDir,?EbinFromGsPriv). - - -start_slaves([]) -> ok; -start_slaves([Host|Hs]) -> - {ok,Name}=slave:start(Host), - io:format("host ~p is up~n", [Name]), - start_slaves(Hs). - -start_nodes(_Dir,[]) -> ok; -start_nodes(Dir,[Node|Nodes]) -> - rpc:call(Node,code,add_path,[Dir]), % hack? should be done in .erlang - spawn_link(Node,mandel,start_server,[[node()]]), - io:format("started mandelserver at node: ~p~n", [Node]), - start_nodes(Dir,Nodes). - -start_client(Opts,Nodes) -> - Wt = get_option(window,Opts,100) div ?JOBWIDTH * ?JOBWIDTH, - Ht = get_option(window,Opts,100) div ?JOBWIDTH * ?JOBWIDTH, - S=gs:start(), - Win=gs:create(window,win1,S,[{title,"Mandel"},{width,Wt-1},{height,Ht-1}, - {configure,true}]), - Canvas=gs:create(canvas,can1,Win,[{width,Wt},{height,Ht}]), - Image=gs:image(Canvas,[{buttonpress,true}]), - MaxIters = get_option(maxiter,Opts,100), - timer:apply_after(8000,mandel,refresher,[Image]), - CT = make_color_table(MaxIters), - State2=#state{image=Image,width=Wt,height=Ht, - xmax=try_random(get_option(xmax,Opts,2),-2,2), - ymax=try_random(get_option(ymax,Opts,2),-2,2), - range=try_random(get_option(range,Opts,4),0,4), - maxiter=MaxIters,colortable=CT, - zoomstep=get_option(zoomstep,Opts,1.7)}, - ToDo = make_jobs(State2), - gs:config(Win,[{map,true}]), - main(State2, [], Nodes, ToDo). - -try_random(random,Low,High) -> - random:uniform()*(High-Low)+Low; -try_random(Float,_Low,_High) when is_number(Float) -> Float. - - -%%----------------------------------------------------------------- -%% Distribute work to the nodes. When a node returns, that -%% node is the first to be used if there's any job left. -%%----------------------------------------------------------------- -main(State, [], PassiveNodes, []) -> - wait_event(State,[],PassiveNodes,[]); -main(State, ActiveNodes, PassiveNodes, []) -> - % No jobs left, but some nodes are still active. - % Wait_Event for their results - wait_event(State,ActiveNodes,PassiveNodes,[]); -main(State, ActiveNodes, [Node|PassiveNodes], [Job|ToDo]) -> - % We have work to do, and at least one passive node. - % Let him do it. - distribute_job(Node, Job), - main(State, [Node|ActiveNodes], PassiveNodes, ToDo); -main(State, ActiveNodes, [], ToDo) -> - % We have work to do, but all nodes are active. - _Node = wait_event(State,ActiveNodes,[],ToDo). - -wait_event(State,ActiveNodes,PassiveNodes,ToDo) -> - receive - {calculation_done, {Node, Job}} -> - if % a small hack. we want to discard data for old pictures - Job#job.ymax==State#state.ymax -> - draw(State, Node, Job); - true -> true - end, - main(State,lists:delete(Node,ActiveNodes),[Node|PassiveNodes],ToDo); - {gs,_Img,buttonpress,_Data,[_Butt,X,Y|_]} -> - #state{width=W,height=H,ymax=Ymax,xmax=Xmax,range=R,zoomstep=ZS} = - State, - RX = Xmax-R+(X/W)*R, - RY = Ymax-R+(1-(Y/H))*R, - R2 = R/ZS, - Xmax2 = RX + R2/2, - Ymax2 = RY + R2/2, - State2 = State#state{xmax=Xmax2,ymax=Ymax2,range=R2}, - io:format("{xmax,~w},{ymax,~w},{range,~w}~n", [Xmax2,Ymax2,R2]), - ToDo2=make_jobs(State2), - main(State2,ActiveNodes,PassiveNodes,ToDo2); - {gs,_Win,destroy,_,_} -> - kill_nodes(lists:append(ActiveNodes,PassiveNodes)); - {gs,_Win,configure,_Data,[W,H|_]} - when State#state.width==W+1, State#state.height==H+1-> - main(State,ActiveNodes,PassiveNodes,ToDo); - {gs,_Win,configure,_Data,[W|_]} -> - gs:config(can1,[{width,W},{height,W}]), - gs:config(win1,{configure,false}), - gs:config(win1,[{width,W-1},{height,W-1}]), - gs:config(win1,{configure,true}), - State2 = State#state{width=W,height=W}, - ToDo2=make_jobs(State2), - main(State2,ActiveNodes,PassiveNodes,ToDo2) - end. - -kill_nodes([]) -> - done; -kill_nodes([Node|Nodes]) -> - exit(rpc:call(Node,erlang,whereis,[mandel_server]),kill), - kill_nodes(Nodes). - - -distribute_job(Node, Job) -> - {mandel_server, Node} ! {mandel_job, {self(), Job}}. - -draw(#state{image=Image, width=Wt, height=Ht, xmax=Xmax, - maxiter=MI,colortable=ColorTable,range=R}, Node, Job) -> - #job{left=Left,data=Data}=Job, - io:format("Got data from node ~30w~n", [Node]), -%% PixelX = K * RealX + M -%% 0 = K * Xmin + M -%% Width-1= K * Xmax + M - K=(1-Wt)/-R, - M=Wt-1-K*Xmax, - Xbegin = round(Left*K+M), - draw_cols(Image, Xbegin, Ht, lists:reverse(Data),MI,ColorTable). - -draw_cols(Image, X, Ht, [H|T],MaxIter,ColorTable) -> - draw_col(Image, X, 0, H,MaxIter,ColorTable), - draw_cols(Image, X+1, Ht, T,MaxIter,ColorTable); -draw_cols(_Image, _X, _, [],_MaxIter,_ColorTable) -> - done. - -draw_col(_Image, _X,_Y,[{no_first_color,0}],_MaxIter,_ColorTable) -> - done; -draw_col(Image, X,Y,[{Color,1}|T],MaxIter,ColorTable) -> - gs:config(Image,[{pix_val,{{X,Y}, - element(Color+1,ColorTable)}}]), - draw_col(Image, X,Y+1,T,MaxIter,ColorTable); -draw_col(Image, X,Y,[{Color,Height}|T],MaxIter,ColorTable) -> - gs:config(Image,[{pix_val,{{{X,Y},{X+1,Y+Height}}, - element(Color+1,ColorTable)}}]), - draw_col(Image, X,Y+Height,T,MaxIter,ColorTable). - -make_jobs(#state{width=W,height=H,range=R, - xmax=Xmax,ymax=Ymax,maxiter=MI}) -> - make_jobs(Xmax-R,Xmax,Ymax-R,Ymax,H,W,MI). - -make_jobs(Xmin,Xmax,Ymin,Ymax,Ht,Wt,MaxIter) -> - NoJobs = Wt/?JOBWIDTH, % Each job is ?JOBWIDTH pixel-col - DX = (Xmax - Xmin)/NoJobs, - make_jobs(DX,Xmin,Xmax,#job{ymin=Ymin,ymax=Ymax,height=Ht,width=Wt/NoJobs, - maxiter=MaxIter},[]). - -make_jobs(DX,Left,Xmax,JobSkel,Res) when Left =< Xmax -> - Right = Left + DX, - Job = JobSkel#job{left=Left,right=Right}, - make_jobs(DX,Right,Xmax,JobSkel,[Job | Res]); -make_jobs(_DX,_Left,_Xmax,_JobSkel,Res) -> Res. - -%%---------------------------------------------------------------------- -%% A small process that refreshes the screen now and then. -%%---------------------------------------------------------------------- -refresher(Image) -> - gs:config(Image,flush), - timer:apply_after(8000,mandel,refresher,[Image]). - -%%----------------------------------------------------------------- -%% This is the server start function. -%%----------------------------------------------------------------- -start_server([ClientNode]) -> - register(mandel_server, self()), - erlang:monitor_node(ClientNode, true), - server_loop(). - -server_loop() -> - receive - {mandel_job, {Pid, Job}} -> - spawn_link(mandel, respond, [Pid, Job]), - server_loop() - end. - -respond(Pid, Job) -> - Data = do_job(Job), - Pid ! {calculation_done, {node(), Data}}. - -do_job(Job) -> - calculate_area(Job). - -calculate_area(Job) -> - #job{ymin=Ymin,ymax=Ymax,height=Ht,width=Wt,left=Xmin,right=Xmax}=Job, - Job#job{data=x_loop(0,[],Wt,(Xmax-Xmin)/Wt,(Ymax-Ymin)/Ht,Xmin,Job)}. - -x_loop(IX,Res,Wt,Dx,Dy,X,Job) when IX < Wt -> - #job{ymin=Ymin,height=Ht,maxiter=MaxIter}=Job, - Cols = y_loop(0,Ht,[],MaxIter,Dy,X,Ymin,no_first_color,0), - x_loop(IX+1,[Cols|Res],Wt,Dx,Dy,X+Dx,Job); -x_loop(_,Res,_,_,_,_,_) -> - Res. - -y_loop(IY,Ht,Res,MaxIter,Dy,X,Y,PrevColor,NprevColor) when IY < Ht -> - Color = color_loop(1,MaxIter,0,0,0,0,X,Y), - if - Color == PrevColor -> - y_loop(IY+1,Ht,Res,MaxIter,Dy,X,Y+Dy,PrevColor,NprevColor+1); - true -> - y_loop(IY+1,Ht,[{PrevColor,NprevColor}|Res],MaxIter, - Dy,X,Y+Dy,Color,1) - end; - -y_loop(_,_,Res,_,_,_,_,PC,N) -> - [{PC,N}|Res]. - -color_loop(Color,MaxIter,Za,Zb,Za2,Zb2,X,Y) - when Za2 + Zb2 < 4, Color < MaxIter-> - Ztmp = Za2 - Zb2 + X, - ZbN = 2 * Za * Zb + Y, - color_loop(Color+1,MaxIter,Ztmp,ZbN,Ztmp * Ztmp,ZbN * ZbN,X,Y); -color_loop(MaxIter,MaxIter,_Za,_Zb,_Za2,_Zb2,_X,_Y) -> - 0; % black -color_loop(Color,_,_,_,_,_,_,_) -> - Color. - -%%---------------------------------------------------------------------- -%% The "colormodel". -%%---------------------------------------------------------------------- -make_color_table(MaxColors) -> - list_to_tuple([{0,0,0}|colors(MaxColors)]). - -colors(Ncolors) -> - {A,B,C}=erlang:now(), - random:seed(A,B,C), - Colors = random_colors(Ncolors), - Colors2 = best_insert([hd(Colors)],tl(Colors)), - Colors2. - -random_colors(0) -> []; -random_colors(N) -> - R = random:uniform(256)-1, - G = random:uniform(256)-1, - B = random:uniform(256)-1, - [{R,G,B}|random_colors(N-1)]. - -best_insert(Sorted,[RGB|Unsorted]) -> - best_insert(insert_at(best_pos(RGB,Sorted),RGB,Sorted),Unsorted); -best_insert(Sorted,[]) -> Sorted. - -insert_at(1,Elem,L) -> [Elem|L]; -insert_at(N,Elem,[H|T]) -> [H|insert_at(N-1,Elem,T)]. - -best_pos(RGB, Sorted) -> - D = distances(RGB,Sorted), - pos_for_smallest_distance(D,1,1000,-1). - -pos_for_smallest_distance([],_CurPos,_SmallestDist,Pos) -> Pos; -pos_for_smallest_distance([Dist|T],CurPos,SmallDist,_Pos) - when Dist < SmallDist -> - pos_for_smallest_distance(T,CurPos+1,Dist,CurPos); -pos_for_smallest_distance([_|T],CurPos,Smallest,Pos) -> - pos_for_smallest_distance(T,CurPos+1,Smallest,Pos). - -distances(_RGB,[]) -> - []; -distances({R,G,B},[{R2,G2,B2}|T]) -> - [lists:max([abs(R-R2),abs(G-G2),abs(B-B2)])|distances({R,G,B},T)]. - -get_option(Option, Options, Default) -> - case gs:assq(Option, Options) of - {value, Val} -> Val; - false -> Default - end. diff --git a/lib/gs/contribs/mandel/mandel.gif b/lib/gs/contribs/mandel/mandel.gif deleted file mode 100644 index 49ed1985cb..0000000000 Binary files a/lib/gs/contribs/mandel/mandel.gif and /dev/null differ diff --git a/lib/gs/contribs/mandel/mandel.html b/lib/gs/contribs/mandel/mandel.html deleted file mode 100644 index f69cfa3c6a..0000000000 --- a/lib/gs/contribs/mandel/mandel.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - -

Distributed Mandelbrot program

- -

Originally written i C++/rpc/lwp/interviews by Klas Eriksson.(1200 lines) -
-Rewritten in Erlang by Klas Eriksson and Martin Björklund.

- -

What is the Mandelbrot -function?

- -

A small manual

- -
    -
  • Try starting erlang in distributed mode. The mandel program will use
    -all connected nodes for mandel calculations!
  • - -
  • Resizing the window will restart the calculation.
  • - -
  • Press left mouse button to zoom.
  • -
- -

mandel:start(list of Option) can be used to give the program -different options.

- -


-Available options are:

- -
    -
  • {xmax,float()}
  • - -
  • {ymax,float()}
  • - -
  • {range,float()}|
  • - -
  • {maxiter,integer()}
  • - -
  • {window,integer()}
  • - -
  • {zoomstep,float()}
  • - -
  • {hosts,(list of string())|all_found_nodes}
  • -
- -


-

- - - diff --git a/lib/gs/contribs/mandel/mandel.tool b/lib/gs/contribs/mandel/mandel.tool deleted file mode 100644 index b59941268e..0000000000 --- a/lib/gs/contribs/mandel/mandel.tool +++ /dev/null @@ -1,6 +0,0 @@ -{version,"0.1"}. -{{tool,"Mandel"}, - {start,{mandel,start,[]}}, - {icon,"mandel.gif"}, - {message,"Mandelbrot"}, - {html,"../mandel/mandel.html"}}. diff --git a/lib/gs/contribs/othello/Makefile b/lib/gs/contribs/othello/Makefile deleted file mode 100644 index 8a66e17ec5..0000000000 --- a/lib/gs/contribs/othello/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2012. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../../vsn.mk -VSN=$(GS_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -MODULES= \ - othello \ - othello_adt \ - othello_board - -HRL_FILES= - -ERL_FILES= $(MODULES:%=%.erl) - -TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES) - -TOOLNAME = othello - -EXTRA_FILES= -TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif -TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%) -BITMAPS= priv/marker.bm priv/square.bm - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: $(TARGET_FILES) - -docs: - -clean: - rm -f $(TARGET_FILES) - rm -f core - -# ---------------------------------------------------- -# Special Build Targets -# ---------------------------------------------------- - -$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).gif $@ - -$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool - $(gen_verbose)rm -f $@ - $(V_at)cp $(TOOLNAME).tool $@ - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" - $(INSTALL_DIR) "$(RELSYSDIR)/othello" - $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/othello" - $(INSTALL_DIR) "$(RELSYSDIR)/othello/priv" - $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/othello/priv" - -release_docs_spec: - diff --git a/lib/gs/contribs/othello/othello.erl b/lib/gs/contribs/othello/othello.erl deleted file mode 100644 index c6ad0a76ec..0000000000 --- a/lib/gs/contribs/othello/othello.erl +++ /dev/null @@ -1,237 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(othello). --export([start/0,new_game/4,start1/5]). - - - -%%---------------------------------------------------------------------- -%% The Othello program now uses the gs graphical package instead of the -%% pxw package. See module othello_board for details -%% -%%---------------------------------------------------------------------- - - -start() -> othello_board:start(). - -new_game(Computer,Player,Depth,Init) -> - spawn_link(othello,start1,[self(),Computer,Player,Depth,Init]). - -start1(Win,Computer,Player,Depth,Init) -> - Board = othello_adt:new(t), - random:seed(), - init_display(Board,Win,Init), - play(Computer,Player,Board,Depth,Win,1). - -play(Computer,Player,Board,Depth,Win,NoDs) -> - tell_win(Win,Computer,Player), - case catch continue(Player,Board) of - {game_over,Result} -> - game_over(Board,Player,Result,Win); - {omit_draw,Player} -> - omit(Player,Win), - play(Computer,swap(Player),Board,Depth,Win,NoDs); - ok -> - Draw = choose_draw(Computer,Player,Board,Depth,Win,NoDs), - Win ! {self(),draw,Draw}, - Board1 = othello_adt:set(Draw,Player,Board), - display(Board1,Board,Win), - play(Computer,swap(Player),Board1,Depth,Win,NoDs+1) - end. - -continue(Player,Board) -> - Draws = game_over(Player,Board), - not_allowed(Draws,Player), - ok. - -choose_draw(Computer,Computer,Board,Depth,_Win,NoDs) -> % Depth > 0 !! - {Draw,_Value} = alpha_beta(Depth,Board,-11000,11000,Computer,NoDs), -% io:format('Choosen draw is {~w,~w} : (~w)~n', -% [othello_adt:col(Draw),othello_adt:row(Draw),Value]), -% io:format('=====================~n',[]), - Draw; -choose_draw(Computer,Player,Board,Depth,Win,NoDs) -> - receive - {Win,position,Draw} -> - flush(Win), - case othello_adt:is_draw(Draw,Player,Board) of - false -> - Win ! {self(),illegal_draw,Draw}, - choose_draw(Computer,Player,Board,Depth,Win,NoDs); - true -> - Draw - end - end. - -flush(Win) -> - receive - {Win,position,_} -> - flush(Win) - after 1 -> - true - end. - -tell_win(Win,Computer,Player) -> - Win ! {self(),player,Computer,Player}, - receive - {Win,go_on_play} -> true - end. - -alpha_beta(0,Board,_,_,Player,_) -> - {-1,othello_adt:evaluate_board(Player,Board)}; -alpha_beta(Depth,Board,Alpha,Beta,Player,NoDs) -> - case compute(Player,Board,NoDs) of - [] -> - Player1 = swap(Player), - case compute(Player1,Board,NoDs) of - [] -> - dead_lock(Board,Player); - PosDraws1 -> - choose(PosDraws1,Board,Depth-1,-Beta,-Alpha,-1, - Player1,NoDs) - end; - PosDraws -> - choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs) -% A = choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs), -% io:format('Alpha-Beta (~w) ==> ~w~n',[Depth,A]), -% A - end. - -choose([Draw|Draws],Board,Depth,Alpha,Beta,Record,Player,NoDs) -> - Player1 = swap(Player), - Board1 = othello_adt:set(Draw,Player,Board), -% io:format('Alpha <~w> Beta <~w> ~n',[Alpha,Beta]), - {_,Value} = alpha_beta(Depth,Board1,Alpha,Beta,Player1,NoDs+1), - Value1 = -Value, - cutoff(Draw,Value1,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs); -choose([],_,_,Alpha,_,Draw,_,_) -> - {Draw,Alpha}. - -cutoff(Draw,Value,_,_,Beta,_,_,_,_,_) when Value >= Beta -> - {Draw,Value}; -cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,_,Player,NoDs) - when Alpha < Value, Value < Beta -> - choose(Draws,Board,Depth,Value,Beta,Draw,Player,NoDs); -cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs) - when Value == Alpha, NoDs < 13 -> - choose(Draws,Board,Depth,Alpha,Beta,random_choice(Draw,Record), - Player,NoDs); -cutoff(_Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs) - when Value =< Alpha -> - choose(Draws,Board,Depth,Alpha,Beta,Record,Player,NoDs). - -compute(Player,Board,NoOfDraws) when NoOfDraws < 13 -> - case othello_adt:possible_draws(Player,Board,begin_play) of - [] -> - othello_adt:possible_draws(Player,Board,playing); - Draws -> - Draws - end; -compute(Player,Board,_) -> - othello_adt:possible_draws(Player,Board,playing). - -%%---------------------------------------------------------- -%% Randomly choose between two draws with the same value. -%%---------------------------------------------------------- - -random_choice(Draw,Draw1) -> - case random:uniform(2) of - 1 -> - Draw; - 2 -> - Draw1 - end. - -dead_lock(Board,Player) -> - case win_or_loose(Board,Player) of - 0 -> {-1,0}; - Value when Value > 0 -> {-1,10000}; - _ -> {-1,-10000} - end. - -win_or_loose(Board,Player) -> - Player1 = swap(Player), - othello_adt:pieces(Player,Board) - othello_adt:pieces(Player1,Board). - -game_over(Player,Board) -> - case othello_adt:possible_draws(Player,Board,playing) of - [] -> - Player1 = swap(Player), - case othello_adt:possible_draws(Player1,Board,playing) of - [] -> - throw({game_over,{{Player,othello_adt:pieces(Player,Board)}, - {Player1,othello_adt:pieces(Player1,Board)}}}); - _ -> - [] % Player`s Draws !! - end; - Draws -> - Draws - end. - -game_over(_Board,_Player,Result,Win) -> - Win ! {self(),game_over,white_res(Result),black_res(Result)}. - -white_res({{white,Res},_}) -> Res; -white_res({_,{white,Res}}) -> Res. - -black_res({{black,Res},_}) -> Res; -black_res({_,{black,Res}}) -> Res. - -not_allowed([],Player) -> - throw({omit_draw, Player}); -not_allowed(_,_Player) -> - ok. - -omit(Player,Win) -> - Win ! {self(),omit_draw,Player}, - receive - {Win,continue} -> - ok - end. - -init_display(_Board,_Win,first_time) -> - true; -init_display(Board,Win,_) -> - display(Board,Win). - -display(Board,Win) -> - All = othello_adt:all_pos(Board), - display1(All,Win), - Win ! {self(),score,othello_adt:pieces(white,Board), - othello_adt:pieces(black,Board)}. - -display(Board,OldB,Win) -> - Diff = othello_adt:diff(Board,OldB), - display1(Diff,Win), - Win ! {self(),score,othello_adt:pieces(white,Board), - othello_adt:pieces(black,Board)}. - -display1([{Pos,Colour}|Diff],Win) -> - Win ! {self(),new_mark,Pos,Colour}, - display1(Diff,Win); -display1(_,_) -> - true. - -swap(white) -> black; -swap(black) -> white. - - diff --git a/lib/gs/contribs/othello/othello.gif b/lib/gs/contribs/othello/othello.gif deleted file mode 100644 index 5970c50209..0000000000 Binary files a/lib/gs/contribs/othello/othello.gif and /dev/null differ diff --git a/lib/gs/contribs/othello/othello.tool b/lib/gs/contribs/othello/othello.tool deleted file mode 100644 index 47550a581d..0000000000 --- a/lib/gs/contribs/othello/othello.tool +++ /dev/null @@ -1,6 +0,0 @@ -{version,"0.1"}. -{{tool,"Othello"}, - {start,{othello,start,[]}}, - {icon,"othello.gif"}, - {message,"Othello - The Game"}, - {html,"http://www.armory.com/~iioa/othguide.html"}}. diff --git a/lib/gs/contribs/othello/othello_adt.erl b/lib/gs/contribs/othello/othello_adt.erl deleted file mode 100644 index e69c1c4d72..0000000000 --- a/lib/gs/contribs/othello/othello_adt.erl +++ /dev/null @@ -1,540 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(othello_adt). --compile(export_all). -%%------------------------------------------------------- -%% Use three main states for the strategy: -%% -%% BeginPlay: Stay in the inner square as long as possible. -%% Use the possible_draws/3. -%% -%% MiddlePlay: Try to choose stable markers (?) -%% Use stable/3 -%% -%% EndPlay: Try to flip as many markers as possible -%% -%% The transition from Begin to Middle is obvious. From Middle -%% to End however, is can be discussed. -%%------------------------------------------------------- - -test(N,B) -> - X=new(B), - statistics(wall_clock), - test0(N,X), - {_,T} = statistics(wall_clock), - {time_was,T/N}. - - -test0(0,_) -> true; -test0(N,X) -> - possible_draws(black,X,begin_play), - test0(N-1,X). - -%%------------------------------------------------------- -%% new/1 - returns a new board -%% -%% Uses a tuple for storing the board -%%------------------------------------------------------- - -new(B) -> - Board = mk_board(B), - {ordsets:from_list([18,19,20,21,26,29,34,37,42,43,44,45]),Board}. - -mk_board(t) -> - Tup = list_to_tuple(gen_list(64,grey)), - Tup1 = setelement(28+1, Tup, white), - Tup2 = setelement(35+1, Tup1, white), - Tup3 = setelement(27+1, Tup2, black), - gen_score_board(), - setelement(36+1, Tup3, black). - -gen_list(0,_) -> []; -gen_list(I,Def) -> [Def|gen_list(I-1,Def)]. - -gen_score_board() -> put(score,list_to_tuple(gen_list(64,0))). - -%%------------------------------------------------------- -%% pos(Col,Row) - returns a position describing column -%% and row. -%% Col and Row have the range 1 - 8. -%%------------------------------------------------------- - -pos(Col,Row) -> ((Row - 1) bsl 3) + (Col - 1). - -%%------------------------------------------------------- -%% col(Pos) - returns the column of the Pos position -%%------------------------------------------------------- - -col(Pos) -> (Pos band 7) + 1. - -%%------------------------------------------------------- -%% row(Pos) - returns the row of the Pos position -%%------------------------------------------------------- - -row(Pos) -> (Pos bsr 3) + 1. - -%%------------------------------------------------------- -%% is_draw(Pos,Colour,Board) - returns true if Pos is a -%% correct draw. -%%------------------------------------------------------- - -is_draw(Pos,Colour,{Bset,Board}) -> - case ordsets:is_element(Pos,Bset) of - true -> - case catch is_good(Colour,Pos,Board) of - true -> - true; - _ -> - false - end; - _ -> - false - end. - -%%------------------------------------------------------- -%% set(Pos,Colour,Board) - returns an updated board -%%------------------------------------------------------- - -set(Pos,Colour,{Bset,Board}) -> - case ordsets:is_element(Pos,Bset) of - true -> - NewBoard = setelement(Pos+1,Board,Colour), - Empty = empty_neighbour(Pos,NewBoard), - NewBset = ordsets:union(Empty,ordsets:del_element(Pos,Bset)), - turn(Colour,Pos,{NewBset,NewBoard}); - _ -> - {error,invalid_position} - end. - -empty_neighbour(Pos,Board) -> - ordsets:from_list(empty_neighbour(Pos,Board,deltas())). - -empty_neighbour(_,_,[]) -> []; -empty_neighbour(Pos,Board,[H|T]) -> - case is_empty(Pos+H,dir(Pos,H),Board) of - true -> [Pos+H|empty_neighbour(Pos,Board,T)]; - _ -> empty_neighbour(Pos,Board,T) - end. - -is_empty(_,false,_) -> false; -is_empty(X,_,_Board) when X<0 -> false; -is_empty(X,_,_Board) when X>63 -> false; -is_empty(X,_,Board) -> - case element(X+1,Board) of - grey -> true; % Empty - _ -> false - end. - -%%------------------------------------------------------- -%% get(Pos,Board) - returns the contents in Pos -%%------------------------------------------------------- - -get(Pos,{_Bset,Board}) -> element(Pos+1,Board). - -%%------------------------------------------------------- -%% pieces(Colour,Board) - returns the number of Colour -%% pieces. -%%------------------------------------------------------- - -pieces(Colour,{_Bset,Board}) -> - pieces(Colour,Board,0,0). - -pieces(Colour,Board,Pos,Count) when Pos < 64 -> - case element(Pos+1,Board) of - Colour -> - pieces(Colour,Board,Pos+1,Count+1); - _ -> - pieces(Colour,Board,Pos+1,Count) - end; -pieces(_,_,_,Count) -> - Count. - -%%------------------------------------------------------- -%% possible_draws(Colour, Board, State) -%% -%% Returns a list of possible draws regarding the current -%% strategy state. -%%------------------------------------------------------- - -possible_draws(Colour,{Bset,Board},begin_play) -> - Dset = ordsets:intersection(Bset,inner_square()), - possible_draws_0(Colour,Dset,Board); -possible_draws(Colour,{Bset,Board},_) -> - possible_draws_0(Colour,Bset,Board). - -possible_draws(Colour,{Bset,Board}) -> - possible_draws_0(Colour,Bset,Board). - -possible_draws_0(_,[],_) -> []; -possible_draws_0(Colour,[H|T],Board) -> - case catch is_good(Colour,H,Board) of - true -> [H|possible_draws_0(Colour,T,Board)]; - false -> possible_draws_0(Colour,T,Board) - end. - - -%%------------------------------------------------------- -%% evaluate_board(Colour,Board) - returns the value of -%% the board from Colours -%% point of view. -%%------------------------------------------------------- - -evaluate_board(Colour,{_Bset,Board}) -> - Score = get(score), % Initialized (zeroed) score board !! - Colour1 = swap(Colour), - Score1 = eval_board(Colour,Colour1,Score,Board,0), - Score2 = cnt_corner(0,Score1,Board,Colour,Colour1), - Score3 = cnt_corner(7,Score2,Board,Colour,Colour1), - Score4 = cnt_corner(56,Score3,Board,Colour,Colour1), - Score5 = cnt_corner(63,Score4,Board,Colour,Colour1), - count(Score5,0). -% A = count(Score5,0), -% io:format('Score = ~w~n',[A]), -% A. - -eval_board(MyCol,OtCol,Score,Board,Pos) when Pos < 64 -> - case element(Pos+1,Board) of - MyCol -> - Score1 = setelement(Pos+1,Score,score(Pos)), - eval_board(MyCol,OtCol,Score1,Board,Pos+1); - OtCol -> - Score1 = setelement(Pos+1,Score,-score(Pos)), - eval_board(MyCol,OtCol,Score1,Board,Pos+1); - _ -> - eval_board(MyCol,OtCol,Score,Board,Pos+1) - end; -eval_board(_,_,Score,_,_) -> - Score. - -cnt_corner(Corner,Score,Board,MyCol,OtCol) -> - case element(Corner+1,Board) of - MyCol -> - cnt_corn(Corner,setelement(Corner+1,Score,50), - Board,50,MyCol); - OtCol -> - cnt_corn(Corner,setelement(Corner+1,Score,-50), - Board,-50,OtCol); - _ -> - Score - end. - -cnt_corn(0,Score,Board,Value,Colour) -> - Score1 = cnt_corn(0,1,8,Score,Board,Value,Colour), - cnt_corn(0,8,1,Score1,Board,Value,Colour); -cnt_corn(7,Score,Board,Value,Colour) -> - Score1 = cnt_corn(7,-1,8,Score,Board,Value,Colour), - cnt_corn(7,8,-1,Score1,Board,Value,Colour); -cnt_corn(56,Score,Board,Value,Colour) -> - Score1 = cnt_corn(56,1,-8,Score,Board,Value,Colour), - cnt_corn(56,-8,1,Score1,Board,Value,Colour); -cnt_corn(63,Score,Board,Value,Colour) -> - Score1 = cnt_corn(63,-1,-8,Score,Board,Value,Colour), - cnt_corn(63,-8,-1,Score1,Board,Value,Colour). - -cnt_corn(Pos,Dir,LineDir,Score,Board,Value,Colour) -> - case dir(Pos,Dir) of - Dir -> - NextEdge = Pos+Dir, - case element(NextEdge+1,Board) of - Colour -> - Score1 = setelement(NextEdge+1,Score,Value), - Score2 = cnt_line(NextEdge,LineDir,Score1,Board, - Colour,Value), - cnt_corn(NextEdge,Dir,LineDir,Score2,Board,Value,Colour); - _ -> - Score - end; - _ -> - Score - end. - -cnt_line(Pos,Dir,Score,Board,Colour,Value) -> - case dir(Pos,Dir) of - Dir -> - OnLinePos = Pos+Dir, - case element(OnLinePos+1,Board) of - Colour -> - Score1 = setelement(OnLinePos+1,Score,Value), - cnt_line(OnLinePos,Dir,Score1,Board,Colour,Value); - _ -> - Score - end; - _ -> - Score - end. - -count(Score,Pos) when Pos < 64 -> - element(Pos+1,Score) + count(Score,Pos+1); -count(_,_) -> - 0. - -swap(white) -> black; -swap(black) -> white. - -%%------------------------------------------------------- -%% stable(Colour,Pos,Board) - returns a value 0-8 -%% -%% A high value is regarded as more stable than a lower one. -%% The stability means how many "friendly" neighbours there -%% are, i.e markers of the same colour. Neighbours positions -%% outside the board are regarded as friendly. -%%------------------------------------------------------- - -stable(Colour,Pos,{_,Board}) -> - stable(deltas(),Colour,Pos,Board). - -stable([],_,_,_) -> 0; -stable([H|T],Colour,Pos,Board) -> - stable_val(Colour,Pos,H,Board) + stable(T,Colour,Pos,Board). - -stable_val(_,H,D,_) when H+D<0 -> 1; -stable_val(_,H,D,_) when H+D>63 -> 1; -stable_val(black,H,D,Board) -> - case element((H+D)+1,Board) of - black -> 1; - _ -> 0 - end; -stable_val(white,H,D,Board) -> - case element((H+D)+1,Board) of - white -> 1; - _ -> 0 - end. - -%%------------------------------------------------------- -%% diff(Board,OldBoard) - return a list of the positions -%% with changed pieces. -%% [{Pos1,Colour1},...] -%%------------------------------------------------------- - -diff(Board,OldBoard) -> diff(0,Board,OldBoard). - -diff(Pos,Board,OldBoard) when Pos < 64 -> - OldP = get(Pos,OldBoard), - case get(Pos,Board) of - OldP -> - diff(Pos+1,Board,OldBoard); - NewP -> - [{Pos,NewP}|diff(Pos+1,Board,OldBoard)] - end; -diff(_,_,_) -> - []. - -%%------------------------------------------------------- -%% all_pos(Board) - return a list of the positions colour. -%% [{Pos1,Colour1},...] -%%------------------------------------------------------- - -all_pos(Board) -> all_pos(0,Board). - -all_pos(Pos,Board) when Pos < 64 -> - [{Pos,get(Pos,Board)}|all_pos(Pos+1,Board)]; -all_pos(_,_) -> - []. - -%%------------------------------------------------------- -%% Internal stuff -%%------------------------------------------------------- - -deltas() -> [9,8,7,1,-1,-7,-8,-9]. - -inner_square() -> - [18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]. % Is already an ordset - % Save list traversing. -% ordsets:list_to_set([18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]). - -inv(black) -> white; -inv(white) -> black. - -is_good(Colour,H,Board) -> - is_good_0(Colour,H,dir(H,-9),Board), - is_good_0(Colour,H,dir(H,-8),Board), - is_good_0(Colour,H,dir(H,-7),Board), - is_good_0(Colour,H,dir(H,-1),Board), - is_good_0(Colour,H,dir(H,1),Board), - is_good_0(Colour,H,dir(H,7),Board), - is_good_0(Colour,H,dir(H,8),Board), - is_good_0(Colour,H,dir(H,9),Board), - false. - -is_good_0(_,_,false,_) -> false; -is_good_0(_,H,D,_) when is_integer(H), is_integer(D), H+D<0 -> false; -is_good_0(_,H,D,_) when is_integer(H), is_integer(D), H+D>63 -> false; -is_good_0(black,H,D,Board) when is_integer(H), is_integer(D) -> - case element((H+D)+1,Board) of - white -> is_good_1(black,H+D,dir(H+D,D),Board); - _ -> false - end; -is_good_0(white,H,D,Board) when is_integer(H), is_integer(D) -> - case element((H+D)+1,Board) of - black -> is_good_1(white,H+D,dir(H+D,D),Board); - _ -> false - end. - -is_good_1(_,_,false,_) -> false; -is_good_1(_,H,D,_) when is_integer(H), is_integer(D), H+D<0 -> false; -is_good_1(_,H,D,_) when is_integer(H), is_integer(D), H+D>63 -> false; -is_good_1(black,H,D,Board) when is_integer(H), is_integer(D) -> - case element((H+D)+1,Board) of - white -> is_good_1(black,H+D,dir(H+D,D),Board); - black -> throw(true); - _ -> false - end; -is_good_1(white,H,D,Board) when is_integer(H), is_integer(D) -> - case element((H+D)+1,Board) of - black -> is_good_1(white,H+D,dir(H+D,D),Board); - white -> throw(true); - _ -> false - end. - -%%------------------------------------------------------- -%% turn(Colour,Draw,Board) - returns an updated board -%% turn all possible pieces -%% on the board -%% Neighbours are not changed !! -%%------------------------------------------------------- - -turn(Colour,Draw,{Bset,Board}) -> - {Bset,turn(Colour,Draw,-9, - turn(Colour,Draw,-8, - turn(Colour,Draw,-7, - turn(Colour,Draw,-1, - turn(Colour,Draw,1, - turn(Colour,Draw,7, - turn(Colour,Draw,8, - turn(Colour,Draw,9,Board))))))))}. - -turn(Colour,H,D,Board) -> - case catch is_good_0(Colour,H,dir(H,D),Board) of - true -> - turn_0(Colour,H,D,Board); - false -> - Board - end. - -turn_0(_,H,D,B) when is_integer(H), is_integer(D), H+D<0 -> B; -turn_0(_,H,D,B) when is_integer(H), is_integer(D), H+D>63 -> B; -turn_0(black,H,D,Board) when is_integer(H), is_integer(D) -> - E = H+D, - case element(E+1,Board) of - white -> turn_0(black,H+D,D,swap(black,E,Board)); - _ -> Board - end; -turn_0(white,H,D,Board) when is_integer(H), is_integer(D) -> - E = H+D, - case element(E+1,Board) of - black -> turn_0(white,H+D,D,swap(white,E,Board)); - _ -> Board - end. - -%%------------------------------------------------------- -%% swap(Colour,Pos,Board) - returns an updated board -%% turn a piece on the board -%% Neighbours are not changed !! -%%------------------------------------------------------- - -swap(Colour,Pos,Board) when is_integer(Pos) -> - setelement(Pos+1,Board,Colour). - -score(Pos) -> score1({col(Pos),row(Pos)}). - -score1({Column,1}) when Column >= 3, Column =< 6 -> 20; -score1({Column,8}) when Column >= 3, Column =< 6 -> 20; -score1({1,Line}) when Line >= 3, Line =< 6 -> 20; -score1({8,Line}) when Line >= 3, Line =< 6 -> 20; -score1({Column,2}) when Column >= 3, Column =< 6 -> -7; -score1({Column,7}) when Column >= 3, Column =< 6 -> -7; -score1({2,Line}) when Line >= 3, Line =< 6 -> -7; -score1({7,Line}) when Line >= 3, Line =< 6 -> -7; -score1({Column,Line}) when Column >= 3, Column =< 6, - Line >= 3, Line =< 6 -> 1; -score1({1,1}) -> 100; -score1({1,8}) -> 100; -score1({8,1}) -> 100; -score1({8,8}) -> 100; -score1({2,1}) -> -30; -score1({7,1}) -> -30; -score1({1,2}) -> -30; -score1({8,2}) -> -30; -score1({1,7}) -> -30; -score1({8,7}) -> -30; -score1({2,8}) -> -30; -score1({7,8}) -> -30; -score1({2,2}) -> -50; -score1({7,2}) -> -50; -score1({2,7}) -> -50; -score1({7,7}) -> -50. - -%%------------------------------------------------------- -%% dir(Pos,Dir) - return Dir if allowed direction at Pos. -%% else return false. -%%------------------------------------------------------- - -dir(0,1) -> 1; % {1,1} -dir(0,8) -> 8; -dir(0,9) -> 9; -dir(0,_) -> false; - -dir(7,-1) -> -1; % {8,1} -dir(7,7) -> 7; -dir(7,8) -> 8; -dir(7,_) -> false; - -dir(56,-8) -> -8; % {1,8} -dir(56,-7) -> -7; -dir(56,1) -> 1; -dir(56,_) -> false; - -dir(63,-9) -> -9; % {8,8} -dir(63,-8) -> -8; -dir(63,-1) -> -1; -dir(63,_) -> false; - -dir(Pos,-1) when (Pos bsr 3) == 0 -> -1; % {_,1} -dir(Pos,1) when (Pos bsr 3) == 0 -> 1; -dir(Pos,7) when (Pos bsr 3) == 0 -> 7; -dir(Pos,8) when (Pos bsr 3) == 0 -> 8; -dir(Pos,9) when (Pos bsr 3) == 0 -> 9; -dir(Pos,_) when (Pos bsr 3) == 0 -> false; - -dir(Pos,-9) when (Pos bsr 3) == 7 -> -9; % {_,8} -dir(Pos,-8) when (Pos bsr 3) == 7 -> -8; -dir(Pos,-7) when (Pos bsr 3) == 7 -> -7; -dir(Pos,-1) when (Pos bsr 3) == 7 -> -1; -dir(Pos,1) when (Pos bsr 3) == 7 -> 1; -dir(Pos,_) when (Pos bsr 3) == 7 -> false; - -dir(Pos,-8) when (Pos band 7) == 0 -> -8; % {1,_} -dir(Pos,-7) when (Pos band 7) == 0 -> -7; -dir(Pos,1) when (Pos band 7) == 0 -> 1; -dir(Pos,8) when (Pos band 7) == 0 -> 8; -dir(Pos,9) when (Pos band 7) == 0 -> 9; -dir(Pos,_) when (Pos band 7) == 0 -> false; - -dir(Pos,-9) when (Pos band 7) == 7 -> -9; % {8,_} -dir(Pos,-8) when (Pos band 7) == 7 -> -8; -dir(Pos,-1) when (Pos band 7) == 7 -> -1; -dir(Pos,7) when (Pos band 7) == 7 -> 7; -dir(Pos,8) when (Pos band 7) == 7 -> 8; -dir(Pos,_) when (Pos band 7) == 7 -> false; - -dir(_Pos,Dir) -> Dir. - diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl deleted file mode 100644 index cc055b1fa1..0000000000 --- a/lib/gs/contribs/othello/othello_board.erl +++ /dev/null @@ -1,649 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(othello_board). --compile([{nowarn_deprecated_function,{gs,config,2}}, - {nowarn_deprecated_function,{gs,create,3}}, - {nowarn_deprecated_function,{gs,create,4}}, - {nowarn_deprecated_function,{gs,destroy,1}}, - {nowarn_deprecated_function,{gs,start,0}}]). - --export([start/0,stop/0,init/0]). - - -%%---------------------------------------------------------------------- -%% The Othello program now uses the gs graphical package instead of the -%% pxw package. -%% -%% Differences are, explanation why and source of change in parenthesis: -%% -%% - Buttons looks different (gs feature) -%% - The black box around "Black to draw" have been removed. (me) -%% - The Colour and Level menues have been moved directly down to the -%% 'Status' box. (usability update, my addition) -%% - The mouse pointer does not change into a watch when the computer -%% is thinking (not supported in gs) -%% - Buttons does not flash when being beeped. (not supported in gs) -%% -%% -%% /Peter -%% -%%---------------------------------------------------------------------- - - --define(BGCOL,forestgreen). - -start() -> - spawn(othello_board,init,[]). - -stop() -> - ok. - -%% This is not an application so we don't have their way of knowing -%% a private data directory where the GIF files are located (this directory). -%% We can find GS and makes it relative from there /kgb - --define(BitmapPath,"../contribs/othello/priv"). - -setup_path() -> - GsPrivDir = code:priv_dir(gs), - Path = filename:join(GsPrivDir,?BitmapPath), - put(path,Path). - -path() -> get(path). - - - -%% -%% The button area are the Quit, Rules buttons at the top of the window. -%% The Status area is the black and white scores level and colour etc -%% inbetween the buttons and the othello board. -%% The board is the 8x8 board where othello battles are fought. -%% -init() -> - process_flag(trap_exit,true), - setup_path(), - S = gs:start(), - put(windowroot,S), % Ugly global store - - %% Shell coordinates - W = 496, - H = 636, - - %% Fix top window - Shell = gs:create(window, S, [{title,"Othello"}, - {width, W},{height, H}]), - - - %% Setup window contents - - setup_buttons(Shell,0,0,W,40), % Fix Menubar - setup_status_box(Shell,0,40,W,100), % Fix Status area - setup_board(Shell,0,140,496,496), % Combat board - - GamePid = othello:new_game(white,black,1,first_time), - - %% Default settings - Options = {white,black,1}, - %%Wids = {Status,B,W,Dr,Le,Co}, - Wids = {change,this,at,later,stage,ponto}, - write_options(Options,Wids), - - gs:config(Shell, {map, true}), %Make win visible - - loop(computer,GamePid,Shell,Wids,Options). - - - - - - -loop(User,GamePid,Shell,Wids,Options) -> - receive - {gs,ButtId, click,_ButtId1,[Button]} -> - GamePid1 = but_pressed(Button,ButtId,User,GamePid,Shell, - Wids,Options), - loop(User,GamePid1,Shell,Wids,Options); - - {gs,_, click,_,[MenuItem,_MenuIndex]} -> - Ops = menu_selected(MenuItem,User,GamePid,Wids,Options), - loop(User,GamePid,Shell,Wids,Ops); - - {'EXIT',GamePid,_} -> - loop(User,null,Shell,Wids,Options); - - {'EXIT',_,_} -> - loop(User,GamePid,Shell,Wids,Options); - - GameMsg -> - game_msg(GameMsg,User,GamePid,Shell,Wids,Options) - end. - -but_pressed("Quit",_ButtId,_User,_GamePid,_Shell,_Wids,_Op) -> - stop(), - exit(quit); -but_pressed("Rules",_ButtId,_User,GamePid,_Shell,_Wids,_Op) -> - io:format("No rules, do as you wish~n",[]), - GamePid; -but_pressed("Help",_ButtId,_User,GamePid,_Shell,_Wids,_Op) -> - io:format("Othello game~n",[]), - io:format("------------~n",[]), - io:format(" Put markers by clicking in squares~n",[]), - io:format(" Change level by clicking on it~n",[]), - io:format(" Change colour by clicking on it~n",[]), - io:format("~n",[]), - GamePid; -but_pressed("Newgame",_ButtId,_User,GamePid,_Shell,Wids,Options) -> - new_game(GamePid,Wids,Options); -but_pressed([],ButtId,User,GamePid,_Shell,_Wids,_Op) - when is_pid(GamePid),User == player -> - [C,R] = atom_to_list(ButtId), - GamePid ! {self(),position,othello_adt:pos(C-96,translate(R-48))}, - GamePid; -but_pressed([],ButtId,_User,GamePid,_Shell,_Wids,_Op) -> - [C,R] = atom_to_list(ButtId), - beep(othello_adt:pos(C-96,translate(R-48))), - GamePid; -but_pressed(Button,ButtId,_User,GamePid,_Shell,_Wids,_Op) -> - io:format('Not implemented button pressed ~p, ~p!!!~n',[ButtId,Button]), - GamePid. - -menu_selected("Black",_User,_GamePid,Wids,Options) -> - Op0 = setelement(1,Options,white), - Op1 = setelement(2,Op0,white), - write_options(Op1,Wids), - Op1; -menu_selected("White",_User,_GamePid,Wids,Options) -> - Op0 = setelement(1,Options,black), - Op1 = setelement(2,Op0,black), - write_options(Op1,Wids), - Op1; -menu_selected("Black (begin)",_User,_GamePid,Wids,Options) -> - Op0 = setelement(1,Options,white), - Op1 = setelement(2,Op0,black), - write_options(Op1,Wids), - Op1; -menu_selected("White (begin)",_User,_GamePid,Wids,Options) -> - Op0 = setelement(1,Options,black), - Op1 = setelement(2,Op0,white), - write_options(Op1,Wids), - Op1; -menu_selected("Beginner",_User,_GamePid,Wids,Options) -> - Op1 = setelement(3,Options,1), - write_options(Op1,Wids), - Op1; -menu_selected("Intermediate",_User,_GamePid,Wids,Options) -> - Op1 = setelement(3,Options,2), - write_options(Op1,Wids), - Op1; -menu_selected("Advanced",_User,_GamePid,Wids,Options) -> - Op1 = setelement(3,Options,3), - write_options(Op1,Wids), - Op1; -menu_selected("Expert",_User,_GamePid,Wids,Options) -> - Op1 = setelement(3,Options,4), - write_options(Op1,Wids), - Op1; -menu_selected(What,_User,_GamePid,_Wids,Options) -> - io:format('Menu item not implemented <~s>~n',[What]), - Options. - -game_msg(Msg,User,GamePid,Shell,Wids,Options) -> - case Msg of - {GamePid,new_mark,Pos,Colour} -> - new_mark(Pos,Colour), - loop(User,GamePid,Shell,Wids,Options); - - {GamePid,illegal_draw,Draw} -> - beep(Draw), - loop(User,GamePid,Shell,Wids,Options); - - {GamePid,player,Computer,Computer} -> - show_player(element(1,Wids),Computer), - cursor("watch"), - GamePid ! {self(),go_on_play}, - loop(computer,GamePid,Shell,Wids,Options); - - {GamePid,player,_Computer,Player} -> - show_player(element(1,Wids),Player), - cursor("top_left_arrow"), - GamePid ! {self(),go_on_play}, - loop(player,GamePid,Shell,Wids,Options); - - {GamePid,omit_draw,Player} -> - omit_draw(GamePid,Player), - loop(User,GamePid,Shell,Wids,Options); - - {GamePid,score,WhiteRes,BlackRes} -> - write_score(Wids,WhiteRes,BlackRes), - loop(User,GamePid,Shell,Wids,Options); - - {GamePid,draw,Draw} -> - write_draw(Wids,Draw), - loop(User,GamePid,Shell,Wids,Options); - - {GamePid,game_over,WhiteRes,BlackRes} -> - game_over(WhiteRes,BlackRes), - loop(User,GamePid,Shell,Wids,Options); - - What -> - io:format('game_msg received: ~w~n',[What]), - loop(User,GamePid,Shell,Wids,Options) - end. - - -new_game(GamePid,Wids,Options) when is_pid(GamePid) -> - exit(GamePid,kill), - new_game(Wids,Options); -new_game(_,Wids,Options) -> - new_game(Wids,Options). - -new_game(_Wids,Options) -> - label("",lastdraw), - Computer = element(1,Options), - Start = element(2,Options), - Depth = element(3,Options), - othello:new_game(Computer,Start,Depth,restart). - -new_mark(Pos,Colour) -> - Col = othello_adt:col(Pos), - Row = othello_adt:row(Pos), - Name = [Col+96,translate(Row)+48], - Button = get(Name), - butbit(Button,Colour). - -beep(Draw) -> - Col = othello_adt:col(Draw), - Row = othello_adt:row(Draw), - Name = [Col+96,translate(Row)+48], - Button = get(Name), - bell(Button). - -show_player(_Status,white) -> - label("White to draw",todraw); -show_player(_Status,black) -> - label("Black to draw",todraw). - -write_score(_Wids,WhiteRes,BlackRes) -> - label(integer_to_list(BlackRes),bscore), - label(integer_to_list(WhiteRes),wscore). - -write_draw(_Wids,Draw) -> - Col = othello_adt:col(Draw), - Row = othello_adt:row(Draw), - label(lists:flatten(io_lib:format('{~w,~w}',[Col,Row])), lastdraw). - -write_options(Options,Wids) -> - write_colour(Options,Wids), - write_level(Options,Wids). - -write_colour(Options,Wids) -> - write_colour(element(1,Options),element(2,Options),Wids). - -write_colour(black,white,_Wids) -> label("White (begin)",colour); -write_colour(black,black,_Wids) -> label("White",colour); -write_colour(white,black,_Wids) -> label("Black (begin)",colour); -write_colour(white,white,_Wids) -> label("Black",colour). - -write_level(Options,_Wids) -> - case element(3,Options) of - 1 -> label("Beginner",level); - 2 -> label("Intermediate",level); - 3 -> label("Advanced",level); - 4 -> label("Expert",level) - end. - -cursor(_What) -> - done. -%cursor(What) -> cursor(get(),What). - -%cursor([{[C,R],Button}|Buts],What) -> -% set_widget(Button,"cursor",What), -% cursor(Buts,What); -%cursor([_|Buts],What) -> -% cursor(Buts,What); -%cursor([],_) -> -% true. - -translate(1) -> 8; -translate(2) -> 7; -translate(3) -> 6; -translate(4) -> 5; -translate(5) -> 4; -translate(6) -> 3; -translate(7) -> 2; -translate(8) -> 1. - -bitmap(grey) -> bitmap_path("square.bm"); -bitmap(black) -> bitmap_path("marker.bm"); -bitmap(white) -> bitmap_path("marker.bm"). - -bitmap_path(Bitmap) -> - filename:join(path(),Bitmap). - -xy_position([[Letter,Digit],_,_]) -> - LettPos = Letter - 97, - X = LettPos*60 , - Y = (8 - list_to_integer([Digit])) * 60, - {X+6,Y+6}; -xy_position(X) -> - io:format("xy_position: ~w~n",[{error,X}]). - - -board() -> - [["a1",grey,nil], - ["b1",grey,nil], - ["c1",grey,nil], - ["d1",grey,nil], - ["e1",grey,nil], - ["f1",grey,nil], - ["g1",grey,nil], - ["h1",grey,nil], - - ["a2",grey,nil], - ["b2",grey,nil], - ["c2",grey,nil], - ["d2",grey,nil], - ["e2",grey,nil], - ["f2",grey,nil], - ["g2",grey,nil], - ["h2",grey,nil], - - ["a3",grey,nil], - ["b3",grey,nil], - ["c3",grey,nil], - ["d3",grey,nil], - ["e3",grey,nil], - ["f3",grey,nil], - ["g3",grey,nil], - ["h3",grey,nil], - - ["a4",grey,nil], - ["b4",grey,nil], - ["c4",grey,nil], - ["d4",white,nil], - ["e4",black,nil], - ["f4",grey,nil], - ["g4",grey,nil], - ["h4",grey,nil], - - ["a5",grey,nil], - ["b5",grey,nil], - ["c5",grey,nil], - ["d5",black,nil], - ["e5",white,nil], - ["f5",grey,nil], - ["g5",grey,nil], - ["h5",grey,nil], - - ["a6",grey,nil], - ["b6",grey,nil], - ["c6",grey,nil], - ["d6",grey,nil], - ["e6",grey,nil], - ["f6",grey,nil], - ["g6",grey,nil], - ["h6",grey,nil], - - ["a7",grey,nil], - ["b7",grey,nil], - ["c7",grey,nil], - ["d7",grey,nil], - ["e7",grey,nil], - ["f7",grey,nil], - ["g7",grey,nil], - ["h7",grey,nil], - - ["a8",grey,nil], - ["b8",grey,nil], - ["c8",grey,nil], - ["d8",grey,nil], - ["e8",grey,nil], - ["f8",grey,nil], - ["g8",grey,nil], - ["h8",grey,nil]]. - - -omit_draw(GamePid,Player) -> -% %% Find mouse coords first -% %% This was not possible in gs - - W = 200, H = 100, Root = get(windowroot), - Box = gs:create(window, Root, [{title,"OMIT"}, {width, W},{height, H}]), - - mk_label_c(lists:flatten(io_lib:format('~w has to omit draw !',[Player])), - Box, W, 10), - - mk_button_c("Ok", Box, W, H-40, 80, 30), - - gs:config(Box, {map, true}), %Make win visible - - receive - {gs,_, click,_,["Ok"]} -> - gs:destroy(Box), - GamePid ! {self(),continue} - end. - -game_over(WhiteRes,BlackRes) -> -% %% Find mouse coords first -% %% This was not possible in gs - - W = 200, H = 160, - Root = get(windowroot), - Box = gs:create(window, Root, [{title,"GAME OVER"}, - {width, W},{height, H}]), - - mk_label_c("GAME OVER", Box, W, 10), - - mk_label_c(lists:flatten(io_lib:format('White score: ~w',[WhiteRes])), - Box,W,40), - mk_label_c(lists:flatten(io_lib:format('Black score: ~w',[BlackRes])), - Box,W,70), - - mk_button_c("Ok", Box, W, H-40, 80, 30), - - gs:config(Box, {map, true}), %Make win visible - - receive - {gs,_, click,_,["Ok"]} -> - gs:destroy(Box) - end. - - - -%% ---------------------------------------------------------------- -%% Library functions. -%% ---------------------------------------------------------------- - -bell(Widget) -> - %% gs does not support bells, - Widget. - -label(Text,Label) -> - gs:config(Label,[{label,{text,Text}}]). - -%% mk_label in centered version -mk_label_c(Label,Parent,Width,Y) -> - W = 8*length(Label), - X = trunc((Width-W)/2), - gs:create(label,Parent,[{width,W}, {height, 20}, {x,X}, {y,Y}, - {label, {text, Label}}]). - - - - -setup_buttons(Shell,X,Y,W,H) -> - ButBox = gs:create(frame, Shell,[{x,X}, {y,Y},{bg,white}, - {width,W}, {height,H}]), - C = gs:create(canvas,ButBox,[{x,X}, {y,Y}, {width, W}, {height, H}, - {bg,white}]), - gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]), - - - mk_button("Quit",ButBox, 10, 10, 70, 20), - mk_button("Rules",ButBox, 80, 10, 70, 20), - mk_button("Newgame",ButBox, 150, 10, 70, 20), - mk_button("Help",ButBox, 220, 10, 70, 20), -%% mk_button("Level",ButBox, 290, 10, 70, 20), - - done. - - - - - -%%---------------------------------------- -%% Sets up the middle window w. all the status info in. -%% The labels are given names: -%% bscore, wscore, lastdraw, todraw, level and colour to simplify -%% their frequent setting -%% -setup_status_box(Shell,X,Y,W,H) -> - F = gs:create(frame, Shell,[{x,X}, {y,Y}, - {width,W}, {height,H},{bg,white}]), - C = gs:create(canvas,F,[{x,0}, {y,0}, {width, W}, {height, H},{bg,white}]), - gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]), - - %% Left side - gs:create(label,F,[{align,w},{x,10}, {y,5}, {width, 100}, - {label,{text, "Black score:"}},{bg,white}]), - gs:create(label,bscore,F,[{align,w},{x,110}, {y,5}, {width, 40}, - {label,{text, "2"}},{bg,white}]), - gs:create(label,F,[{align,w},{x,10}, {y,35}, {width, 100}, - {label,{text, "White score:"}},{bg,white}]), - gs:create(label,wscore,F,[{align,w},{x,110}, {y,35}, {width, 40}, - {label,{text, "2"}},{bg,white}]), - gs:create(label,F,[{align,w},{x,10}, {y,65}, {width, 100}, - {label,{text, "Last draw:"}},{bg,white}]), - gs:create(label,lastdraw,F,[{align,w},{x,110}, {y,65}, {width, 40}, - {label,{text, ""}},{bg,white}]), - - - %% Right side - X2 = trunc(W/2)+10, - gs:create(label,todraw,F,[{align,w},{x,X2}, {y,5}, {width, 100}, - {label,{text, "Black to draw:"}},{bg,white}]), - - gs:create(label,F,[{align,w},{x,X2}, {y,35}, {width, 80}, - {label,{text, "Level:"}},{bg,white}]), - setup_level_menu(F,X2+80,35), - -%% gs:create(label,level,F,[{align,w},{x,X2+80}, {y,35}, {width, 130}, -%% {label,{text, "Intermediate"}},{bg,white}]), - gs:create(label,F,[{align,w},{x,X2}, {y,65}, {width, 80}, - {label,{text, "Colour:"}},{bg,white}]), - setup_col_menu(F,X2+80,65), - -%% gs:create(label,colour,F,[{align,w},{x,X2+80}, {y,65}, {width, 120}, -%% {label,{text, "black (begin)"}},{bg,white}]), - - done. - - -setup_col_menu(P,X,Y) -> - MB = gs:create(menubutton,colour,P, - [{x,X}, {y,Y}, {bw,3}, - %%{width,W}, {height,H}, - {align,w}, {bg,white}, - {relief, raised}, - {activefg,white}, {activebg,black}, - {label, {text,"Colours"}}]), - - M = gs:create(menu,MB,[]), - gs:create(menuitem,M,[{label,{text,"Black (begin)"}}]), - gs:create(menuitem,M,[{label,{text,"Black"}}]), - gs:create(menuitem,M,[{label,{text,"White (begin)"}}]), - gs:create(menuitem,M,[{label,{text,"White"}}]), - done. - -setup_level_menu(P,X,Y) -> - MB = gs:create(menubutton,level,P, - [{x,X}, {y,Y}, - %%{width,W}, {height,H}, - {relief, raised}, - {activefg,white}, {activebg,black}, - {align,w}, {bg,white}, - {label, {text,"Colours"}}]), - - M = gs:create(menu,MB,[]), - gs:create(menuitem,M,[{label,{text,"Beginner"}}]), - gs:create(menuitem,M,[{label,{text,"Intermediate"}}]), - gs:create(menuitem,M,[{label,{text,"Advanced"}}]), - gs:create(menuitem,M,[{label,{text,"Expert"}}]), - done. - - -setup_board(Shell,X,Y,W,H) -> - F = gs:create(frame, Shell,[{x,X}, {y,Y}, - {width,W}, {height,H},{bg,white}]), - display_board(F). - - -mk_button(Label, Parent, X, Y, W, H) -> - gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y}, - {label, {text, Label}}, {bg,white}, - {activefg,white}, {activebg,black}]). - -%% Centers a button around Width -mk_button_c(Label, Parent, Width, Y, W, H) -> - X = trunc((Width-W)/2), - gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y}, - {label, {text, Label}}, {bg,white}]). - - -butbit(Button,Col) -> - gs:config(Button,[ - {label,{image,bitmap(Col)}}, - {fg, Col}, - {activefg,Col}, - {label, {image, bitmap(Col)}}]), - Button. - -mk_board_butt(Top,Name,X,Y,Col) -> - B = gs:create(button,list_to_atom(Name), Top, - [{x,X}, {y,Y}, {width,60}, {height,60}, - {padx,5},{pady,5}, - {relief,flat}, - {bg,?BGCOL}, {activebg,?BGCOL}]), - butbit(B,Col), - B. - - - -display_board(Top) -> - Board = board(), - display_board(Top,Board,1). - -display_board(_,_,65) -> true; -display_board(Top,[H|T],Place) -> - [Name,Colour,_] = H, - {X,Y} = xy_position(H), - Button = mk_board_butt(Top,Name,X,Y,Colour), - %%Button = mk_button("",Name,Top,X,Y,60,60), - put(Name,Button), - %%Bitmap = bitmap(Colour), - %%butbit(Button,Bitmap), - %%set_widget(Button,"internalWidth","1"), - %%set_widget(Button,"internalHeight","1"), - %%borderWidth(2,Button), - display_board(Top,T,Place+1). - - diff --git a/lib/gs/contribs/othello/priv/marker.bm b/lib/gs/contribs/othello/priv/marker.bm deleted file mode 100644 index fe7f3df820..0000000000 --- a/lib/gs/contribs/othello/priv/marker.bm +++ /dev/null @@ -1,43 +0,0 @@ -#define marker2_width 60 -#define marker2_height 60 -static unsigned char marker2_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, - 0xff, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, - 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, - 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0xc0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00, - 0x00, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xcf, 0x1f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xc7, 0x0f, 0x00, - 0x00, 0xfc, 0xff, 0xff, 0xff, 0xe7, 0x07, 0x00, 0x00, 0xf8, 0xff, 0xff, - 0x7f, 0xf1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xbf, 0xfc, 0x03, 0x00, - 0x00, 0xf0, 0xff, 0xff, 0x59, 0xff, 0x01, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/othello/priv/square.bm b/lib/gs/contribs/othello/priv/square.bm deleted file mode 100644 index 4e6880b330..0000000000 --- a/lib/gs/contribs/othello/priv/square.bm +++ /dev/null @@ -1,43 +0,0 @@ -#define square_width 60 -#define square_height 60 -static unsigned char square_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -- cgit v1.2.3 From 38e8ab99454f69acab55e5bcb575ed60a8b72c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Dec 2015 15:10:27 +0100 Subject: common_test tests: Replace 'random' with 'rand' --- lib/common_test/test/ct_master_SUITE.erl | 2 +- lib/common_test/test/ct_test_support.erl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl index 15b49c67c0..55837352e2 100644 --- a/lib/common_test/test/ct_master_SUITE.erl +++ b/lib/common_test/test/ct_master_SUITE.erl @@ -135,7 +135,7 @@ make_spec(DataDir, FileName, NodeNames, Suites, Config) -> C = lists:map( fun(NodeName) -> - Rnd = random:uniform(2), + Rnd = rand:uniform(2), if Rnd == 1-> {config,NodeName,filename:join(DataDir, "master/config.txt")}; diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 248ec6c4df..4a47d345e9 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -414,14 +414,14 @@ ct_rpc({M,F,A}, Config) -> %%%----------------------------------------------------------------- %%% random_error/1 random_error(Config) when is_list(Config) -> - random:seed(os:timestamp()), + rand:seed(exsplus), Gen = fun(0,_) -> ok; (N,Fun) -> Fun(N-1, Fun) end, - Gen(random:uniform(100), Gen), + Gen(rand:uniform(100), Gen), ErrorTypes = ['BADMATCH','BADARG','CASE_CLAUSE','FUNCTION_CLAUSE', 'EXIT','THROW','UNDEF'], - Type = lists:nth(random:uniform(length(ErrorTypes)), ErrorTypes), - Where = case random:uniform(2) of + Type = lists:nth(rand:uniform(length(ErrorTypes)), ErrorTypes), + Where = case rand:uniform(2) of 1 -> io:format("ct_test_support *returning* error of type ~w", [Type]), -- cgit v1.2.3 From 983642a38b3627425f77fc6f8b8ccd121fd41f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Dec 2015 13:18:20 +0100 Subject: percept tests: Replace 'random' with 'rand' --- lib/percept/test/egd_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/percept/test/egd_SUITE.erl b/lib/percept/test/egd_SUITE.erl index 41e8999e17..5a0a9af14d 100644 --- a/lib/percept/test/egd_SUITE.erl +++ b/lib/percept/test/egd_SUITE.erl @@ -40,7 +40,7 @@ -define(default_timeout, ?t:minutes(1)). init_per_suite(Config) when is_list(Config) -> - random:seed(now()), + rand:seed(exsplus), Config. end_per_suite(Config) when is_list(Config) -> @@ -348,4 +348,4 @@ get_points(0, Out) -> get_points(N, Out) -> get_points(N - 1, [get_point() | Out]). -random(N) -> trunc(random:uniform(trunc(N + 1)) - 1). +random(N) -> trunc(rand:uniform(trunc(N + 1)) - 1). -- cgit v1.2.3 From a16ad650d3f9cca03dbc1cf542e9f1ca7dd0a7e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 11 Dec 2015 14:30:01 +0100 Subject: mnesia tests: Replace 'random' with 'rand' --- lib/mnesia/test/mnesia_consistency_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mnesia/test/mnesia_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl index 087aef86c9..279e7bc1ec 100644 --- a/lib/mnesia/test/mnesia_consistency_test.erl +++ b/lib/mnesia/test/mnesia_consistency_test.erl @@ -696,7 +696,7 @@ consistency_after_restore(ReplicaType, Op, Config) -> ?verify_mnesia(Nodes, []). change_tab(Father, Tab, Test) -> - Key = random:uniform(20), + Key = rand:uniform(20), Update = fun() -> case mnesia:read({Tab, Key}) of [{Tab, Key, 1}] -> -- cgit v1.2.3 From 61fd09aaef2474cd74ddbc465e9d1dfd879a4ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 4 Dec 2015 12:04:12 +0100 Subject: Deprecate the 'random' module The 'rand' module was introduced in OTP 18 and its use is discouraged. Deprecate it to further discourage its use. --- lib/stdlib/src/otp_internal.erl | 6 ++++++ lib/stdlib/src/random.erl | 1 + 2 files changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 90ef364d1a..166eb3cef2 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -639,6 +639,12 @@ obsolete_1(httpd_conf, is_file, 1) -> obsolete_1(httpd_conf, make_integer, 1) -> {deprecated, "deprecated; use erlang:list_to_integer/1 instead"}; +%% Added in OTP 19. + +obsolete_1(random, _, _) -> + {deprecated, "the 'random' module is deprecated; " + "use the 'rand' module instead"}; + obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl index 8b67cde56c..8b639dd0a7 100644 --- a/lib/stdlib/src/random.erl +++ b/lib/stdlib/src/random.erl @@ -18,6 +18,7 @@ %% %CopyrightEnd% %% -module(random). +-deprecated(module). %% Reasonable random number generator. %% The method is attributed to B. A. Wichmann and I. D. Hill -- cgit v1.2.3 From 3131a94b5d2ce2b95aa0efb99c767e3658f24550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 11 Dec 2015 16:25:34 +0100 Subject: Remove the code path cache in the code server In practice, it does not seem that code path cache can improve performance. Looking for any file that is not found will cause the cache to be rebuilt, which will negate any gain of using the cache. --- lib/kernel/doc/src/code.xml | 36 +-------- lib/kernel/src/code.erl | 45 ++++++----- lib/kernel/src/code_server.erl | 170 ++++----------------------------------- lib/kernel/test/code_SUITE.erl | 172 +--------------------------------------- lib/stdlib/src/otp_internal.erl | 2 + 5 files changed, 47 insertions(+), 378 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index eb0f4b7a06..acc39145e2 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -100,30 +100,6 @@ use semi-colon as separator.)

-
- Code Path Cache -

The code server incorporates a code path cache. The cache - functionality is disabled by default. To activate it, start - the emulator with the command line flag -code_path_cache - or call code:rehash(). When the cache is created (or - updated), the code server searches for modules in the code path - directories. This may take some time if the the code path is long. - After the cache creation, the time for loading modules in a large - system (one with a large directory structure) is significantly - reduced compared to having the cache disabled. The code server - is able to look up the location of a module from the cache in - constant time instead of having to search through the code path - directories.

-

Application resource files (.app files) are also stored - in the code path cache. This feature is used by the application - controller (see - application(3)) to load - applications efficiently in large systems.

-

Note that when the code path cache is created (or updated), any - relative directory names in the code path are converted to - absolute.

-
-
Loading of Code From Archive Files @@ -699,13 +675,6 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]), not sticky.

- - - Rehash or create code path cache - -

This function creates or rehashes the code path cache.

-
-
Full name of a file located in the code path @@ -714,10 +683,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]), arbitrary type. If found, the full name is returned. non_existing is returned if the file cannot be found. The function can be useful, for example, to locate - application resource files. If the code path cache is used, - the code server will efficiently read the full name from - the cache, provided that Filename is an object code - file or an .app file.

+ application resource files.

diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 352c02562b..ae28c97b47 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -68,6 +68,8 @@ clash/0, get_mode/0]). +-deprecated({rehash,0,next_major_release}). + -export_type([load_error_rsn/0, load_ret/0]). -include_lib("kernel/include/file.hrl"). @@ -293,7 +295,9 @@ replace_path(Name, Dir) when (is_atom(Name) orelse is_list(Name)), call({replace_path,Name,Dir}). -spec rehash() -> 'ok'. -rehash() -> call(rehash). +rehash() -> + cache_warning(), + ok. -spec get_mode() -> 'embedded' | 'interactive'. get_mode() -> call(get_mode). @@ -322,6 +326,7 @@ start_link(Flags) -> %%----------------------------------------------------------------- do_start(Flags) -> + maybe_warn_for_cache(), load_code_server_prerequisites(), Mode = get_mode(Flags), @@ -452,30 +457,14 @@ which(File, Base, [Directory|Tail]) -> Filename :: file:filename(), Absname :: file:filename(). where_is_file(File) when is_list(File) -> - case call({is_cached,File}) of - no -> - Path = get_path(), - which(File, ".", Path); - Dir -> - filename:join(Dir, File) - end. + Path = get_path(), + which(File, ".", Path). -spec where_is_file(Path :: file:filename(), Filename :: file:filename()) -> file:filename() | 'non_existing'. where_is_file(Path, File) when is_list(Path), is_list(File) -> - CodePath = get_path(), - if - Path =:= CodePath -> - case call({is_cached, File}) of - no -> - which(File, ".", Path); - Dir -> - filename:join(Dir, File) - end; - true -> - which(File, ".", Path) - end. + which(File, ".", Path). -spec set_primary_archive(ArchiveFile :: file:filename(), ArchiveBin :: binary(), @@ -552,6 +541,22 @@ has_ext(Ext, Extlen, File) -> _ -> false end. +%%% +%%% Warning for deprecated code path cache. +%%% + +maybe_warn_for_cache() -> + case init:get_argument(code_path_cache) of + {ok, _} -> + cache_warning(); + error -> + ok + end. + +cache_warning() -> + W = "The code path cache functionality has been removed", + error_logger:warning_report(W). + %%% %%% Silently load native code for all modules loaded so far. %%% diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 68dd21b1d7..4361bb7b60 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -40,7 +40,6 @@ path, moddb, namedb, - cache = no_cache, mode = interactive, on_load = []}). -type state() :: #state{}. @@ -89,19 +88,11 @@ init(Ref, Parent, [Root,Mode0]) -> end, Path = add_loader_path(IPath, Mode), - State0 = #state{root = Root, - path = Path, - moddb = Db, - namedb = init_namedb(Path), - mode = Mode}, - - State = - case init:get_argument(code_path_cache) of - {ok, _} -> - create_cache(State0); - error -> - State0 - end, + State = #state{root = Root, + path = Path, + moddb = Db, + namedb = init_namedb(Path), + mode = Mode}, put(?ANY_NATIVE_CODE_LOADED, false), @@ -264,50 +255,29 @@ handle_call({load_file,Mod}, Caller, St) -> end; handle_call({add_path,Where,Dir0}, {_From,_Tag}, - #state{cache=Cache0,namedb=Namedb,path=Path0}=S) -> - case Cache0 of - no_cache -> - {Resp,Path} = add_path(Where, Dir0, Path0, Namedb), - {reply,Resp,S#state{path=Path}}; - _ -> - Dir = absname(Dir0), %% Cache always expands the path - {Resp,Path} = add_path(Where, Dir, Path0, Namedb), - Cache = update_cache([Dir], Where, Cache0), - {reply,Resp,S#state{path=Path,cache=Cache}} - end; + #state{namedb=Namedb,path=Path0}=S) -> + {Resp,Path} = add_path(Where, Dir0, Path0, Namedb), + {reply,Resp,S#state{path=Path}}; handle_call({add_paths,Where,Dirs0}, {_From,_Tag}, - #state{cache=Cache0,namedb=Namedb,path=Path0}=S) -> - case Cache0 of - no_cache -> - {Resp,Path} = add_paths(Where, Dirs0, Path0, Namedb), - {reply,Resp,S#state{path=Path}}; - _ -> - %% Cache always expands the path - Dirs = [absname(Dir) || Dir <- Dirs0], - {Resp,Path} = add_paths(Where, Dirs, Path0, Namedb), - Cache=update_cache(Dirs,Where,Cache0), - {reply,Resp,S#state{cache=Cache,path=Path}} - end; + #state{namedb=Namedb,path=Path0}=S) -> + {Resp,Path} = add_paths(Where, Dirs0, Path0, Namedb), + {reply,Resp,S#state{path=Path}}; handle_call({set_path,PathList}, {_From,_Tag}, #state{path=Path0,namedb=Namedb}=S) -> {Resp,Path,NewDb} = set_path(PathList, Path0, Namedb), - {reply,Resp,rehash_cache(S#state{path=Path,namedb=NewDb})}; + {reply,Resp,S#state{path=Path,namedb=NewDb}}; handle_call({del_path,Name}, {_From,_Tag}, #state{path=Path0,namedb=Namedb}=S) -> {Resp,Path} = del_path(Name, Path0, Namedb), - {reply,Resp,rehash_cache(S#state{path=Path})}; + {reply,Resp,S#state{path=Path}}; handle_call({replace_path,Name,Dir}, {_From,_Tag}, #state{path=Path0,namedb=Namedb}=S) -> {Resp,Path} = replace_path(Name, Dir, Path0, Namedb), - {reply,Resp,rehash_cache(S#state{path=Path})}; - -handle_call(rehash, {_From,_Tag}, S0) -> - S = create_cache(S0), - {reply,ok,S}; + {reply,Resp,S#state{path=Path}}; handle_call(get_path, {_From,_Tag}, S) -> {reply,S#state.path,S}; @@ -398,9 +368,6 @@ handle_call({is_sticky, Mod}, {_From,_Tag}, S) -> handle_call(stop,{_From,_Tag}, S) -> {stop,normal,stopped,S}; -handle_call({is_cached,_File}, {_From,_Tag}, S=#state{cache=no_cache}) -> - {reply, no, S}; - handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From,_Tag}, S=#state{mode=Mode}) -> case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) of {ok, Files} -> @@ -409,26 +376,6 @@ handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From {reply, Error, S} end; -handle_call({is_cached,File}, {_From,_Tag}, S=#state{cache=Cache}) -> - ObjExt = objfile_extension(), - Ext = filename:extension(File), - Type = case Ext of - ObjExt -> obj; - ".app" -> app; - _ -> undef - end, - if Type =:= undef -> - {reply, no, S}; - true -> - Key = {Type,list_to_atom(filename:rootname(File, Ext))}, - case ets:lookup(Cache, Key) of - [] -> - {reply, no, S}; - [{Key,Dir}] -> - {reply, Dir, S} - end - end; - handle_call(get_mode, {_From,_Tag}, S=#state{mode=Mode}) -> {reply, Mode, S}; @@ -447,69 +394,6 @@ do_mod_call(Action, Module, Error, St) -> {reply,Error,St} end. -%% -------------------------------------------------------------- -%% Cache functions -%% -------------------------------------------------------------- - -create_cache(St = #state{cache = no_cache}) -> - Cache = ets:new(code_cache, [protected]), - rehash_cache(Cache, St); -create_cache(St) -> - rehash_cache(St). - -rehash_cache(St = #state{cache = no_cache}) -> - St; -rehash_cache(St = #state{cache = OldCache}) -> - ets:delete(OldCache), - Cache = ets:new(code_cache, [protected]), - rehash_cache(Cache, St). - -rehash_cache(Cache, St = #state{path = Path}) -> - Exts = [{obj,objfile_extension()}, {app,".app"}], - {Cache,NewPath} = locate_mods(lists:reverse(Path), first, Exts, Cache, []), - St#state{cache = Cache, path=NewPath}. - -update_cache(Dirs, Where, Cache0) -> - Exts = [{obj,objfile_extension()}, {app,".app"}], - {Cache, _} = locate_mods(Dirs, Where, Exts, Cache0, []), - Cache. - -locate_mods([Dir0|Path], Where, Exts, Cache, Acc) -> - Dir = absname(Dir0), %% Cache always expands the path - case erl_prim_loader:list_dir(Dir) of - {ok, Files} -> - Cache = filter_mods(Files, Where, Exts, Dir, Cache), - locate_mods(Path, Where, Exts, Cache, [Dir|Acc]); - error -> - locate_mods(Path, Where, Exts, Cache, Acc) - end; -locate_mods([], _, _, Cache, Path) -> - {Cache,Path}. - -filter_mods([File|Rest], Where, Exts, Dir, Cache) -> - Ext = filename:extension(File), - Root = list_to_atom(filename:rootname(File, Ext)), - case lists:keyfind(Ext, 2, Exts) of - {Type, _} -> - Key = {Type,Root}, - case Where of - first -> - true = ets:insert(Cache, {Key,Dir}); - last -> - case ets:lookup(Cache, Key) of - [] -> - true = ets:insert(Cache, {Key,Dir}); - _ -> - ignore - end - end; - false -> - ok - end, - filter_mods(Rest, Where, Exts, Dir, Cache); -filter_mods([], _, _, _, Cache) -> - Cache. - %% -------------------------------------------------------------- %% Path handling functions. %% -------------------------------------------------------------- @@ -1238,16 +1122,6 @@ load_abs(File, Mod0, Caller, St) -> {reply,{error,nofile},St} end. -try_load_module(Mod, Dir, Caller, St) -> - File = filename:append(Dir, to_list(Mod) ++ - objfile_extension()), - case erl_prim_loader:get_file(File) of - error -> - {reply,error,St}; - {ok,Binary,FName} -> - try_load_module(absname(FName), Mod, Binary, Caller, St) - end. - try_load_module(File, Mod, Bin, {From,_}=Caller, St0) -> M = to_atom(Mod), case pending_on_load(M, From, St0) of @@ -1345,26 +1219,12 @@ load_file(Mod0, {From,_}=Caller, St0) -> {yes,St} -> {noreply,St} end. -load_file_1(Mod, Caller, #state{path=Path,cache=no_cache}=St) -> +load_file_1(Mod, Caller, #state{path=Path}=St) -> case mod_to_bin(Path, Mod) of error -> {reply,{error,nofile},St}; {Mod,Binary,File} -> try_load_module(File, Mod, Binary, Caller, St) - end; -load_file_1(Mod, Caller, #state{cache=Cache}=St0) -> - Key = {obj,Mod}, - case ets:lookup(Cache, Key) of - [] -> - St = rehash_cache(St0), - case ets:lookup(St#state.cache, Key) of - [] -> - {reply,{error,nofile},St}; - [{Key,Dir}] -> - try_load_module(Mod, Dir, Caller, St) - end; - [{Key,Dir}] -> - try_load_module(Mod, Dir, Caller, St0) end. mod_to_bin([Dir|Tail], Mod) -> diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index ef5303defd..dfcb20d594 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -30,8 +30,7 @@ upgrade/1, sticky_dir/1, pa_pz_option/1, add_del_path/1, dir_disappeared/1, ext_mod_dep/1, clash/1, - load_cached/1, start_node_with_cache/1, add_and_rehash/1, - where_is_file_cached/1, where_is_file_no_cache/1, + where_is_file/1, purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, on_load_embedded/1, on_load_errors/1, big_boot_embedded/1, @@ -56,9 +55,8 @@ all() -> load_binary, dir_req, object_code, set_path_file, upgrade, sticky_dir, pa_pz_option, add_del_path, dir_disappeared, - ext_mod_dep, clash, load_cached, start_node_with_cache, - add_and_rehash, where_is_file_no_cache, - where_is_file_cached, purge_stacktrace, mult_lib_roots, + ext_mod_dep, clash, where_is_file, + purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, on_load_binary, on_load_embedded, on_load_errors, big_boot_embedded, native_early_modules, get_mode]. @@ -904,140 +902,7 @@ uniq([H|T],A) -> uniq(T,[H|A]). -load_cached(suite) -> - []; -load_cached(doc) -> - []; -load_cached(Config) when is_list(Config) -> - Priv = ?config(priv_dir, Config), - WD = filename:dirname(code:which(?MODULE)), - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-pa \"" ++ WD ++ "\""}, - {erl, [this]}]), - CCTabCreated = fun(Tab) -> - case ets:info(Tab, name) of - code_cache -> true; - _ -> false - end - end, - Tabs = rpc:call(Node, ets, all, []), - case rpc:call(Node, lists, any, [CCTabCreated,Tabs]) of - true -> - ?t:stop_node(Node), - ?t:fail("Code cache should not be active!"); - false -> - ok - end, - rpc:call(Node, code, del_path, [Priv]), - rpc:call(Node, code, add_pathz, [Priv]), - - FullModName = Priv ++ "/code_cache_test", - {ok,Dev} = file:open(FullModName ++ ".erl", [write]), - io:format(Dev, "-module(code_cache_test). -export([a/0]). a() -> ok.~n", []), - ok = file:close(Dev), - {ok,code_cache_test} = compile:file(FullModName, [{outdir,Priv}]), - - F = fun load_loop/2, - N = 1000, - {T0,T1} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]), - TNoCache = now_diff(T1, T0), - rpc:call(Node, code, rehash, []), - {T2,T3} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]), - TCache = now_diff(T3, T2), - AvgNoCache = TNoCache/N, - AvgCache = TCache/N, - io:format("Avg. load time (no_cache/cache): ~w/~w~n", [AvgNoCache,AvgCache]), - ?t:stop_node(Node), - if AvgNoCache =< AvgCache -> - ?t:fail("Cache not working properly."); - true -> - ok - end. - -load_loop(N, M) -> - load_loop(N, M, now()). -load_loop(0, _M, T0) -> - {T0,now()}; -load_loop(N, M, T0) -> - code:load_file(M), - code:delete(M), - code:purge(M), - load_loop(N-1, M, T0). - -now_diff({A2, B2, C2}, {A1, B1, C1}) -> - ((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1. - -start_node_with_cache(suite) -> - []; -start_node_with_cache(doc) -> - []; -start_node_with_cache(Config) when is_list(Config) -> - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-code_path_cache"}, - {erl, [this]}]), - Tabs = rpc:call(Node, ets, all, []), - io:format("Tabs: ~w~n", [Tabs]), - CCTabCreated = fun(Tab) -> - case rpc:call(Node, ets, info, [Tab,name]) of - code_cache -> true; - _ -> false - end - end, - true = lists:any(CCTabCreated, Tabs), - ?t:stop_node(Node), - ok. - -add_and_rehash(suite) -> - []; -add_and_rehash(doc) -> - []; -add_and_rehash(Config) when is_list(Config) -> - Priv = ?config(priv_dir, Config), - WD = filename:dirname(code:which(?MODULE)), - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-pa \"" ++ WD ++ "\""}, - {erl, [this]}]), - CCTabCreated = fun(Tab) -> - case ets:info(Tab, name) of - code_cache -> true; - _ -> false - end - end, - Tabs0 = rpc:call(Node, ets, all, []), - case rpc:call(Node, lists, any, [CCTabCreated,Tabs0]) of - true -> - ?t:stop_node(Node), - ?t:fail("Code cache should not be active!"); - false -> - ok - end, - ok = rpc:call(Node, code, rehash, []), % create cache - Tabs1 = rpc:call(Node, ets, all, []), - true = rpc:call(Node, lists, any, [CCTabCreated,Tabs1]), % cache table created - ok = rpc:call(Node, code, rehash, []), - OkDir = filename:join(Priv, ""), - BadDir = filename:join(Priv, "guggemuffsussiputt"), - CP = [OkDir | rpc:call(Node, code, get_path, [])], - true = rpc:call(Node, code, set_path, [CP]), - CP1 = [BadDir | CP], - {error,_} = rpc:call(Node, code, set_path, [CP1]), - true = rpc:call(Node, code, del_path, [OkDir]), - true = rpc:call(Node, code, add_path, [OkDir]), - true = rpc:call(Node, code, add_path, [OkDir]), - {error,_} = rpc:call(Node, code, add_path, [BadDir]), - ok = rpc:call(Node, code, rehash, []), - - ?t:stop_node(Node), - ok. - -where_is_file_no_cache(suite) -> - []; -where_is_file_no_cache(doc) -> - []; -where_is_file_no_cache(Config) when is_list(Config) -> +where_is_file(Config) when is_list(Config) -> {T,KernelBeamFile} = timer:tc(code, where_is_file, ["kernel.beam"]), io:format("Load time: ~w ms~n", [T]), KernelEbinDir = filename:dirname(KernelBeamFile), @@ -1046,35 +911,6 @@ where_is_file_no_cache(Config) when is_list(Config) -> non_existing = code:where_is_file("kernel"), % no such file ok. -where_is_file_cached(suite) -> - []; -where_is_file_cached(doc) -> - []; -where_is_file_cached(Config) when is_list(Config) -> - {ok,Node} = - ?t:start_node(code_cache_node, peer, [{args, - "-code_path_cache"}, - {erl, [this]}]), - Tabs = rpc:call(Node, ets, all, []), - io:format("Tabs: ~w~n", [Tabs]), - CCTabCreated = fun(Tab) -> - case rpc:call(Node, ets, info, [Tab,name]) of - code_cache -> true; - _ -> false - end - end, - true = lists:any(CCTabCreated, Tabs), - KernelBeamFile = rpc:call(Node, code, where_is_file, ["kernel.beam"]), - {T,KernelBeamFile} = rpc:call(Node, timer, tc, [code,where_is_file,["kernel.beam"]]), - io:format("Load time: ~w ms~n", [T]), - KernelEbinDir = rpc:call(Node, filename, dirname, [KernelBeamFile]), - AppFile = rpc:call(Node, filename, join, [KernelEbinDir,"kernel.app"]), - AppFile = rpc:call(Node, code, where_is_file, ["kernel.app"]), - non_existing = rpc:call(Node, code, where_is_file, ["kernel"]), % no such file - ?t:stop_node(Node), - ok. - - purge_stacktrace(suite) -> []; purge_stacktrace(doc) -> diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 166eb3cef2..960c70f255 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -644,6 +644,8 @@ obsolete_1(httpd_conf, make_integer, 1) -> obsolete_1(random, _, _) -> {deprecated, "the 'random' module is deprecated; " "use the 'rand' module instead"}; +obsolete_1(code, rehash, 0) -> + {deprecated, "deprecated because the code path cache feature has been removed"}; obsolete_1(_, _, _) -> no. -- cgit v1.2.3 From ac8196ad06425c25aa3baa76427fbd538e636cb3 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 14 Dec 2015 15:58:30 +0100 Subject: ssl: Print openssl version string --- lib/ssl/test/ssl_to_openssl_SUITE.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 119baf1072..4441545257 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -112,6 +112,7 @@ init_per_suite(Config0) -> false -> {skip, "Openssl not found"}; _ -> + ct:pal("Version: ~p", [os:cmd("openssl version")]), catch crypto:stop(), try crypto:start() of ok -> -- cgit v1.2.3 From 2af883c62efe6bae1bf9013783f43a5b9848c237 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 7 Dec 2015 13:24:00 +0100 Subject: stdlib: Remove undocumented function specification syntax The syntax -spec/callback F/A :: FunctionType; has been removed. No deprecation was deemed necessary. --- lib/stdlib/src/erl_lint.erl | 25 ++++++++++++------------- lib/stdlib/src/erl_parse.yrl | 14 ++------------ lib/stdlib/test/erl_lint_SUITE.erl | 27 +++++++++++++++++++++++++-- lib/stdlib/test/erl_pp_SUITE.erl | 8 -------- 4 files changed, 39 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 4a4019b8bd..3ce6abe752 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -373,9 +373,9 @@ format_error({spec_fun_undefined, {F, A}}) -> format_error({missing_spec, {F,A}}) -> io_lib:format("missing specification for function ~w/~w", [F, A]); format_error(spec_wrong_arity) -> - "spec has the wrong arity"; + "spec has wrong arity"; format_error(callback_wrong_arity) -> - "callback has the wrong arity"; + "callback has wrong arity"; format_error({deprecated_builtin_type, {Name, Arity}, Replacement, Rel}) -> UseS = case Replacement of @@ -2878,7 +2878,7 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) -> St1 = St0#lint{specs = dict:store(MFA, Line, Specs)}, case dict:is_key(MFA, Specs) of true -> add_error(Line, {redefine_spec, MFA0}, St1); - false -> check_specs(TypeSpecs, Arity, St1) + false -> check_specs(TypeSpecs, spec_wrong_arity, Arity, St1) end. %% callback_decl(Line, Fun, Types, State) -> State. @@ -2892,7 +2892,8 @@ callback_decl(Line, MFA0, TypeSpecs, St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)}, case dict:is_key(MFA, Callbacks) of true -> add_error(Line, {redefine_callback, MFA0}, St1); - false -> check_specs(TypeSpecs, Arity, St1) + false -> check_specs(TypeSpecs, callback_wrong_arity, + Arity, St1) end end. @@ -2929,7 +2930,7 @@ is_fa({FuncName, Arity}) when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> true; is_fa(_) -> false. -check_specs([FunType|Left], Arity, St0) -> +check_specs([FunType|Left], ETag, Arity, St0) -> {FunType1, CTypes} = case FunType of {type, _, bounded_fun, [FT = {type, _, 'fun', _}, Cs]} -> @@ -2937,18 +2938,16 @@ check_specs([FunType|Left], Arity, St0) -> {FT, lists:append(Types0)}; {type, _, 'fun', _} = FT -> {FT, []} end, - SpecArity = - case FunType1 of - {type, L, 'fun', [any, _]} -> any; - {type, L, 'fun', [{type, _, product, D}, _]} -> length(D) - end, + {type, L, 'fun', [{type, _, product, D}, _]} = FunType1, + SpecArity = length(D), St1 = case Arity =:= SpecArity of true -> St0; - false -> add_error(L, spec_wrong_arity, St0) + false -> %% Cannot happen if called from the compiler. + add_error(L, ETag, St0) end, St2 = check_type({type, nowarn(), product, [FunType1|CTypes]}, St1), - check_specs(Left, Arity, St2); -check_specs([], _Arity, St) -> + check_specs(Left, ETag, Arity, St2); +check_specs([], _ETag, _Arity, St) -> St. nowarn() -> diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index ae42a8f0b1..e07ab2efc2 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -85,10 +85,6 @@ type_spec -> '(' spec_fun type_sigs ')' : {'$2', '$3'}. spec_fun -> atom : '$1'. spec_fun -> atom ':' atom : {'$1', '$3'}. -%% The following two are retained only for backwards compatibility; -%% they are not part of the EEP syntax and should be removed. -spec_fun -> atom '/' integer '::' : {'$1', '$3'}. -spec_fun -> atom ':' atom '/' integer '::' : {'$1', '$3', '$5'}. typed_attr_val -> expr ',' typed_record_fields : {typed_record, '$1', '$3'}. typed_attr_val -> expr '::' top_type : {type_def, '$1', '$3'}. @@ -634,14 +630,8 @@ build_type_spec({Kind,Aa}, {SpecFun, TypeSpecs}) {atom, _, Fun} -> {Fun, find_arity_from_specs(TypeSpecs)}; {{atom,_, Mod}, {atom,_, Fun}} -> - {Mod,Fun,find_arity_from_specs(TypeSpecs)}; - {{atom, _, Fun}, {integer, _, Arity}} -> - %% Old style spec. Allow this for now. - {Fun,Arity}; - {{atom,_, Mod}, {atom, _, Fun}, {integer, _, Arity}} -> - %% Old style spec. Allow this for now. - {Mod,Fun,Arity} - end, + {Mod,Fun,find_arity_from_specs(TypeSpecs)} + end, {attribute,Aa,Kind,{NewSpecFun, TypeSpecs}}. find_arity_from_specs([Spec|_]) -> diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 1d35cc71a5..3c746a13d7 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -65,7 +65,7 @@ too_many_arguments/1, basic_errors/1,bin_syntax_errors/1, predef/1, - maps/1,maps_type/1,otp_11851/1 + maps/1,maps_type/1,otp_11851/1,otp_11879/1 ]). % Default timetrap timeout (set in init_per_testcase). @@ -94,7 +94,7 @@ all() -> bif_clash, behaviour_basic, behaviour_multiple, otp_11861, otp_7550, otp_8051, format_warn, {group, on_load}, too_many_arguments, basic_errors, bin_syntax_errors, predef, - maps, maps_type, otp_11851]. + maps, maps_type, otp_11851, otp_11879]. groups() -> [{unused_vars_warn, [], @@ -3849,6 +3849,29 @@ otp_11851(Config) when is_list(Config) -> [] = run(Config, Ts), ok. +otp_11879(doc) -> + "OTP-11879: The -spec f/a :: (As) -> B; syntax removed, " + "and is_subtype/2 deprecated"; +otp_11879(_Config) -> + Fs = [{attribute,0,file,{"file.erl",0}}, + {attribute,0,module,m}, + {attribute,1,spec, + {{f,1}, + [{type,2,'fun',[{type,3,product,[{var,4,'V1'}, + {var,5,'V1'}]}, + {type,6,integer,[]}]}]}}, + {attribute,20,callback, + {{cb,21}, + [{type,22,'fun',[{type,23,product,[{var,24,'V1'}, + {var,25,'V1'}]}, + {type,6,integer,[]}]}]}}], + {error,[{"file.erl", + [{1,erl_lint,{spec_fun_undefined,{f,1}}}, + {2,erl_lint,spec_wrong_arity}, + {22,erl_lint,callback_wrong_arity}]}], + []} = compile:forms(Fs, [return,report]), + ok. + run(Config, Tests) -> F = fun({N,P,Ws,E}, BadL) -> case catch run_test(Config, P, Ws) of diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 8cdd2ceca9..d0de600a1d 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -1000,18 +1000,10 @@ otp_8567(Config) when is_list(Config) -> "t() ->\n" " 3.\n" "\n" - "-spec(t1/1 :: (ot()) -> ot1()).\n" - "t1(A) ->\n" - " A.\n" - "\n" "-spec(t2 (ot()) -> ot1()).\n" "t2(A) ->\n" " A.\n" "\n" - "-spec(otp_8567:t3/1 :: (ot()) -> ot1()).\n" - "t3(A) ->\n" - " A.\n" - "\n" "-spec(otp_8567:t4 (ot()) -> ot1()).\n" "t4(A) ->\n" " A.\n">>, -- cgit v1.2.3 From ce1cffd6f8812fa6216d9d71afaca20e789b7beb Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 9 Dec 2015 15:05:40 +0100 Subject: dialyzer: Print constraints using the '::' syntax --- lib/dialyzer/src/dialyzer_contracts.erl | 18 +++++++---- lib/dialyzer/test/r9c_SUITE_data/results/mnesia | 2 +- .../results/contracts_with_subtypes | 36 +++++++++++----------- .../results/contracts_with_subtypes2 | 2 +- .../test/small_SUITE_data/results/pretty_bitstring | 2 +- lib/dialyzer/test/user_SUITE_data/results/wsp_pdu | 2 +- 6 files changed, 34 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 7251de8b10..83b3ef72f2 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -126,13 +126,19 @@ butlast([H|T]) -> [H|butlast(T)]. constraints_to_string([]) -> ""; -constraints_to_string([{type, _, constraint, [{atom, _, What}, Types]}]) -> - atom_to_list(What) ++ "(" ++ - sequence([erl_types:t_form_to_string(T) || T <- Types], ",") ++ ")"; constraints_to_string([{type, _, constraint, [{atom, _, What}, Types]}|Rest]) -> - atom_to_list(What) ++ "(" ++ - sequence([erl_types:t_form_to_string(T) || T <- Types], ",") - ++ "), " ++ constraints_to_string(Rest). + S = constraint_to_string(What, Types), + case Rest of + [] -> S; + _ -> S ++ ", " ++ constraints_to_string(Rest) + end. + +constraint_to_string(is_subtype, [{var, _, Var}, T]) -> + atom_to_list(Var) ++ " :: " ++ erl_types:t_form_to_string(T); +constraint_to_string(What, Types) -> + atom_to_list(What) ++ "(" + ++ sequence([erl_types:t_form_to_string(T) || T <- Types], ",") + ++ ")". sequence([], _Delimiter) -> ""; sequence([H], _Delimiter) -> H; diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia index 1dc5a105bf..220b18ca7a 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia +++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia @@ -6,7 +6,7 @@ mnesia_bup.erl:111: The created fun has no local return mnesia_bup.erl:574: Function fallback_receiver/2 has no local return mnesia_bup.erl:967: Function uninstall_fallback_master/2 has no local return mnesia_checkpoint.erl:1014: The variable Error can never match since previous clauses completely covered the type {'ok',#checkpoint_args{nodes::[any()],retainers::[any(),...]}} -mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> no_return() when is_subtype(Msg,term()), is_subtype(From,{pid(),Tag::_}), is_subtype(Parent,pid()), is_subtype(Module,module()), is_subtype(Debug,[dbg_opt()]), is_subtype(Misc,term()) +mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> no_return() when Msg :: term(), From :: {pid(),Tag::_}, Parent :: pid(), Module :: module(), Debug :: [dbg_opt()], Misc :: term() mnesia_controller.erl:1666: The variable Tab can never match since previous clauses completely covered the type [any()] mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'reply',_,_} | {'stop','shutdown',#state{}} mnesia_controller.erl:1685: The pattern {'noreply', State2, _Timeout} can never match the type {'reply',_,_} diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes index a9fbfb6068..d2a3ebb766 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes +++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes @@ -1,15 +1,15 @@ -contracts_with_subtypes.erl:106: The call contracts_with_subtypes:rec_arg({'a','b'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A}) -contracts_with_subtypes.erl:107: The call contracts_with_subtypes:rec_arg({'b','a'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A}) -contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A}) -contracts_with_subtypes.erl:135: The call contracts_with_subtypes:rec2({'a','b'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) -contracts_with_subtypes.erl:136: The call contracts_with_subtypes:rec2({'b','a'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) -contracts_with_subtypes.erl:137: The call contracts_with_subtypes:rec2({'a',{'b','a'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) -contracts_with_subtypes.erl:138: The call contracts_with_subtypes:rec2({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) -contracts_with_subtypes.erl:139: The call contracts_with_subtypes:rec2({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) -contracts_with_subtypes.erl:140: The call contracts_with_subtypes:rec2({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) -contracts_with_subtypes.erl:141: The call contracts_with_subtypes:rec2({'a',{'b',{'a',{'b','a'}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) -contracts_with_subtypes.erl:142: The call contracts_with_subtypes:rec2({'b',{'a',{'b',{'a','b'}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab()) +contracts_with_subtypes.erl:106: The call contracts_with_subtypes:rec_arg({'a','b'}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A} +contracts_with_subtypes.erl:107: The call contracts_with_subtypes:rec_arg({'b','a'}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A} +contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A} +contracts_with_subtypes.erl:135: The call contracts_with_subtypes:rec2({'a','b'}) breaks the contract (Arg) -> 'ok' when Arg :: ab() +contracts_with_subtypes.erl:136: The call contracts_with_subtypes:rec2({'b','a'}) breaks the contract (Arg) -> 'ok' when Arg :: ab() +contracts_with_subtypes.erl:137: The call contracts_with_subtypes:rec2({'a',{'b','a'}}) breaks the contract (Arg) -> 'ok' when Arg :: ab() +contracts_with_subtypes.erl:138: The call contracts_with_subtypes:rec2({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when Arg :: ab() +contracts_with_subtypes.erl:139: The call contracts_with_subtypes:rec2({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab() +contracts_with_subtypes.erl:140: The call contracts_with_subtypes:rec2({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab() +contracts_with_subtypes.erl:141: The call contracts_with_subtypes:rec2({'a',{'b',{'a',{'b','a'}}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab() +contracts_with_subtypes.erl:142: The call contracts_with_subtypes:rec2({'b',{'a',{'b',{'a','b'}}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab() contracts_with_subtypes.erl:175: The pattern 1 can never match the type string() contracts_with_subtypes.erl:178: The pattern 'alpha' can never match the type {'ok',_} | {'ok',_,string()} contracts_with_subtypes.erl:180: The pattern 42 can never match the type {'ok',_} | {'ok',_,string()} @@ -24,13 +24,13 @@ contracts_with_subtypes.erl:23: Invalid type specification for function contract contracts_with_subtypes.erl:240: The pattern {'ok', 42} can never match the type {'ok',_,string()} contracts_with_subtypes.erl:241: The pattern 42 can never match the type {'ok',_,string()} contracts_with_subtypes.erl:267: Function flat_ets_new_t/0 has no local return -contracts_with_subtypes.erl:268: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed') +contracts_with_subtypes.erl:268: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when Name :: atom(), Options :: [Option], Option :: 'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed' contracts_with_subtypes.erl:294: Function factored_ets_new_t/0 has no local return -contracts_with_subtypes.erl:295: The call contracts_with_subtypes:factored_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,Type | Access | 'named_table' | {'keypos',Pos} | {'heir',Pid::pid(),HeirData} | {'heir','none'} | Tweaks), is_subtype(Type,type()), is_subtype(Access,access()), is_subtype(Tweaks,{'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed'), is_subtype(Pos,pos_integer()), is_subtype(HeirData,term()) -contracts_with_subtypes.erl:77: The call contracts_with_subtypes:foo1(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,atom()), is_subtype(Res,atom()) -contracts_with_subtypes.erl:78: The call contracts_with_subtypes:foo2(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,Arg2), is_subtype(Arg2,atom()), is_subtype(Res,atom()) -contracts_with_subtypes.erl:79: The call contracts_with_subtypes:foo3(5) breaks the contract (Arg1) -> Res when is_subtype(Arg2,atom()), is_subtype(Arg1,Arg2), is_subtype(Res,atom()) +contracts_with_subtypes.erl:295: The call contracts_with_subtypes:factored_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when Name :: atom(), Options :: [Option], Option :: Type | Access | 'named_table' | {'keypos',Pos} | {'heir',Pid::pid(),HeirData} | {'heir','none'} | Tweaks, Type :: type(), Access :: access(), Tweaks :: {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed', Pos :: pos_integer(), HeirData :: term() +contracts_with_subtypes.erl:77: The call contracts_with_subtypes:foo1(5) breaks the contract (Arg1) -> Res when Arg1 :: atom(), Res :: atom() +contracts_with_subtypes.erl:78: The call contracts_with_subtypes:foo2(5) breaks the contract (Arg1) -> Res when Arg1 :: Arg2, Arg2 :: atom(), Res :: atom() +contracts_with_subtypes.erl:79: The call contracts_with_subtypes:foo3(5) breaks the contract (Arg1) -> Res when Arg2 :: atom(), Arg1 :: Arg2, Res :: atom() contracts_with_subtypes.erl:7: Invalid type specification for function contracts_with_subtypes:extract/0. The success typing is () -> 'something' -contracts_with_subtypes.erl:80: The call contracts_with_subtypes:foo4(5) breaks the contract (Type) -> Type when is_subtype(Type,atom()) +contracts_with_subtypes.erl:80: The call contracts_with_subtypes:foo4(5) breaks the contract (Type) -> Type when Type :: atom() contracts_with_subtypes.erl:81: The call contracts_with_subtypes:foo5(5) breaks the contract (Type::atom()) -> Type::atom() -contracts_with_subtypes.erl:82: The call contracts_with_subtypes:foo6(5) breaks the contract (Type) -> Type when is_subtype(Type,atom()) +contracts_with_subtypes.erl:82: The call contracts_with_subtypes:foo6(5) breaks the contract (Type) -> Type when Type :: atom() diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2 b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2 index 9f5433a13d..1a8aeb13d0 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2 +++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2 @@ -1,3 +1,3 @@ contracts_with_subtypes2.erl:18: Function t/0 has no local return -contracts_with_subtypes2.erl:19: The call contracts_with_subtypes2:t({'a',{'b',{'c',{'d',{'e',{'g',3}}}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A}), is_subtype(A,{'b',B}), is_subtype(B,{'c',C}), is_subtype(C,{'d',D}), is_subtype(D,{'e',E}), is_subtype(E,{'f',_}) +contracts_with_subtypes2.erl:19: The call contracts_with_subtypes2:t({'a',{'b',{'c',{'d',{'e',{'g',3}}}}}}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A}, A :: {'b',B}, B :: {'c',C}, C :: {'d',D}, D :: {'e',E}, E :: {'f',_} diff --git a/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring index 0ad6eee766..e148e5cf22 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring +++ b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring @@ -1,3 +1,3 @@ pretty_bitstring.erl:7: Function t/0 has no local return -pretty_bitstring.erl:8: The call binary:copy(#{#<1>(8, 1, 'integer', ['unsigned', 'big']), #<2>(8, 1, 'integer', ['unsigned', 'big']), #<3>(3, 1, 'integer', ['unsigned', 'big'])}#,2) breaks the contract (Subject,N) -> binary() when is_subtype(Subject,binary()), is_subtype(N,non_neg_integer()) +pretty_bitstring.erl:8: The call binary:copy(#{#<1>(8, 1, 'integer', ['unsigned', 'big']), #<2>(8, 1, 'integer', ['unsigned', 'big']), #<3>(3, 1, 'integer', ['unsigned', 'big'])}#,2) breaks the contract (Subject,N) -> binary() when Subject :: binary(), N :: non_neg_integer() diff --git a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu index d1f8f4caf2..626e677524 100644 --- a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu +++ b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu @@ -6,7 +6,7 @@ wsp_pdu.erl:2403: The call wsp_pdu:d_date(Data1::binary()) will never return sin wsp_pdu.erl:2406: Guard test is_integer(Sec::{[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()}) can never succeed wsp_pdu.erl:2408: The pattern {'short', Data2} can never match the type {[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()} wsp_pdu.erl:2755: Function parse_push_flag/1 has no local return -wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) breaks the contract (Integer) -> string() when is_subtype(Integer,integer()) +wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) breaks the contract (Integer) -> string() when Integer :: integer() wsp_pdu.erl:2875: The call wsp_pdu:d_text_string(Data::byte()) will never return since it differs in the 1st argument from the success typing arguments: (binary()) wsp_pdu.erl:2976: The call wsp_pdu:d_q_value(QData::byte()) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>>) wsp_pdu.erl:3336: The call wsp_pdu:encode_typed_field(Ver::any(),'Q-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any()) -- cgit v1.2.3 From f8eb1fa88f93487c15ce0834f373cad790159680 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 11 Dec 2015 12:16:06 +0100 Subject: debugger: Use '::' for constraints --- lib/debugger/src/dbg_iload.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl index 7746a06fcb..369b456524 100644 --- a/lib/debugger/src/dbg_iload.erl +++ b/lib/debugger/src/dbg_iload.erl @@ -39,7 +39,7 @@ %% dbg_iserver. We are suspended until the module has been loaded. %%-------------------------------------------------------------------- -spec load_mod(Mod, file:filename(), binary(), ets:tid()) -> - {'ok', Mod} when is_subtype(Mod, atom()). + {'ok', Mod} when Mod :: atom(). load_mod(Mod, File, Binary, Db) -> Flag = process_flag(trap_exit, true), -- cgit v1.2.3 From b08742128224c2d9860a97444d22064b4ecbb54d Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 11 Dec 2015 12:16:17 +0100 Subject: hipe: Use '::' for constraints --- lib/hipe/icode/hipe_icode.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl index 9692eebb10..07d230491d 100644 --- a/lib/hipe/icode/hipe_icode.erl +++ b/lib/hipe/icode/hipe_icode.erl @@ -1376,12 +1376,12 @@ remove_constants(L) -> %% Substitution: replace occurrences of X by Y if {X,Y} is in the %% Subst_list. --spec subst([{_,_}], I) -> I when is_subtype(I, icode_instr()). +-spec subst([{_,_}], I) -> I when I :: icode_instr(). subst(Subst, I) -> subst_defines(Subst, subst_uses(Subst, I)). --spec subst_uses([{_,_}], I) -> I when is_subtype(I, icode_instr()). +-spec subst_uses([{_,_}], I) -> I when I :: icode_instr(). subst_uses(Subst, I) -> case I of @@ -1405,7 +1405,7 @@ subst_uses(Subst, I) -> #icode_label{} -> I end. --spec subst_defines([{_,_}], I) -> I when is_subtype(I, icode_instr()). +-spec subst_defines([{_,_}], I) -> I when I :: icode_instr(). subst_defines(Subst, I) -> case I of -- cgit v1.2.3 From 57a1eebddcbbc4f3f9734fb5cff8f9b40e1b2c2d Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 11 Dec 2015 12:16:27 +0100 Subject: stdlib: Add a comment about is_subtype(_, _) constraints --- lib/stdlib/test/erl_pp_SUITE.erl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index d0de600a1d..8a128b3815 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -876,6 +876,9 @@ type_examples() -> {ex30,<<"-type t99() ::" "{t2(),'\\'t::4'(),t5(),t6(),t7(),t8(),t10(),t14()," "t15(),t20(),t21(), t22(),t25()}. ">>}, + %% Writing constraints as is_subtype(V, T) is not supported since + %% Erlang/OTP 19.0, but as long as the parser recognizes the + %% is_subtype(V, T) syntax, we need a few examples of the syntax. {ex31,<<"-spec t1(FooBar :: t99()) -> t99();" "(t2()) -> t2();" "('\\'t::4'()) -> '\\'t::4'() when is_subtype('\\'t::4'(), t24);" -- cgit v1.2.3 From 69f4b8be1899eb115ced063ef7d606880df72d3d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 11 Dec 2015 17:19:47 +0100 Subject: inets: Fix dialyzer warning --- lib/inets/src/http_server/httpd_custom_api.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/src/http_server/httpd_custom_api.erl b/lib/inets/src/http_server/httpd_custom_api.erl index 282f3a6ee6..d5a6fa8715 100644 --- a/lib/inets/src/http_server/httpd_custom_api.erl +++ b/lib/inets/src/http_server/httpd_custom_api.erl @@ -23,7 +23,8 @@ -callback response_default_headers() -> [{Key::string(), Value::string()}]. -callback response_header({Key::string(), Value::string()}) -> - {true, {Key::string(), Value::string()}} | false. + {true, {Key::string(), Value::string()}} | false | + {true, string()}. %% Used internally to avoid traversing headers twice -callback request_header({Key::string(), Value::string()}) -> {true, {Key::string(), Value::string()}} | false. -- cgit v1.2.3 From 4ba8b8b69f18e642dc430746cd5857ec34a47aeb Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 14 Dec 2015 10:36:49 +0100 Subject: inets: Include behaviour modules in install target --- lib/inets/src/http_server/Makefile | 2 +- lib/inets/src/inets_app/inets.app.src | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile index b9f2290289..1c05d454a5 100644 --- a/lib/inets/src/http_server/Makefile +++ b/lib/inets/src/http_server/Makefile @@ -137,7 +137,7 @@ release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/src/http_server" $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/http_server" $(INSTALL_DIR) "$(RELSYSDIR)/ebin" - $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" + $(INSTALL_DATA) $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) "$(RELSYSDIR)/ebin" release_docs_spec: diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src index 2b9b8f5f32..883ba84e8e 100644 --- a/lib/inets/src/inets_app/inets.app.src +++ b/lib/inets/src/inets_app/inets.app.src @@ -65,6 +65,7 @@ httpd_connection_sup, httpd_conf, httpd_custom, + httpd_custom_api, httpd_esi, httpd_example, httpd_file, -- cgit v1.2.3 From 4586435cd4ca0d3ad3aedd60f462aed8da589460 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 15 Dec 2015 09:43:08 +0100 Subject: Update version numbers --- lib/asn1/vsn.mk | 2 +- lib/common_test/vsn.mk | 2 +- lib/compiler/vsn.mk | 2 +- lib/crypto/vsn.mk | 2 +- lib/dialyzer/vsn.mk | 2 +- lib/erl_interface/vsn.mk | 2 +- lib/eunit/vsn.mk | 2 +- lib/hipe/vsn.mk | 2 +- lib/inets/vsn.mk | 2 +- lib/jinterface/vsn.mk | 2 +- lib/kernel/vsn.mk | 2 +- lib/observer/vsn.mk | 2 +- lib/parsetools/vsn.mk | 2 +- lib/runtime_tools/vsn.mk | 2 +- lib/sasl/vsn.mk | 2 +- lib/snmp/vsn.mk | 2 +- lib/stdlib/vsn.mk | 2 +- lib/test_server/vsn.mk | 2 +- lib/tools/vsn.mk | 2 +- lib/typer/vsn.mk | 2 +- lib/wx/vsn.mk | 2 +- lib/xmerl/vsn.mk | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index d4c46863a3..87a229424c 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1 +1 @@ -ASN1_VSN = 4.0 +ASN1_VSN = 4.0.1 diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index ff2bd20ab3..f33b705dcb 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1 +1 @@ -COMMON_TEST_VSN = 1.11 +COMMON_TEST_VSN = 1.11.1 diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 357b35e47b..c5089ff57e 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 6.0.1 +COMPILER_VSN = 6.0.2 diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index c2166a8e75..de4329e612 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 3.6.1 +CRYPTO_VSN = 3.6.2 diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index e57caa9ad3..9480f17f51 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.8.1 +DIALYZER_VSN = 2.8.2 diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk index 94cfd30cec..18ba9df41e 100644 --- a/lib/erl_interface/vsn.mk +++ b/lib/erl_interface/vsn.mk @@ -1,2 +1,2 @@ -EI_VSN = 3.8 +EI_VSN = 3.8.1 ERL_INTERFACE_VSN = $(EI_VSN) diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk index 079520def2..00cbab5829 100644 --- a/lib/eunit/vsn.mk +++ b/lib/eunit/vsn.mk @@ -1 +1 @@ -EUNIT_VSN = 2.2.11 +EUNIT_VSN = 2.2.12 diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index 3ec9d7ee45..123792e708 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.13 +HIPE_VSN = 3.14 diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 7cc95fa6d3..2717f5b110 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 6.0.3 +INETS_VSN = 6.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk index 4df01d1151..41e670528a 100644 --- a/lib/jinterface/vsn.mk +++ b/lib/jinterface/vsn.mk @@ -1 +1 @@ -JINTERFACE_VSN = 1.6 +JINTERFACE_VSN = 1.6.1 diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index d549033302..703075634b 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 4.1 +KERNEL_VSN = 4.1.1 diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk index 7e7e32099b..bd89977e28 100644 --- a/lib/observer/vsn.mk +++ b/lib/observer/vsn.mk @@ -1 +1 @@ -OBSERVER_VSN = 2.1 +OBSERVER_VSN = 2.1.1 diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk index b99b3bb713..de3da23c8a 100644 --- a/lib/parsetools/vsn.mk +++ b/lib/parsetools/vsn.mk @@ -1 +1 @@ -PARSETOOLS_VSN = 2.1 +PARSETOOLS_VSN = 2.1.1 diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index 83e3612561..3dd7df9f2e 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.9.1 +RUNTIME_TOOLS_VSN = 1.9.2 diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index 959d9c88d5..cb454d5331 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 2.6 +SASL_VSN = 2.6.1 diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index bf8e87fa0c..61a7d2207a 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 5.2 +SNMP_VSN = 5.2.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 3387d74e57..39b44c9104 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 2.6 +STDLIB_VSN = 2.7 diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk index fd9e4e6d74..3a3815c557 100644 --- a/lib/test_server/vsn.mk +++ b/lib/test_server/vsn.mk @@ -1 +1 @@ -TEST_SERVER_VSN = 3.9 +TEST_SERVER_VSN = 3.9.1 diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index e4eda213ba..3efe89d9f9 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 2.8.1 +TOOLS_VSN = 2.8.2 diff --git a/lib/typer/vsn.mk b/lib/typer/vsn.mk index 74c0ccfc59..507593ef56 100644 --- a/lib/typer/vsn.mk +++ b/lib/typer/vsn.mk @@ -1 +1 @@ -TYPER_VSN = 0.9.9 +TYPER_VSN = 0.9.10 diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index 7608bb3014..a1bacb5d66 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 1.5 +WX_VSN = 1.6 diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk index 1ed230316f..0d6082e023 100644 --- a/lib/xmerl/vsn.mk +++ b/lib/xmerl/vsn.mk @@ -1 +1 @@ -XMERL_VSN = 1.3.8 +XMERL_VSN = 1.3.9 -- cgit v1.2.3 From f4a0ae1736216feac5ae053610644bba2e12ed34 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 15 Dec 2015 09:45:27 +0100 Subject: Update release notes --- lib/asn1/doc/src/notes.xml | 17 ++++ lib/common_test/doc/src/notes.xml | 60 ++++++++++++ lib/compiler/doc/src/notes.xml | 23 +++++ lib/crypto/doc/src/notes.xml | 15 +++ lib/dialyzer/doc/src/notes.xml | 16 ++++ lib/diameter/doc/src/notes.xml | 23 +++++ lib/erl_docgen/doc/src/notes.xml | 19 +++- lib/erl_interface/doc/src/notes.xml | 16 ++++ lib/eunit/doc/src/notes.xml | 15 +++ lib/hipe/doc/src/notes.xml | 45 +++++++++ lib/inets/doc/src/notes.xml | 67 ++++++++++++- lib/jinterface/doc/src/notes.xml | 22 +++++ lib/kernel/doc/src/notes.xml | 64 +++++++++++++ lib/observer/doc/src/notes.xml | 30 ++++++ lib/parsetools/doc/src/notes.xml | 16 ++++ lib/public_key/doc/src/notes.xml | 40 ++++++++ lib/runtime_tools/doc/src/notes.xml | 15 +++ lib/sasl/doc/src/notes.xml | 15 +++ lib/snmp/doc/src/notes.xml | 30 +++++- lib/ssh/doc/src/notes.xml | 185 ++++++++++++++++++++++++++++++++++++ lib/ssl/doc/src/notes.xml | 88 +++++++++++++++++ lib/stdlib/doc/src/notes.xml | 61 ++++++++++++ lib/test_server/doc/src/notes.xml | 29 ++++++ lib/tools/doc/src/notes.xml | 16 ++++ lib/typer/doc/src/notes.xml | 15 +++ lib/wx/doc/src/notes.xml | 18 ++++ lib/xmerl/doc/src/notes.xml | 16 ++++ 27 files changed, 973 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index 9b2d6bbde5..315c472465 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -32,6 +32,23 @@

This document describes the changes made to the asn1 application.

+
Asn1 4.0.1 + +
Fixed Bugs and Malfunctions + + +

+ Trying to encode an empty named BIT STRING in BER would + fail with a function_clause exception. (Thanks to + Svilen Ivanov for reporting this bug.)

+

+ Own Id: OTP-13149

+
+
+
+ +
+
Asn1 4.0
Fixed Bugs and Malfunctions diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index 6972d18dfc..9906db2c90 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -33,6 +33,66 @@ notes.xml
+
Common_Test 1.11.1 + +
Fixed Bugs and Malfunctions + + +

+ When data from the netconf server was split into many ssh + packages, the netconf client performed really bad. This + is now improved.

+

+ Own Id: OTP-13007

+
+ +

+ In ct_netconfc, if a timer expired 'at the same time' as + the server sent the rpc-reply, the timeout message might + already be in the client's message queue when the client + removed the timer ref from its 'pending' list. This + caused a crash in the client since the timer ref could no + longer be found when handling the timeout message. This + problem is now fixed by always flushing the timeout + message from the message queue when canceling a timer.

+

+ Own Id: OTP-13008

+
+ +

+ The error logger handler ct_conn_log_h did not respect + the 'silent' option, and tried to print to an undefined + file descriptor. This has been corrected.

+

+ Own Id: OTP-13035

+
+ +

+ If the user would let the test run proceed after test + suite compilation failure, Common Test did not set the + exit status to indicate failure as expected. This has + been corrected. Also, the 'abort_if_missing_suites' + option now makes Common Test abort the test run without + asking the user if compilation fails, even if access to + stdin/stdout exists.

+

+ Own Id: OTP-13173 Aux Id: seq12978

+
+ +

+ With the Common Test 'create_priv_dir' start option set + to 'auto_per_tc', the name of the priv directory for a + configuration function could clash with the name of the + priv directory for a test case, which would cause Test + Server failure. This error has been corrected.

+

+ Own Id: OTP-13181

+
+
+
+ +
+
Common_Test 1.11
Fixed Bugs and Malfunctions diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index daf3bd3af9..3c06e4f98e 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,29 @@

This document describes the changes made to the Compiler application.

+
Compiler 6.0.2 + +
Fixed Bugs and Malfunctions + + +

+ Fix cerl_trees:label/2 bug with map K/V swap

+

+ Own Id: OTP-13091

+
+ +

+ Warnings produced when the 'bin_opt_info' option + was given could sometimes lack filenames and line + numbers. (Thanks to José Valim for reporting this bug.)

+

+ Own Id: OTP-13113

+
+
+
+ +
+
Compiler 6.0.1
Fixed Bugs and Malfunctions diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index 54dd8872eb..f684b6f6eb 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,21 @@

This document describes the changes made to the Crypto application.

+
Crypto 3.6.2 + +
Fixed Bugs and Malfunctions + + +

+ Small documentation fixes

+

+ Own Id: OTP-13017

+
+
+
+ +
+
Crypto 3.6.1
Fixed Bugs and Malfunctions diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index aa29684697..27364ae06a 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,22 @@

This document describes the changes made to the Dialyzer application.

+
Dialyzer 2.8.2 + +
Fixed Bugs and Malfunctions + + +

+ Reintroduce the erlang:make_fun/3 BIF in + erl_bif_types.

+

+ Own Id: OTP-13068

+
+
+
+ +
+
Dialyzer 2.8.1
Fixed Bugs and Malfunctions diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index 61bed37682..828ade4a71 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -43,6 +43,29 @@ first.

+
diameter 1.11.1 + +
Fixed Bugs and Malfunctions + + +

+ Fix request table leaks

+

+ The End-to-End and Hop-by-Hop identifiers of outgoing + Diameter requests are stored in a table in order for the + caller to be located when the corresponding answer + message is received. Entries were orphaned if the handler + was terminated by an exit signal as a consequence of + actions taken by callback functions, or if callbacks + modified identifiers in retransmission cases.

+

+ Own Id: OTP-13137

+
+
+
+ +
+
diameter 1.11
Fixed Bugs and Malfunctions diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml index ba1ad2f5e8..aa8bf14919 100644 --- a/lib/erl_docgen/doc/src/notes.xml +++ b/lib/erl_docgen/doc/src/notes.xml @@ -31,7 +31,24 @@

This document describes the changes made to the erl_docgen application.

-
Erl_Docgen 0.4 +
Erl_Docgen 0.4.1 + +
Improvements and New Features + + +

Updated the xmllint target to just check the xml + files with real documentation content.
Corrected + some errors and added some missing target in the DTD's. +

+

+ Own Id: OTP-13026

+
+
+
+ +
+ +
Erl_Docgen 0.4
Improvements and New Features diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml index 00427ea2ee..6d951e895f 100644 --- a/lib/erl_interface/doc/src/notes.xml +++ b/lib/erl_interface/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the Erl_interface application.

+
Erl_Interface 3.8.1 + +
Improvements and New Features + + +

+ Fix the conditional selection of gethostbyname_r and + gethostbyaddr_r.

+

+ Own Id: OTP-13188

+
+
+
+ +
+
Erl_Interface 3.8
Improvements and New Features diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml index 3760e396ee..cf0523d230 100644 --- a/lib/eunit/doc/src/notes.xml +++ b/lib/eunit/doc/src/notes.xml @@ -33,6 +33,21 @@

This document describes the changes made to the EUnit application.

+
Eunit 2.2.12 + +
Fixed Bugs and Malfunctions + + +

+ Small documentation fixes

+

+ Own Id: OTP-13017

+
+
+
+ +
+
Eunit 2.2.11
Fixed Bugs and Malfunctions diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index e1aec698e4..b5b13948e9 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -31,6 +31,51 @@

This document describes the changes made to HiPE.

+
Hipe 3.14 + +
Fixed Bugs and Malfunctions + + +

+ Fix hipe bug causing segfaults when native code + constructs binaries starting with a zero-length integer + field.

+

+ Own Id: OTP-13048

+
+ +

+ Reintroduce the erlang:make_fun/3 BIF in + erl_bif_types.

+

+ Own Id: OTP-13068

+
+ +

+ In certain cases of matching with very big binaries, the + HiPE compiler generated code that would fail the match, + even in cases that the matching was successful. The + problem was more quite noticeable on 32-bit platforms.

+

+ Own Id: OTP-13092

+
+
+
+ + +
Improvements and New Features + + +

+ mikpe/hipe_x86_signal-musl-support

+

+ Own Id: OTP-13159

+
+
+
+ +
+
Hipe 3.13
Fixed Bugs and Malfunctions diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 7ebb3ddffa..c98ec1a9dc 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,72 @@ notes.xml -
Inets 6.0.3 +
Inets 6.1 + +
Fixed Bugs and Malfunctions + + +

+ Replace obs-folds with spaces instead of failing

+

+ Own Id: OTP-13069

+
+ +

+ Add validation fun for URI scheme to http_uri API

+

+ Own Id: OTP-13071

+
+ +

+ Handle stream bodies as documented.

+

+ Own Id: OTP-13093

+
+ +

+ Correct error handling of mod_esi generated chunks. Send + warning headers in chunk trailers instead of generating + an unexpected additional 500 request response, when + problems, such as a timeout occurs.

+

+ Own Id: OTP-13110

+
+ +

+ HTTP client terminates gracefully when an invalid chunked + length header is encountered.

+

+ Own Id: OTP-13117

+
+
+
+ + +
Improvements and New Features + + +

+ Add default for SNI (Server Name Indication) when running + https using the inets HTTP-client.

+

+ Own Id: OTP-12985

+
+ +

+ Be forgiving to chunked sizes that have trailing + whitespaces as prior implementation was. Also some legacy + embedded devices does actually have trailing whitespaces + even though this in not according to the spec.

+

+ Own Id: OTP-13116

+
+
+
+ +
+ +
Inets 6.0.3
Fixed Bugs and Malfunctions diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml index d9f7ae9f92..e66bcda0c1 100644 --- a/lib/jinterface/doc/src/notes.xml +++ b/lib/jinterface/doc/src/notes.xml @@ -31,6 +31,28 @@

This document describes the changes made to the Jinterface application.

+
Jinterface 1.6.1 + +
Fixed Bugs and Malfunctions + + +

+ Add missing Term tag matching switch statement that was + missing an external fun tag.

+

+ Own Id: OTP-13106

+
+ +

+ fixed writing small compressed values.

+

+ Own Id: OTP-13165

+
+
+
+ +
+
Jinterface 1.6
Fixed Bugs and Malfunctions diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index d02c3e8ad2..5341a793ef 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,70 @@

This document describes the changes made to the Kernel application.

+
Kernel 4.1.1 + +
Fixed Bugs and Malfunctions + + +

+ Host name lookups though inet_res, the Erlang DNS + resolver, are now done case insensitively according to + RFC 4343. Patch by Holger Weiß.

+

+ Own Id: OTP-12836

+
+ +

+ IPv6 distribution handler has been updated to share code + with IPv4 so that all features are supported in IPv6 as + well. A bug when using an IPv4 address as hostname has + been fixed.

+

+ Own Id: OTP-13040

+
+ +

+ Caching of host names in the internal DNS resolver + inet_res has been made character case insensitive for + host names according to RFC 4343.

+

+ Own Id: OTP-13083

+
+ +

Cooked file mode buffering has been fixed so + file:position/2 now works according to Posix on Posix + systems i.e. when file:position/2 returns an error the + file pointer is unaffected.

The Windows system + documentation, however, is unclear on this point so the + documentation of file:position/2 still does not promise + anything.

Cooked file mode file:pread/2,3 and + file:pwrite/2,3 have been corrected to honor character + encoding like the combination of file:position/2 and + file:read/2 or file:write/2 already does. This is + probably not very useful since the character + representation on the caller's side is latin1, + period.

+

+ Own Id: OTP-13155 Aux Id: PR#646

+
+
+
+ + +
Improvements and New Features + + +

+ Add {line_delim, byte()} option to inet:setopts/2 and + decode_packet/3

+

+ Own Id: OTP-12837

+
+
+
+ +
+
Kernel 4.1
Improvements and New Features diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml index f0c87d865e..e2eeffc667 100644 --- a/lib/observer/doc/src/notes.xml +++ b/lib/observer/doc/src/notes.xml @@ -32,6 +32,36 @@

This document describes the changes made to the Observer application.

+
Observer 2.1.1 + +
Fixed Bugs and Malfunctions + + +

+ Show ets owner pid in crashdump viewers popup window, + thanks Leo Liu.

+

+ Own Id: OTP-13030

+
+ +

+ Several initialisms (eg, ERTS, ETS, SMP) are used as + headings. They were being capitalized incorrectly.

+

+ Own Id: OTP-13044

+
+ +

+ Fixed a crash in crashdump viewer when dump contained a + truncated binary.

+

+ Own Id: OTP-13163

+
+
+
+ +
+
Observer 2.1
Fixed Bugs and Malfunctions diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml index 7a9770e667..43840a3bc7 100644 --- a/lib/parsetools/doc/src/notes.xml +++ b/lib/parsetools/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the Parsetools application.

+
Parsetools 2.1.1 + +
Fixed Bugs and Malfunctions + + +

+ Correct the documentation of the error tuple returned by + Yecc and Leex.

+

+ Own Id: OTP-13031

+
+
+
+ +
+
Parsetools 2.1
Improvements and New Features diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index 8034d7fade..8eb56f7354 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -35,6 +35,46 @@ notes.xml +
Public_Key 1.1 + +
Improvements and New Features + + +

+ The 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384' and + 'ecdsa-sha2-nistp521' signature algorithms for ssh are + implemented. See RFC 5656.

+

+ Own Id: OTP-12936

+
+ +

+ There is now a file (public_key/priv/moduli) which lists + size-generator-modulus triples. The purpose is to give + servers the possibility to select the crypto primes + randomly among a list of pregenerated triples. This + reduces the risk for some attacks on diffie-hellman + negotiation.

+

+ See the reference manual for public_key:dh_gex_group/4 + where the handling of this is described.

+

+ The ssh server (ssh:daemon) uses this.

+

+ Own Id: OTP-13054 Aux Id: OTP-13052

+
+ +

+ Add different upper bounds for diffrent string types as + suggested by comment in PKIX1Explicit88.

+

+ Own Id: OTP-13132

+
+
+
+ +
+
Public_Key 1.0.1
Improvements and New Features diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index 5aebea98ce..e92f0e02ad 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -32,6 +32,21 @@

This document describes the changes made to the Runtime_Tools application.

+
Runtime_Tools 1.9.2 + +
Improvements and New Features + + +

+ Clarified dbg:stop documentation

+

+ Own Id: OTP-13078

+
+
+
+ +
+
Runtime_Tools 1.9.1
Fixed Bugs and Malfunctions diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml index 5945ef6490..537511a865 100644 --- a/lib/sasl/doc/src/notes.xml +++ b/lib/sasl/doc/src/notes.xml @@ -31,6 +31,21 @@

This document describes the changes made to the SASL application.

+
SASL 2.6.1 + +
Improvements and New Features + + +

+ Documentation improvements

+

+ Own Id: OTP-13000

+
+
+
+ +
+
SASL 2.6
Improvements and New Features diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 94e73ddfca..9e7f13e126 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -34,7 +34,35 @@ -
SNMP 5.2 +
SNMP 5.2.1 + +
Fixed Bugs and Malfunctions + + +

+ Small documentation fixes

+

+ Own Id: OTP-13017

+
+
+
+ + +
Improvements and New Features + + +

+ Update configuration check of imask ( list of ones and + zeros) to allow the empty list.

+

+ Own Id: OTP-13101

+
+
+
+ +
+ +
SNMP 5.2
Improvements and New Features diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 010b1b15c7..8fb689fdd5 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,191 @@ notes.xml +
Ssh 4.2 + +
Fixed Bugs and Malfunctions + + +

+ Better error handling in ssh_file. There was some rare + errors when a NFS-mounted file was opened by ssh_file and + then remotely deleted during reading. That caused an + endless loop.

+

+ That bug is now fixed.

+

+ Own Id: OTP-12699 Aux Id: OTP-11688

+
+ +

+ Fixed a bug in the compression algorithm + zlib@openssh.com.

+

+ Own Id: OTP-12759

+
+ +

+ It is now possible to start more than one daemon with a + file descriptor given in option fd. Each daemon must of + course have a unique file descriptor.

+

+ Own Id: OTP-12966 Aux Id: seq12945

+
+ +

+ Fixed a bug that caused the option dh_gex_limit to + be ignored.

+

+ Own Id: OTP-13029

+
+ +

+ A problem is fixed with the ssh:connect option + pref_public_key_algs specifying user keys.

+

+ Own Id: OTP-13158

+
+
+
+ + +
Improvements and New Features + + +

+ Document updates in the ssh reference manual: app doc + file and ssh_connection.

+

+ Own Id: OTP-12003

+
+ +

+ The authorization phase is made stateful to prevent ssh + acting on messages sent in wrong order.

+

+ Own Id: OTP-12787

+
+ +

+ Testcases for bad message lengths and for bad subfield + lengths added.

+

+ Own Id: OTP-12792 Aux Id: Codenomicon #5214, 6166

+
+ +

+ The 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384' and + 'ecdsa-sha2-nistp521' signature algorithms for ssh are + implemented. See RFC 5656.

+

+ Own Id: OTP-12936

+
+ +

+ The crypto algorithms 'aes192-ctr' and 'aes256-ctr' are + implemented. See RFC 4344.

+

+ Own Id: OTP-12939

+
+ +

+ The ciphers and macs AEAD_AES_128_GCM and + AEAD_AES_256_GCM are implemented but not enabled per + default. See the SSH App Reference Manual and RFC5647 for + details.

+

+ The ciphers aes128-gcm@openssh.com and + aes256-gcm@openssh.com are also implemented and available + in the default configuration.

+

+ Own Id: OTP-13018

+
+ +

+ The ssh:daemon option dh_gex_groups is extended to read a + user provided ssh moduli file with generator-modulus + pairs. The file is in openssh format.

+

+ Own Id: OTP-13052 Aux Id: OTP-13054

+
+ +

+ There is now a file (public_key/priv/moduli) which lists + size-generator-modulus triples. The purpose is to give + servers the possibility to select the crypto primes + randomly among a list of pregenerated triples. This + reduces the risk for some attacks on diffie-hellman + negotiation.

+

+ See the reference manual for public_key:dh_gex_group/4 + where the handling of this is described.

+

+ The ssh server (ssh:daemon) uses this.

+

+ Own Id: OTP-13054 Aux Id: OTP-13052

+
+ +

+ The ssh:daemon option pwdfun now also takes a fun/4. This + enables the user to 1) check userid-password in another + way than the builtin algorithm, 2) implement rate + limiting per user or source IP or IP+Port, and 3) + implement blocking of missbehaving peers.

+

+ The old fun/2 still works as previously.

+

+ Own Id: OTP-13055 Aux Id: OTP-13053

+
+ +

+ There is now a new option to make the server limit the + size range of moduli available for the diffie-hellman + group exchange negotiation. See option + {dh_gex_limits,{Min,Max}} in ssh:daemon/3.

+

+ Own Id: OTP-13066

+
+ +

+ Ecdh key exchange now validates compressed and + uncompressed keys as defined in rfc5656

+

+ Own Id: OTP-13067

+
+ +

+ Search order for the .ssh directory are changed so + $HOME is tried before + init:get_argument(home).

+

+ Own Id: OTP-13109

+
+ +

+ The sftp receive window handling is optimized so it will + not update the remote end too often. This makes "sftp + mget" considerable faster.

+

+ Own Id: OTP-13130

+
+ +

+ The option key_cb is extended to take an optional + list that is passed to the callback module as an option. + With this it is possible to have different keys depending + on which host that is connected. Another possibility is + to write a callback module that fetches keys etc from a + database.

+

+ Thanks to Vipin Nair.

+

+ Own Id: OTP-13156

+
+
+
+ +
+
Ssh 4.1.3
Known Bugs and Problems diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 4d4a219b4f..61d1c8355a 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -28,6 +28,94 @@

This document describes the changes made to the SSL application.

+
SSL 7.2 + +
Fixed Bugs and Malfunctions + + +

+ Honor distribution port range options

+

+ Own Id: OTP-12838

+
+ +

+ Correct supervisor specification in TLS distribution.

+

+ Own Id: OTP-13134

+
+ +

+ Correct cache timeout

+

+ Own Id: OTP-13141

+
+ +

+ Avoid crash and restart of ssl process when key file does + not exist.

+

+ Own Id: OTP-13144

+
+ +

+ Enable passing of raw socket options on the format + {raw,_,_,_} to the underlying socket.

+

+ Own Id: OTP-13166

+
+ +

+ Hibernation with small or a zero timeout will now work as + expected

+

+ Own Id: OTP-13189

+
+
+
+ + +
Improvements and New Features + + +

+ Add upper limit for session cache, configurable on ssl + application level.

+

+ If upper limit is reached, invalidate the current cache + entries, e.i the session lifetime is the max time a + session will be keept, but it may be invalidated earlier + if the max limit for the table is reached. This will keep + the ssl manager process well behaved, not exhusting + memeory. Invalidating the entries will incrementally + empty the cache to make room for fresh sessions entries.

+

+ Own Id: OTP-12392

+
+ +

+ Use new time functions to measure passed time.

+

+ Own Id: OTP-12457

+
+ +

+ Improved error handling in TLS distribution

+

+ Own Id: OTP-13142

+
+ +

+ Distribution over TLS now honors the nodelay distribution + flag

+

+ Own Id: OTP-13143

+
+
+
+ +
+
SSL 7.1
Fixed Bugs and Malfunctions diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index c84ca9c8ad..267a993a1b 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,67 @@

This document describes the changes made to the STDLIB application.

+
STDLIB 2.7 + +
Fixed Bugs and Malfunctions + + +

The Erlang Pretty Printer uses :: for function + type constraints.

A bug concerning pretty printing + of annotated type union elements in map pair types has + been fixed.

Some minor issues regarding the + documentation of types and specs have been corrected.

+

+ Own Id: OTP-13084

+
+ +

The shell command rp prints strings as lists + of integers if pretty printing of lists is set to + false.

+

+ Own Id: OTP-13145

+
+ +

+ The shell would crash if a bit syntax expression with + conflicting types were given (e.g. if a field type was + given as 'integer-binary'). (Thanks to Aleksei + Magusev for reporting this bug.)

+

+ Own Id: OTP-13157

+
+ +

The rand:export_seed/0 would never return + 'undefined' even if no seed has previously been + created. Fixed to return 'undefined' if there is + no seed in the process dictionary.

+

+ Own Id: OTP-13162

+
+
+
+ + +
Improvements and New Features + + +

+ Add support for the Delete, Home and End keys in the + Erlang shell.

+

+ Own Id: OTP-13032

+
+ +

beam_lib:all_chunks/1 and + beam_lib:build_module/1 have been documented.

+

+ Own Id: OTP-13063

+
+
+
+ +
+
STDLIB 2.6
Fixed Bugs and Malfunctions diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml index da956de9ef..b48bda94d0 100644 --- a/lib/test_server/doc/src/notes.xml +++ b/lib/test_server/doc/src/notes.xml @@ -33,6 +33,35 @@ notes.xml +
Test_Server 3.9.1 + +
Fixed Bugs and Malfunctions + + +

+ When generating Makefile from Makefile.src, + ts_lib:get_arg/4 earlier removed all spaces in the + extracted argument. The code was probably meant for + removing leading and trailing spaces only, and is now + corrected to do so.

+

+ Own Id: OTP-13015

+
+ +

+ With the Common Test 'create_priv_dir' start option set + to 'auto_per_tc', the name of the priv directory for a + configuration function could clash with the name of the + priv directory for a test case, which would cause Test + Server failure. This error has been corrected.

+

+ Own Id: OTP-13181

+
+
+
+ +
+
Test_Server 3.9
Fixed Bugs and Malfunctions diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index bf27d2a3e5..985207a39b 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the Tools application.

+
Tools 2.8.2 + +
Fixed Bugs and Malfunctions + + +

+ The emacs mode does not add a newline after the arrow on + -callback lines anymore.

+

+ Own Id: OTP-13042

+
+
+
+ +
+
Tools 2.8.1
Fixed Bugs and Malfunctions diff --git a/lib/typer/doc/src/notes.xml b/lib/typer/doc/src/notes.xml index 044873ec94..21a2a6d597 100644 --- a/lib/typer/doc/src/notes.xml +++ b/lib/typer/doc/src/notes.xml @@ -31,6 +31,21 @@

This document describes the changes made to TypEr.

+
TypEr 0.9.10 + +
Fixed Bugs and Malfunctions + + +

Fix a bug that could result in a crash when printing + warnings onto standard error.

+

+ Own Id: OTP-13010

+
+
+
+ +
+
TypEr 0.9.9
Fixed Bugs and Malfunctions diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index 6a0dd898e3..0bbeeaafab 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -32,6 +32,24 @@

This document describes the changes made to the wxErlang application.

+
Wx 1.6 + +
Improvements and New Features + + +

Add wxOverlay and make wxPostScripDC optional to make + it easier to build on windows.

Correct some + function specifications.

The driver implementation + have been optimized and now invokes commands after events + have been sent to erlang.

+

+ Own Id: OTP-13160

+
+
+
+ +
+
Wx 1.5
Improvements and New Features diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml index a1558b224f..19274e95ae 100644 --- a/lib/xmerl/doc/src/notes.xml +++ b/lib/xmerl/doc/src/notes.xml @@ -32,6 +32,22 @@

This document describes the changes made to the Xmerl application.

+
Xmerl 1.3.9 + +
Fixed Bugs and Malfunctions + + +

+ Removed the built-in definitions of xml.xsd from the + xmerl_xsd module.

+

+ Own Id: OTP-13070

+
+
+
+ +
+
Xmerl 1.3.8
Fixed Bugs and Malfunctions -- cgit v1.2.3 From 200247f972b012ced0c4b2c6611f091af66ebedd Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 14 Sep 2015 11:52:09 +0200 Subject: kernel: Remove cmd server for unix os:cmd Since we no longer to vfork in the emulator there is no need to serialize the os:cmd calls through a central command server. This greatly decreases the complexity of this code and should make it fast+more scalable. OTP-13089 --- lib/kernel/src/os.erl | 191 ++++++------------------------------------- lib/kernel/test/os_SUITE.erl | 58 +++---------- 2 files changed, 37 insertions(+), 212 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index ffb899e5ca..0022959c11 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -212,174 +212,33 @@ extensions() -> Command :: atom() | io_lib:chars(). cmd(Cmd) -> validate(Cmd), - Bytes = case type() of - {unix, _} -> - unix_cmd(Cmd); - {win32, Wtype} -> - Command0 = case {os:getenv("COMSPEC"),Wtype} of - {false,windows} -> lists:concat(["command.com /c", Cmd]); - {false,_} -> lists:concat(["cmd /c", Cmd]); - {Cspec,_} -> lists:concat([Cspec," /c",Cmd]) - end, - %% open_port/2 awaits string() in Command, but io_lib:chars() can be - %% deep lists according to io_lib module description. - Command = lists:flatten(Command0), - Port = open_port({spawn, Command}, [stream, in, eof, hide]), - get_data(Port, []) - end, - String = unicode:characters_to_list(list_to_binary(Bytes)), + {SpawnCmd, SpawnOpts, SpawnInput} = mk_cmd(os:type(), Cmd), + Port = open_port({spawn, SpawnCmd}, [binary, stderr_to_stdout, + stream, in, eof, hide | SpawnOpts]), + true = port_command(Port, SpawnInput), + Bytes = get_data(Port, []), + String = unicode:characters_to_list(Bytes), if %% Convert to unicode list if possible otherwise return bytes is_list(String) -> String; - true -> Bytes + true -> binary_to_list(Bytes) end. -unix_cmd(Cmd) -> - Tag = make_ref(), - {Pid,Mref} = erlang:spawn_monitor( - fun() -> - process_flag(trap_exit, true), - Port = start_port(), - erlang:port_command(Port, mk_cmd(Cmd)), - exit({Tag,unix_get_data(Port)}) - end), - receive - {'DOWN',Mref,_,Pid,{Tag,Result}} -> - Result; - {'DOWN',Mref,_,Pid,Reason} -> - exit(Reason) - end. - -%% The -s flag implies that only the positional parameters are set, -%% and the commands are read from standard input. We set the -%% $1 parameter for easy identification of the resident shell. -%% --define(ROOT, "/"). --define(ROOT_ANDROID, "/system"). --define(SHELL, "bin/sh -s unix:cmd 2>&1"). --define(PORT_CREATOR_NAME, os_cmd_port_creator). - -%% -%% Serializing open_port through a process to avoid smp lock contention -%% when many concurrent os:cmd() want to do vfork (OTP-7890). -%% --spec start_port() -> port(). -start_port() -> - Ref = make_ref(), - Request = {Ref,self()}, - {Pid, Mon} = case whereis(?PORT_CREATOR_NAME) of - undefined -> - spawn_monitor(fun() -> - start_port_srv(Request) - end); - P -> - P ! Request, - M = erlang:monitor(process, P), - {P, M} - end, - receive - {Ref, Port} when is_port(Port) -> - erlang:demonitor(Mon, [flush]), - Port; - {Ref, Error} -> - erlang:demonitor(Mon, [flush]), - exit(Error); - {'DOWN', Mon, process, Pid, _Reason} -> - start_port() - end. - -start_port_srv(Request) -> - %% We don't want a group leader of some random application. Use - %% kernel_sup's group leader. - {group_leader, GL} = process_info(whereis(kernel_sup), - group_leader), - true = group_leader(GL, self()), - process_flag(trap_exit, true), - StayAlive = try register(?PORT_CREATOR_NAME, self()) - catch - error:_ -> false - end, - start_port_srv_handle(Request), - case StayAlive of - true -> start_port_srv_loop(); - false -> exiting - end. - -start_port_srv_handle({Ref,Client}) -> - Path = case lists:reverse(erlang:system_info(system_architecture)) of - % androideabi - "ibaediordna" ++ _ -> filename:join([?ROOT_ANDROID, ?SHELL]); - _ -> filename:join([?ROOT, ?SHELL]) - end, - Reply = try open_port({spawn, Path},[stream]) of - Port when is_port(Port) -> - (catch port_connect(Port, Client)), - unlink(Port), - Port - catch - error:Reason -> - {Reason,erlang:get_stacktrace()} - end, - Client ! {Ref,Reply}, - ok. - -start_port_srv_loop() -> - receive - {Ref, Client} = Request when is_reference(Ref), - is_pid(Client) -> - start_port_srv_handle(Request); - _Junk -> - ok - end, - start_port_srv_loop(). - -%% -%% unix_get_data(Port) -> Result -%% -unix_get_data(Port) -> - unix_get_data(Port, []). - -unix_get_data(Port, Sofar) -> - receive - {Port,{data, Bytes}} -> - case eot(Bytes) of - {done, Last} -> - lists:flatten([Sofar|Last]); - more -> - unix_get_data(Port, [Sofar|Bytes]) - end; - {'EXIT', Port, _} -> - lists:flatten(Sofar) - end. - -%% -%% eot(String) -> more | {done, Result} -%% -eot(Bs) -> - eot(Bs, []). - -eot([4| _Bs], As) -> - {done, lists:reverse(As)}; -eot([B| Bs], As) -> - eot(Bs, [B| As]); -eot([], _As) -> - more. - -%% -%% mk_cmd(Cmd) -> {ok, ShellCommandString} | {error, ErrorString} -%% -%% We do not allow any input to Cmd (hence commands that want -%% to read from standard input will return immediately). -%% Standard error is redirected to standard output. -%% -%% We use ^D (= EOT = 4) to mark the end of the stream. -%% -mk_cmd(Cmd) when is_atom(Cmd) -> % backward comp. - mk_cmd(atom_to_list(Cmd)); -mk_cmd(Cmd) -> - %% We insert a new line after the command, in case the command - %% contains a comment character. - [$(, unicode:characters_to_binary(Cmd), "\n) + Command = case {os:getenv("COMSPEC"),Wtype} of + {false,windows} -> lists:concat(["command.com /c", Cmd]); + {false,_} -> lists:concat(["cmd /c", Cmd]); + {Cspec,_} -> lists:concat([Cspec," /c",Cmd]) + end, + {Command, [], []}; +mk_cmd(OsType,Cmd) when is_atom(Cmd) -> + mk_cmd(OsType, atom_to_list(Cmd)); +mk_cmd(_,Cmd) -> + %% Have to send command in like this in order to make sh commands like + %% cd and ulimit available + {"/bin/sh -s unix:cmd", [out], + %% We insert a new line after the command, in case the command + %% contains a comment character. + ["(", unicode:characters_to_binary(Cmd), "\n); exit\n"]}. validate(Atom) when is_atom(Atom) -> ok; @@ -397,7 +256,7 @@ validate1([]) -> get_data(Port, Sofar) -> receive {Port, {data, Bytes}} -> - get_data(Port, [Sofar|Bytes]); + get_data(Port, [Sofar,Bytes]); {Port, eof} -> Port ! {self(), close}, receive @@ -410,5 +269,5 @@ get_data(Port, Sofar) -> after 1 -> % force context switch ok end, - lists:flatten(Sofar) + iolist_to_binary(Sofar) end. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 29d8d10262..83a95019e7 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -22,7 +22,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). -export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1, - find_executable/1, unix_comment_in_command/1, deep_list_command/1, evil/1]). + find_executable/1, unix_comment_in_command/1, deep_list_command/1, + large_output_command/1]). -include_lib("test_server/include/test_server.hrl"). @@ -30,7 +31,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command, - find_executable, unix_comment_in_command, deep_list_command, evil]. + find_executable, unix_comment_in_command, deep_list_command, + large_output_command]. groups() -> []. @@ -267,50 +269,14 @@ deep_list_command(Config) when is_list(Config) -> %% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"]) ok. - --define(EVIL_PROCS, 100). --define(EVIL_LOOPS, 100). --define(PORT_CREATOR, os_cmd_port_creator). -evil(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:minutes(5)), - Parent = self(), - Ps = lists:map(fun (N) -> - spawn_link(fun () -> - evil_loop(Parent, ?EVIL_LOOPS,N) - end) - end, lists:seq(1, ?EVIL_PROCS)), - Devil = spawn_link(fun () -> devil(hd(Ps), hd(lists:reverse(Ps))) end), - lists:foreach(fun (P) -> receive {P, done} -> ok end end, Ps), - unlink(Devil), - exit(Devil, kill), - test_server:timetrap_cancel(Dog), - ok. - -devil(P1, P2) -> - erlang:display({?PORT_CREATOR, whereis(?PORT_CREATOR)}), - (catch ?PORT_CREATOR ! lists:seq(1,1000000)), - (catch ?PORT_CREATOR ! lists:seq(1,666)), - (catch ?PORT_CREATOR ! grrrrrrrrrrrrrrrr), - (catch ?PORT_CREATOR ! {'EXIT', P1, buhuuu}), - (catch ?PORT_CREATOR ! {'EXIT', hd(erlang:ports()), buhuuu}), - (catch ?PORT_CREATOR ! {'EXIT', P2, arggggggg}), - receive after 500 -> ok end, - (catch exit(whereis(?PORT_CREATOR), kill)), - (catch ?PORT_CREATOR ! ">8|"), - receive after 500 -> ok end, - (catch exit(whereis(?PORT_CREATOR), diiiiiiiiiiiiiiiiiiiie)), - receive after 100 -> ok end, - devil(P1, P2). - -evil_loop(Parent, Loops, N) -> - Res = integer_to_list(N), - evil_loop(Parent, Loops, Res, "echo " ++ Res). - -evil_loop(Parent, 0, _Res, _Cmd) -> - Parent ! {self(), done}; -evil_loop(Parent, Loops, Res, Cmd) -> - comp(Res, os:cmd(Cmd)), - evil_loop(Parent, Loops-1, Res, Cmd). +large_output_command(doc) -> + "Test to take sure that the correct data is" + "received when doing large commands"; +large_output_command(suite) -> []; +large_output_command(Config) when is_list(Config) -> + %% Maximum allowed on windows is 8192, so we test well below that + AAA = lists:duplicate(7000, $a), + comp(AAA,os:cmd("echo " ++ AAA)). comp(Expected, Got) -> case strip_nl(Got) of -- cgit v1.2.3 From 5db3a62f821413f267427b2bc38045324c57aaf6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 14 Dec 2015 20:15:12 +0100 Subject: erts: Add new test case pdict_SUITE:mixed --- lib/kernel/test/pdict_SUITE.erl | 61 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl index 6de4ff9f77..b096296fa1 100644 --- a/lib/kernel/test/pdict_SUITE.erl +++ b/lib/kernel/test/pdict_SUITE.erl @@ -32,6 +32,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, + mixed/1, simple/1, complicated/1, heavy/1, simple_all_keys/1, info/1]). -export([init_per_testcase/2, end_per_testcase/2]). -export([other_process/2]). @@ -47,7 +48,8 @@ end_per_testcase(_Case, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [simple, complicated, heavy, simple_all_keys, info]. + [simple, complicated, heavy, simple_all_keys, info, + mixed]. groups() -> []. @@ -369,3 +371,60 @@ match_keys(All) -> Ks = lists:sort([K||{K,_}<-All]), Ks = lists:sort(erlang:get_keys()), ok. + + +%% Do random mixed put/erase to test grow/shrink +%% Written for a temporary bug in gc during shrink +mixed(_Config) -> + Rand0 = rand:seed_s(exsplus), + io:format("Random seed = ~p\n\n", [rand:export_seed_s(Rand0)]), + + erts_debug:set_internal_state(available_internal_state, true), + try + C = do_mixed([10,0,100,50,1000,500,600,100,150,1,11,2,30,0], + 0, + array:new(), + 1, + Rand0), + io:format("\nDid total of ~p operations\n", [C]) + after + erts_debug:set_internal_state(available_internal_state, false) + end. + +do_mixed([], _, _, C, _) -> + C; +do_mixed([GoalN | Tail], GoalN, Array, C, Rand0) -> + io:format("Reached goal of ~p keys in dict after ~p mixed ops\n",[GoalN, C]), + GoalN = array:size(Array), + do_mixed(Tail, GoalN, Array, C, Rand0); +do_mixed([GoalN | _]=Goals, CurrN, Array0, C, Rand0) -> + CurrN = array:size(Array0), + GrowPercent = case GoalN > CurrN of + true when CurrN == 0 -> 100; + true -> 75; + false -> 25 + end, + {R, Rand1} = rand:uniform_s(100, Rand0), + case R of + _ when R =< GrowPercent -> %%%%%%%%%%%%% GROW + {Key, Rand2} = rand:uniform_s(10000, Rand1), + case put(Key, {Key,C}) of + undefined -> + Array1 = array:set(CurrN, Key, Array0), + do_mixed(Goals, CurrN+1, Array1, C+1, Rand2); + _ -> + do_mixed(Goals, CurrN, Array0, C+1, Rand2) + end; + + _ -> %%%%%%%%%% SHRINK + {Kix, Rand2} = rand:uniform_s(CurrN, Rand1), + Key = array:get(Kix-1, Array0), + + %% provoke GC during shrink + erts_debug:set_internal_state(fill_heap, true), + + {Key, _} = erase(Key), + Array1 = array:set(Kix-1, array:get(CurrN-1, Array0), Array0), + Array2 = array:resize(CurrN-1, Array1), + do_mixed(Goals, CurrN-1, Array2, C+1, Rand2) + end. -- cgit v1.2.3 From 3685711811a2d3452d0a55d6872d5dfb705b1933 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 15 Dec 2015 15:26:45 +0100 Subject: ssl: Convert all test to use "ssl_test_lib:portable_open_port" --- lib/ssl/test/ssl_to_openssl_SUITE.erl | 123 +++++++++++++++++----------------- 1 file changed, 61 insertions(+), 62 deletions(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 119baf1072..57acbb94cf 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -753,11 +753,9 @@ erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> "-CAfile", CaCertFile, "-key", KeyFile,"-connect", "localhost:" ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)], - OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), - true = port_command(OpenSslPort, Data), - + true = port_command(OpenSslPort, Data), ssl_test_lib:check_result(Server, ok), %% Clean close down! Server needs to be closed first !! @@ -841,7 +839,6 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) -> Exe = "openssl", Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), "-cert", CertFile, "-key", KeyFile], - OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -1003,7 +1000,7 @@ erlang_client_alpn_openssl_server(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_client_and_openssl_server_with_opts(Config, [{alpn_advertised_protocols, [<<"spdy/2">>]}], - "", + [], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) @@ -1016,7 +1013,7 @@ erlang_client_openssl_server_alpn(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_client_and_openssl_server_with_opts(Config, [], - "-alpn spdy/2", + ["-alpn", "spdy/2"], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) @@ -1153,7 +1150,7 @@ erlang_server_openssl_client_npn_renegotiate(Config) when is_list(Config) -> erlang_client_openssl_server_npn_only_server(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_client_and_openssl_server_with_opts(Config, [], - "-nextprotoneg spdy/2", Data, fun(Server, OpensslPort) -> + ["-nextprotoneg", "spdy/2"], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) end), @@ -1165,7 +1162,7 @@ erlang_client_openssl_server_npn_only_client(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_client_and_openssl_server_with_opts(Config, [{client_preferred_next_protocols, - {client, [<<"spdy/2">>], <<"http/1.1">>}}], "", + {client, [<<"spdy/2">>], <<"http/1.1">>}}], [], Data, fun(Server, OpensslPort) -> true = port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) @@ -1276,14 +1273,14 @@ erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, {from, self()}, {mfa, {?MODULE, send_and_hostname, []}}, {options, ServerOptions}]), Port = ssl_test_lib:inet_port(Server), - ClientCommand = case SNIHostname of + Exe = "openssl", + ClientArgs = case SNIHostname of undefined -> - "openssl s_client -connect " ++ Hostname ++ ":" ++ integer_to_list(Port); + ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port)]; _ -> - "openssl s_client -connect " ++ Hostname ++ ":" ++ integer_to_list(Port) ++ " -servername " ++ SNIHostname - end, - ct:log("Options: ~p", [[ServerOptions, ClientCommand]]), - ClientPort = open_port({spawn, ClientCommand}, [stderr_to_stdout]), + ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port), "-servername", SNIHostname] + end, + ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs), %% Client check needs to be done befor server check, %% or server check might consume client messages @@ -1305,14 +1302,14 @@ erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHo {from, self()}, {mfa, {?MODULE, send_and_hostname, []}}, {options, ServerOptions}]), Port = ssl_test_lib:inet_port(Server), - ClientCommand = case SNIHostname of + Exe = "openssl", + ClientArgs = case SNIHostname of undefined -> - "openssl s_client -connect " ++ Hostname ++ ":" ++ integer_to_list(Port); + ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port)]; _ -> - "openssl s_client -connect " ++ Hostname ++ ":" ++ integer_to_list(Port) ++ " -servername " ++ SNIHostname + ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port), "-servername", SNIHostname] end, - ct:log("Options: ~p", [[ServerOptions, ClientCommand]]), - ClientPort = open_port({spawn, ClientCommand}, [stderr_to_stdout]), + ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs), %% Client check needs to be done befor server check, %% or server check might consume client messages @@ -1332,12 +1329,11 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", - - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key", KeyFile], - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -1395,13 +1391,19 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server " ++ OpensslServerOpts ++ " -accept " ++ - integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile, - - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = case OpensslServerOpts of + [] -> + ["s_server", "-accept", + integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile,"-key", KeyFile]; + [Opt, Value] -> + ["s_server", Opt, Value, "-accept", + integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile,"-key", KeyFile] + end, + + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -1435,13 +1437,10 @@ start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callba KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -msg -alpn http/1.1,spdy/2 -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile, - - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - + Exe = "openssl", + Args = ["s_server", "-msg", "-alpn", "http/1.1,spdy/2", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key" ++ KeyFile], + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, @@ -1473,12 +1472,13 @@ start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, Callba {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -alpn http/1.0,spdy/2 -msg -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost", - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_client", "-alpn", "http/1.0,spdy/2" "-msg" "-port", + integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-host", "localhost"], - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), Callback(Server, OpenSslPort), @@ -1503,12 +1503,12 @@ start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, Ca KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_server -msg -alpn http/1.1,spdy/2 -nextprotoneg spdy/3 -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile, - - ct:log("openssl cmd: ~p~n", [Cmd]), + Exe = "openssl", + Args = ["s_server", "-msg", "-alpn", "http/1.1,spdy/2", "-nextprotoneg", + "spdy/3", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-cert" ++ CertFile ++ "-key" ++ KeyFile], - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -1542,17 +1542,15 @@ start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Ca {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - Cmd = "openssl s_client -alpn http/1.1,spdy/2 -nextprotoneg spdy/3 -msg -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -host localhost", - - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_client", "-alpn", "http/1.1,spdy/2", "-nextprotoneg", "spdy/3", + "-msg", "-port", integer_to_list(Port), ssl_test_lib:version_flag(Version), + "-host", "localhost"], + OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), Callback(Server, OpenSslPort), ssl_test_lib:close(Server), - ssl_test_lib:close_port(OpenSslPort), process_flag(trap_exit, false). @@ -1570,13 +1568,12 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac CertFile = proplists:get_value(certfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Version = tls_record:protocol_version(tls_record:highest_protocol_version([])), - - Cmd = "openssl s_server -msg -nextprotoneg http/1.1,spdy/2 -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile, - - ct:log("openssl cmd: ~p~n", [Cmd]), - - OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + + Exe = "openssl", + Args = ["s_server", "-msg", "-nextprotoneg", "http/1.1,spdy/2", "-accept", integer_to_list(Port), + ssl_test_lib:version_flag(Version), + "-cert", CertFile, "-key", KeyFile], + OpensslPort = ssl_test_lib:portable_open_port(Exe, Args), ssl_test_lib:wait_for_openssl_server(Port), @@ -1759,7 +1756,9 @@ check_sane_openssl_renegotaite(Config) -> end. check_sane_openssl_sslv2(Config) -> - Port = open_port({spawn, "openssl s_client -ssl2 "}, [stderr_to_stdout]), + Exe = "openssl", + Args = ["s_client", "-ssl2"], + Port = ssl_test_lib:portable_open_port(Exe, Args), case supports_sslv2(Port) of true -> Config; -- cgit v1.2.3 From af888f46b08c354021724ca76029930d3baf2e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Oct 2015 14:05:16 +0200 Subject: init_SUITE: Correct the test for a "real system" --- lib/kernel/test/init_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index 54ab5aa566..3fe618ea4c 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -307,8 +307,8 @@ create_boot(Config) -> is_real_system(KernelVsn, StdlibVsn) -> LibDir = code:lib_dir(), - filelib:is_dir(filename:join(LibDir, "kernel"++KernelVsn)) andalso - filelib:is_dir(filename:join(LibDir, "stdlib"++StdlibVsn)). + filelib:is_dir(filename:join(LibDir, "kernel-"++KernelVsn)) andalso + filelib:is_dir(filename:join(LibDir, "stdlib-"++StdlibVsn)). %% ------------------------------------------------ %% Slave executes erlang:halt() on master nodedown. -- cgit v1.2.3 From cf04a89bb3585466896e6eef61bfd6e8aed27527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 17 Dec 2015 08:43:12 +0100 Subject: test_server tests: Update test cases to cope with use of 'rand' In 80757f9, test_server was updated use the new 'rand' module instead of 'random', but the the shuffle test cases were not updated. --- .../test_server_shuffle01_SUITE.erl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl index 847c7b6bdd..80ac9f6b3d 100644 --- a/lib/test_server/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl @@ -224,7 +224,7 @@ conf5_end(_Config) -> ok. conf6_init(Config) when is_list(Config) -> - [{shuffle,{_,_,_}}] = ?config(tc_group_properties,Config), + validate_shuffle(Config), test_server:comment("Shuffle (random)"), init = ?config(suite,Config), [{cc6,conf6}|Config]. @@ -242,23 +242,28 @@ conf5(suite) -> % test specification conf7_init(Config) when is_list(Config) -> test_server:comment("Group 7, Shuffle (random seed)"), - case proplists:get_value(shuffle,?config(tc_group_properties,Config)) of - {_,_,_} -> ok - end, + validate_shuffle(Config), [{cc7,conf7}|Config]. conf7_end(_Config) -> ok. conf8_init(Config) when is_list(Config) -> test_server:comment("Group 8, Shuffle (user start seed)"), - case proplists:get_value(shuffle,?config(tc_group_properties,Config)) of - {_,_,_} -> ok - end, + validate_shuffle(Config), init = ?config(suite,Config), [{cc8,conf8}|Config]. conf8_end(_Config) -> ok. +validate_shuffle(Config) -> + case proplists:get_value(shuffle, ?config(tc_group_properties,Config)) of + {_,_,_} -> + ok; + Seed -> + %% Must be a valid seed. + _ = rand:seed_s(rand:export_seed_s(Seed)) + end. + %%---------- test cases ---------- -- cgit v1.2.3 From 41e0a3fcbcc39ed1b7d503fc6d648c00f858bd42 Mon Sep 17 00:00:00 2001 From: Andrew Bennett Date: Thu, 17 Dec 2015 16:03:05 +0100 Subject: crypto: Support 192-bit keys for AES ECB --- lib/crypto/c_src/crypto.c | 1 + lib/crypto/test/crypto_SUITE.erl | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index bb2771163d..a839518a64 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -452,6 +452,7 @@ struct cipher_type_t cipher_types[] = {"aes_cfb8", &EVP_aes_128_cfb8}, {"aes_cfb128", &EVP_aes_128_cfb128}, {"aes_ecb", &EVP_aes_128_ecb, 16}, + {"aes_ecb", &EVP_aes_192_ecb, 24}, {"aes_ecb", &EVP_aes_256_ecb, 32}, {NULL} }; diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 0b955c0965..30319facea 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1301,7 +1301,31 @@ aes_ecb() -> <<"0000000000000000">>}, {aes_ecb, <<"FEDCBA9876543210">>, - <<"FFFFFFFFFFFFFFFF">>} + <<"FFFFFFFFFFFFFFFF">>}, + %% AES ECB test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + %% F.1.1 ECB-AES128.Encrypt, F.1.2 ECB-AES128.Decrypt + {aes_ecb, + hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710")}, + %% F.1.3 ECB-AES192.Encrypt, F.1.4 ECB-AES192.Decrypt + {aes_ecb, + hexstr2bin("8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710")}, + %% F.1.5 ECB-AES256.Encrypt, F.1.6 ECB-AES256.Decrypt + {aes_ecb, + hexstr2bin("603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710")} ]. aes_ige256() -> -- cgit v1.2.3 From 78a2b1f8dbba3227dc56e86a7df1231c04f5735d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 11 Dec 2015 11:54:20 +0100 Subject: ssh: fix the check that open-ssh supports certain pubkeys in a test suite --- lib/ssh/test/ssh_to_openssh_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 02cc79e4d5..67a61d3c11 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -110,9 +110,9 @@ end_per_testcase(_TestCase, _Config) -> chk_key(Pgm, Name, File, Config) -> case ssh_test_lib:openssh_supports(Pgm, public_key, Name) of - true -> - {skip,lists:concat(["openssh client does not support ",Name])}; false -> + {skip,lists:concat(["openssh client does not support ",Name])}; + true -> {ok,[[Home]]} = init:get_argument(home), KeyFile = filename:join(Home, File), case file:read_file(KeyFile) of -- cgit v1.2.3 From 573552e7c6df1bc828385ff918b1ad1965463ba2 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 18 Dec 2015 12:10:47 +0100 Subject: ssh: add econnaborted to disconnect msgs in test suite --- lib/ssh/test/ssh_protocol_SUITE.erl | 47 +++++++++++++++---------------------- 1 file changed, 19 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 5af60adfae..4c088acabf 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -277,12 +277,7 @@ no_common_alg_server_disconnects(Config) -> {send, hello}, {match, #ssh_msg_kexinit{_='_'}, receive_msg}, {send, ssh_msg_kexinit}, % with server unsupported 'ssh-dss' ! - {match, - {'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, - tcp_closed, - {tcp_error,econnaborted} - ]}, - receive_msg} + {match, disconnect(), receive_msg} ] ). @@ -323,10 +318,7 @@ no_common_alg_client_disconnects(Config) -> first_kex_packet_follows = false, reserved = 0 }}, - {match, - {'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'}, - tcp_closed]}, - receive_msg} + {match, disconnect(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED), receive_msg} ], InitialState) } @@ -437,10 +429,7 @@ bad_service_name_then_correct(Config) -> [{set_options, [print_ops, print_seqnums, print_messages]}, {send, #ssh_msg_service_request{name = "kdjglkfdjgkldfjglkdfjglkfdjglkj"}}, {send, #ssh_msg_service_request{name = "ssh-connection"}}, - {match, {'or',[#ssh_msg_disconnect{_='_'}, - tcp_closed - ]}, - receive_msg} + {match, disconnect(), receive_msg} ], InitialState). @@ -450,10 +439,7 @@ bad_service_name(Config, Name) -> ssh_trpt_test_lib:exec( [{set_options, [print_ops, print_seqnums, print_messages]}, {send, #ssh_msg_service_request{name = Name}}, - {match, {'or',[#ssh_msg_disconnect{_='_'}, - tcp_closed - ]}, - receive_msg} + {match, disconnect(), receive_msg} ], InitialState). %%%-------------------------------------------------------------------- @@ -476,11 +462,7 @@ bad_packet_length(Config, LengthExcess) -> PacketFun}}, %% Prohibit remote decoder starvation: {send, #ssh_msg_service_request{name="ssh-userauth"}}, - {match, {'or',[#ssh_msg_disconnect{_='_'}, - tcp_closed, - {tcp_error,econnaborted} - ]}, - receive_msg} + {match, disconnect(), receive_msg} ], InitialState). %%%-------------------------------------------------------------------- @@ -509,11 +491,7 @@ bad_service_name_length(Config, LengthExcess) -> PacketFun} }, %% Prohibit remote decoder starvation: {send, #ssh_msg_service_request{name="ssh-userauth"}}, - {match, {'or',[#ssh_msg_disconnect{_='_'}, - tcp_closed, - {tcp_error,econnaborted} - ]}, - receive_msg} + {match, disconnect(), receive_msg} ], InitialState). %%%================================================================ @@ -644,3 +622,16 @@ connect_and_kex(Config, InitialState) -> {match, #ssh_msg_newkeys{_='_'}, receive_msg} ], InitialState). + +%%%---------------------------------------------------------------- + +%%% For matching peer disconnection +disconnect() -> + disconnect('_'). + +disconnect(Code) -> + {'or',[#ssh_msg_disconnect{code = Code, + _='_'}, + tcp_closed, + {tcp_error,econnaborted} + ]}. -- cgit v1.2.3 From 516708326db6887190425f5c020e66dfe3666a67 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sun, 20 Dec 2015 16:23:20 +0100 Subject: Be resilient to diameter_service state upgrades By not failing in code that looks up state: pick_peer and service_info. --- lib/diameter/src/base/diameter_service.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index a31cef2c8c..ed22ef7801 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -206,7 +206,7 @@ stop_transport(SvcName, [_|_] = Refs) -> info(SvcName, Item) -> case lookup_state(SvcName) of - [#state{} = S] -> + [S] -> service_info(Item, S); [] -> undefined @@ -215,7 +215,12 @@ info(SvcName, Item) -> %% lookup_state/1 lookup_state(SvcName) -> - ets:lookup(?STATE_TABLE, SvcName). + case ets:lookup(?STATE_TABLE, SvcName) of + [#state{}] = L -> + L; + _ -> + [] + end. %% --------------------------------------------------------------------------- %% # subscribe/1 -- cgit v1.2.3 From 464492d2ebe24bc13c91fbc99550c05eead599d4 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sun, 20 Dec 2015 10:23:44 +0100 Subject: Update/fix appup for 17.5.6.7 OTP-12947 strict_mbit OTP-12969 watchdog function_clause OTP-13137 request leak diameter_config (that allows the new option) should be loaded after the others. Anchor was missing from one regexp. Patches did not accumulate through older versions. --- lib/diameter/src/diameter.appup.src | 66 ++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 38 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index adb3f960ff..7d66557162 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -36,45 +36,40 @@ {"1.4.4", [{restart_application, diameter}]}, {"1.5", [{restart_application, diameter}]}, %% R16B03 {"1.6", [{restart_application, diameter}]}, %% 17.0 - {<<"1\\.(7(\\.1)?|8)$">>, %% 17.[134] + {<<"^1\\.(7(\\.1)?|8)$">>, %% 17.[134] [{restart_application, diameter}]}, {<<"^1.9(\\.1)?$">>, %% 17.5(.3)? - [{load_module, diameter_codec}, - {load_module, diameter_traffic}, - {load_module, diameter_sctp}, - {load_module, diameter_peer_fsm}, + [{restart_application, diameter}]}, + {"1.9.2", [{load_module, diameter_peer_fsm}, %% 17.5.5 {load_module, diameter_watchdog}, {load_module, diameter_stats}, - {load_module, diameter_config}, + {load_module, diameter_codec}, {load_module, diameter_lib}, {load_module, diameter_peer}, {load_module, diameter_reg}, {load_module, diameter_service}, {load_module, diameter_session}, {load_module, diameter_sync}, + {load_module, diameter_traffic}, + {load_module, diameter_sctp}, {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_base_accounting}, - {load_module, diameter_gen_relay}]}, - {"1.9.2", [{load_module, diameter_peer_fsm}, %% 17.5.5 - {load_module, diameter_watchdog}, - {load_module, diameter_stats}, - {load_module, diameter_config}, + {load_module, diameter_gen_relay}, + {load_module, diameter}, + {load_module, diameter_config}]}, + {"1.9.2.1", [{load_module, diameter_watchdog}, %% 17.5.6.3 {load_module, diameter_codec}, - {load_module, diameter_lib}, - {load_module, diameter_peer}, - {load_module, diameter_reg}, - {load_module, diameter_service}, - {load_module, diameter_session}, - {load_module, diameter_sync}, {load_module, diameter_traffic}, - {load_module, diameter_sctp}, + {load_module, diameter_service}, {load_module, diameter_gen_base_rfc6733}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_base_accounting}, - {load_module, diameter_gen_relay}]} + {load_module, diameter_gen_relay}, + {load_module, diameter, + {load_module, diameter_config}}]} ], [ {"0.9", [{restart_application, diameter}]}, @@ -93,44 +88,39 @@ {"1.4.4", [{restart_application, diameter}]}, {"1.5", [{restart_application, diameter}]}, {"1.6", [{restart_application, diameter}]}, - {<<"1\\.(7(\\.1)?|8)$">>, + {<<"^1\\.(7(\\.1)?|8)$">>, [{restart_application, diameter}]}, {<<"^1.9(\\.1)?$">>, - [{load_module, diameter_gen_relay}, + [{restart_application, diameter}]}, + {"1.9.2", [{load_module, diameter_config}, + {load_module, diameter}, + {load_module, diameter_gen_relay}, {load_module, diameter_gen_base_accounting}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc6733}, + {load_module, diameter_sctp}, + {load_module, diameter_traffic}, {load_module, diameter_sync}, {load_module, diameter_session}, {load_module, diameter_service}, {load_module, diameter_reg}, {load_module, diameter_peer}, {load_module, diameter_lib}, - {load_module, diameter_config}, + {load_module, diameter_codec}, {load_module, diameter_stats}, {load_module, diameter_watchdog}, - {load_module, diameter_peer_fsm}, - {load_module, diameter_sctp}, - {load_module, diameter_traffic}, - {load_module, diameter_codec}]}, - {"1.9.2", [{load_module, diameter_gen_relay}, + {load_module, diameter_peer_fsm}]}, + {"1.9.2.1", [{load_module, diameter_config}, + {load_module, diameter}, + {load_module, diameter_gen_relay}, {load_module, diameter_gen_base_accounting}, {load_module, diameter_gen_base_rfc3588}, {load_module, diameter_gen_acct_rfc6733}, {load_module, diameter_gen_base_rfc6733}, - {load_module, diameter_sctp}, - {load_module, diameter_traffic}, - {load_module, diameter_sync}, - {load_module, diameter_session}, {load_module, diameter_service}, - {load_module, diameter_reg}, - {load_module, diameter_peer}, - {load_module, diameter_lib}, + {load_module, diameter_traffic}, {load_module, diameter_codec}, - {load_module, diameter_config}, - {load_module, diameter_stats}, - {load_module, diameter_watchdog}, - {load_module, diameter_peer_fsm}]} + {load_module, diameter_watchdog}]} ] }. -- cgit v1.2.3 From 68198c72bc4924d42ea54b4ea0997109ec59cfeb Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sun, 20 Dec 2015 11:01:24 +0100 Subject: vsn -> 1.9.2.2 --- lib/diameter/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk index a16b8d712c..18b77e243f 100644 --- a/lib/diameter/vsn.mk +++ b/lib/diameter/vsn.mk @@ -16,5 +16,5 @@ # %CopyrightEnd% APPLICATION = diameter -DIAMETER_VSN = 1.9.2.1 +DIAMETER_VSN = 1.9.2.2 APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN) -- cgit v1.2.3 From 6a6ff0791a7de5a7a9e034366271497aa2130204 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Sun, 20 Dec 2015 16:29:15 +0100 Subject: Update release notes --- lib/diameter/doc/src/notes.xml | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'lib') diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index 7726d761bd..838b1ad7dc 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -42,6 +42,58 @@ first.

+
diameter 1.9.2.2 + +
Fixed Bugs and Malfunctions + + +

+ Fix diameter_watchdog function clause.

+

+ OTP-12912 introduced an error with accepting transports + setting {restrict_connections, false}, causing + processes to fail when peer connections were terminated.

+

+ Own Id: OTP-12969

+
+ +

+ Fix request table leaks

+

+ The End-to-End and Hop-by-Hop identifiers of outgoing + Diameter requests are stored in a table in order for the + caller to be located when the corresponding answer + message is received. Entries were orphaned if the handler + was terminated by an exit signal as a consequence of + actions taken by callback functions, or if callbacks + modified identifiers in retransmission cases.

+

+ Own Id: OTP-13137

+
+
+
+ + +
Improvements and New Features + + +

+ Add service_opt() strict_mbit.

+

+ There are differing opinions on whether or not reception + of an arbitrary AVP setting the M-bit is an error. The + default interpretation is strict: if a command grammar + doesn't explicitly allow an AVP setting the M-bit then + reception of such an AVP is regarded as an error. Setting + {strict_mbit, false} disables this check.

+

+ Own Id: OTP-12947

+
+
+
+ +
+
diameter 1.9.2.1
Fixed Bugs and Malfunctions -- cgit v1.2.3 From c3135a817f22f76b1ae594dc5821d2d6eab1d25a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 11 Dec 2015 12:01:43 +0100 Subject: ssh: Add first version of ssh_benchmark_SUITE --- lib/ssh/test/Makefile | 5 +- lib/ssh/test/ssh.spec | 3 + lib/ssh/test/ssh_bench.spec | 1 + lib/ssh/test/ssh_benchmark_SUITE.erl | 295 +++++++++++++++++++++ lib/ssh/test/ssh_benchmark_SUITE_data/id_dsa | 13 + lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256 | 5 + .../test/ssh_benchmark_SUITE_data/id_ecdsa256.pub | 1 + lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384 | 6 + .../test/ssh_benchmark_SUITE_data/id_ecdsa384.pub | 1 + lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521 | 7 + .../test/ssh_benchmark_SUITE_data/id_ecdsa521.pub | 1 + lib/ssh/test/ssh_benchmark_SUITE_data/id_rsa | 15 ++ .../test/ssh_benchmark_SUITE_data/ssh_host_dsa_key | 13 + .../ssh_benchmark_SUITE_data/ssh_host_dsa_key.pub | 11 + .../ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256 | 5 + .../ssh_host_ecdsa_key256.pub | 1 + .../ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384 | 6 + .../ssh_host_ecdsa_key384.pub | 1 + .../ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521 | 7 + .../ssh_host_ecdsa_key521.pub | 1 + .../test/ssh_benchmark_SUITE_data/ssh_host_rsa_key | 16 ++ .../ssh_benchmark_SUITE_data/ssh_host_rsa_key.pub | 5 + 22 files changed, 416 insertions(+), 3 deletions(-) create mode 100644 lib/ssh/test/ssh_bench.spec create mode 100644 lib/ssh/test/ssh_benchmark_SUITE.erl create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_dsa create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256 create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256.pub create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384 create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384.pub create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521 create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521.pub create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/id_rsa create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key.pub create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256 create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256.pub create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384 create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384.pub create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521 create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521.pub create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key create mode 100644 lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key.pub (limited to 'lib') diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile index 781a876723..9cd98f069f 100644 --- a/lib/ssh/test/Makefile +++ b/lib/ssh/test/Makefile @@ -35,9 +35,8 @@ MODULES= \ ssh_algorithms_SUITE \ ssh_options_SUITE \ ssh_renegotiate_SUITE \ - \ ssh_basic_SUITE \ - \ + ssh_benchmark_SUITE \ ssh_connection_SUITE \ ssh_protocol_SUITE \ ssh_sftp_SUITE \ @@ -129,7 +128,7 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)" $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)" - $(INSTALL_DATA) ssh.spec ssh.cover "$(RELSYSDIR)" + $(INSTALL_DATA) ssh.spec ssh_bench.spec ssh.cover "$(RELSYSDIR)" $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec index 8de0fe44e4..a3296d97a1 100644 --- a/lib/ssh/test/ssh.spec +++ b/lib/ssh/test/ssh.spec @@ -1,4 +1,7 @@ {suites,"../ssh_test",all}. +{skip_cases, "../ssh_test", + ssl_benchmark_SUITE, [openssh_shell,erl_shell], + "Benchmarks run separately"}. {skip_cases,"../ssh_test",ssh_ssh_SUITE, [ssh], "Current implementation is timingdependent and\nhence will succeed/fail on a whim"}. diff --git a/lib/ssh/test/ssh_bench.spec b/lib/ssh/test/ssh_bench.spec new file mode 100644 index 0000000000..029f0bd074 --- /dev/null +++ b/lib/ssh/test/ssh_bench.spec @@ -0,0 +1 @@ +{suites,"../ssh_test",[ssh_benchmark_SUITE]}. diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl new file mode 100644 index 0000000000..0d7239c5b5 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -0,0 +1,295 @@ +%%%------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(ssh_benchmark_SUITE). +-compile(export_all). + +-include_lib("common_test/include/ct_event.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-include_lib("ssh/src/ssh.hrl"). +-include_lib("ssh/src/ssh_connect.hrl"). + +suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}]. +%%suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> [{group, opensshc_erld} +%% {group, erlc_opensshd} + ]. + +groups() -> + [{opensshc_erld, [{repeat, 3}], [openssh_client_shell]}, + {erlc_opensshd, [{repeat, 3}], [erl_shell]} + ]. + + +init_per_suite(Config) -> + catch ssh:stop(), + catch crypto:stop(), + try + ok = crypto:start(), + ok = ssh:start(), + {ok,TracerPid} = erlang_trace(), + [{tracer_pid,TracerPid} | Config] + catch + C:E -> + {skip, io_lib:format("Couldn't start ~p:~p",[C,E])} + end. + +end_per_suite(_Config) -> + catch ssh:stop(), + catch crypto:stop(), + ok. + + + +init_per_group(opensshc_erld, Config) -> + case ssh_test_lib:ssh_type() of + openSSH -> + DataDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + ssh_test_lib:setup_dsa(DataDir, UserDir), + ssh_test_lib:setup_rsa(DataDir, UserDir), + ssh_test_lib:setup_ecdsa("256", DataDir, UserDir), + [{c_kexs, ssh_test_lib:sshc(kex)}, + {c_ciphers, ssh_test_lib:sshc(cipher)} + | Config]; + _ -> + {skip, "No OpenSsh client found"} + end; + +init_per_group(erlc_opensshd, _) -> + {skip, "Group erlc_opensshd not implemented"}; + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, _Config) -> + ok. + + +init_per_testcase(_Func, Conf) -> + Conf. + +end_per_testcase(_Func, _Conf) -> + ok. + +%%%================================================================ +openssh_client_shell(Config) -> + SystemDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + KnownHosts = filename:join(UserDir, "known_hosts"), + + {ok, TracerPid} = erlang_trace(), + {ServerPid, _Host, Port} = + ssh_test_lib:daemon([{system_dir, SystemDir}, + {public_key_alg, ssh_dsa}, + {failfun, fun ssh_test_lib:failfun/2}]), + ct:sleep(500), + + Data = lists:duplicate(100000, $a), + Cmd = lists:concat(["ssh -p ",Port, + " -o UserKnownHostsFile=", KnownHosts, + " -o \"StrictHostKeyChecking no\"", + " localhost '\"",Data,"\"'."]), +%% ct:pal("Cmd ="++Cmd), + + Parent = self(), + SlavePid = spawn(fun() -> + Parent ! {self(),os:cmd(Cmd)} + end), + receive + {SlavePid, ClientResponse} -> +%% ct:pal("ClientResponse = ~p",[ClientResponse]), + {ok, List} = get_trace_list(TracerPid), + Times = find_times(List), + Algs = proplists:get_value(algorithms, List, #alg{}), + ct:pal("List = ~p~n~nAlgorithms = ~p~n~nTimes = ~p",[List,Algs,Times]), + lists:foreach( + fun({Tag0,MicroSeconds,Unit}) -> + Tag = case Tag0 of + {A,B} -> lists:concat([A," ",B]); + _ when is_list(Tag0) -> lists:concat(Tag0); + _ when is_atom(Tag0) -> Tag0 + end, + DataName = + ["Erl server ",Tag,sp(algo(Tag,Algs))," [",Unit,"]"], + EventData = [{value, MicroSeconds}, + {suite, ?MODULE}, + {name, lists:concat(DataName)} + ], + ct:pal("ct_event:notify ~p",[EventData]), + ct_event:notify(#event{name = benchmark_data, + data = EventData}) + end, Times), + ssh:stop_daemon(ServerPid), + ok + after 10000 -> + ssh:stop_daemon(ServerPid), + exit(SlavePid, kill), + {fail, timeout} + end. + + +algo(kex, #alg{kex=Alg} ) -> Alg; +algo(_, _) -> "". + +sp("") -> ""; +sp(A) -> lists:concat([" ",A]). + +%%%================================================================ +find_times(L) -> + [{accept_to_hello, find_time([tcp_accept, + {send,hello}], L, [])/1000, + millisec}, + {kex, find_time([{send,hello}, + {send,ssh_msg_newkeys}], L, []), + microsec}, + {kex_to_auth, find_time([{send,ssh_msg_newkeys}, + {recv,ssh_msg_userauth_request}], L, []), + microsec}, + {auth, find_time([{recv,ssh_msg_userauth_request}, + {send,ssh_msg_userauth_success}], L, []), + microsec}, + {to_prompt, find_time([tcp_accept, + {recv,{ssh_msg_channel_request,"env"}}], L, []), + microsec} + + | alg_times([encrypt,decrypt], L) + ]. + + +find_time([Event|Events], [{Event,T}|TraceList], Ts) -> + %% Important that the first one found is used! + find_time(Events, TraceList, [T|Ts]); +find_time([], _, [T1,T0]) -> + now2micro_sec(now_diff(T1,T0)); +find_time(Events, [_|TraceList], Ts) -> + find_time(Events, TraceList, Ts); +find_time(_, [], _Ts) -> + throw({error,not_found}). + + + +alg_times(Ops, L) -> + OpAlgs = lists:usort([{Op,Alg} || Op <- Ops, + {{{Op,Alg},_,_},_} <- L]), + [begin + {[Op,"(",Alg,")"], + sum_times(OpAlg, L, 0, 0), + "microsec/kbyte" + } + end || {Op,Alg} = OpAlg <- OpAlgs]. + + +sum_times(T, [{{T,start,Id={_,Nbytes}},TS0}|Events], SumBytes, SumMicroSec) -> + TS1 = proplists:get_value({T,stop,Id}, Events), + sum_times(T, Events, SumBytes+Nbytes, SumMicroSec+now2micro_sec(now_diff(TS1,TS0))); +sum_times(T, [_|Events], SumBytes, SumMicroSec) -> + sum_times(T, Events, SumBytes, SumMicroSec); +sum_times(T, [], SumBytes, SumMicroSec) -> + round(1024*SumMicroSec / SumBytes). % Microseconds per 1k bytes. + +%%%---------------------------------------------------------------- +%%% +%%% API for the traceing +%%% +get_trace_list(TracerPid) -> + TracerPid ! {get_trace_list,self()}, + receive + {trace_list,L} -> {ok,lists:reverse(L)} + after 5000 -> {error,no_reply} + end. + +erlang_trace() -> + TracerPid = spawn(fun trace_loop/0), + 0 = erlang:trace(new, true, [call,timestamp,{tracer,TracerPid}]), + [init_trace(MFA, TP) + || {MFA,TP} <- [{{ssh_acceptor,handle_connection,5}, []}, + {{ssh_connection_handler,hello,2}, []}, + {{ssh_message,encode,1}, []}, + {{ssh_message,decode,1}, [{['_'], [], [{return_trace}]}]}, + {{ssh_transport,select_algorithm,3}, [{['_','_','_'], [], [{return_trace}]}]}, + {{ssh_transport,encrypt,2}, [{['_','_'], [], [{return_trace}]}]}, + {{ssh_transport,decrypt,2}, [{['_','_'], [], [{return_trace}]}]} + ]], + {ok, TracerPid}. + + +%%%---------------- +init_trace(MFA = {Module,_,_}, TP) -> + case code:is_loaded(Module) of + false -> code:load_file(Module); + _ -> ok + end, + erlang:trace_pattern(MFA, TP, [local]). + + +trace_loop() -> + trace_loop([]). + +trace_loop(L) -> + receive + {trace_ts, Pid, call, {M,F,Args}, TS} = Ev -> + cond_pal(Ev), + trace_loop(save_event(call, Pid, {M,F,Args}, TS, L)); + {trace_ts, Pid, return_from, {M,F,Arity}, Ret, TS} = Ev -> + cond_pal(Ev), + trace_loop(save_event(return_from, Pid, {M,F,Arity,Ret}, TS, L)); + {get_trace_list, From} -> + From ! {trace_list, L}, + trace_loop(L) + + ; Other -> io:format('~p got ~p~n',[self(),Other]), trace_loop(L) + end. + +%%cond_pal(Ev) -> ct:pal("~p",[Ev]). +cond_pal(Ev) -> ok. + + +save_event(_Type, _Pid, MFA, TimeStamp, L) -> + try + event_name(MFA) + of + {Tag, 'TS'} -> [{Tag,TimeStamp} | L]; + Val -> [Val | L] + catch + _:_ -> L + end. + +event_name({ssh_acceptor,handle_connection,_}) -> {tcp_accept, 'TS'}; +event_name({ssh_connection_handler,hello,[socket_control|_]}) -> {{send,hello}, 'TS'}; +event_name({ssh_connection_handler,hello,[{version_exchange,_}|_]}) -> {{recv,hello}, 'TS'}; +event_name({ssh_message,encode,[Msg]}) -> {{send,element(1,Msg)}, 'TS'}; +event_name({ssh_message,decode,1, + #ssh_msg_channel_request{request_type=ReqType}}) -> {{recv,{ssh_msg_channel_request,ReqType}}, 'TS'}; +event_name({ssh_message,decode,1,Return}) -> {{recv,element(1,Return)}, 'TS'}; +event_name({ssh_transport,select_algorithm,3,{ok,Algs}}) -> {algorithms,Algs}; +event_name({ssh_transport,encrypt,[S,Data]}) -> {{{encrypt,S#ssh.encrypt},start, {S#ssh.send_sequence,size(Data)}}, 'TS'}; +event_name({ssh_transport,encrypt,2,{S,Ret}}) -> {{{encrypt,S#ssh.encrypt},stop, {S#ssh.send_sequence,size(Ret) }}, 'TS'}; +event_name({ssh_transport,decrypt,[S,Data]}) -> {{{decrypt,S#ssh.decrypt},start, {S#ssh.recv_sequence,size(Data)}}, 'TS'}; +event_name({ssh_transport,decrypt,2,{S,Ret}}) -> {{{decrypt,S#ssh.decrypt},stop, {S#ssh.recv_sequence,size(Ret) }}, 'TS'}. + + +now2sec({A,B,C}) -> A*1000000 + B + C/1000000. + +now2micro_sec({A,B,C}) -> (A*1000000 + B)*1000000 + C. + +now_diff({A1,B1,C1}, {A0,B0,C0}) -> {A1-A0, B1-B0, C1-C0}. + diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_dsa b/lib/ssh/test/ssh_benchmark_SUITE_data/id_dsa new file mode 100644 index 0000000000..d306f8b26e --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_dsa @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ +APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod +/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP +kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW +JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD +OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt ++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e +uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX +Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE +ZU8w8Q+H7z0j+a+70x2iAw== +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256 b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256 new file mode 100644 index 0000000000..4b1eb12eaa --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJfCaBKIIKhjbJl5F8BedqlXOQYDX5ba9Skypllmx/w+oAoGCCqGSM49 +AwEHoUQDQgAE49RbK2xQ/19ji3uDPM7uT4692LbwWF1TiaA9vUuebMGazoW/98br +N9xZu0L1AWwtEjs3kmJDTB7eJEGXnjUAcQ== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256.pub new file mode 100644 index 0000000000..a0147e60fa --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPUWytsUP9fY4t7gzzO7k+Ovdi28FhdU4mgPb1LnmzBms6Fv/fG6zfcWbtC9QFsLRI7N5JiQ0we3iRBl541AHE= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384 b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384 new file mode 100644 index 0000000000..4e8aa40959 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCYXb6OSAZyXRfLXOtMo43za197Hdc/T0YKjgQQjwDt6rlRwqTh7v7S +PV2kXwNGdWigBwYFK4EEACKhZANiAARN2khlJUOOIiwsWHEALwDieeZR96qL4pUd +ci7aeGaczdUK5jOA9D9zmBZtSYTfO8Cr7ekVghDlcWAIJ/BXcswgQwSEQ6wyfaTF +8FYfyr4l3u9IirsnyaFzeIgeoNis8Gw= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384.pub new file mode 100644 index 0000000000..41e722e545 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBE3aSGUlQ44iLCxYcQAvAOJ55lH3qovilR1yLtp4ZpzN1QrmM4D0P3OYFm1JhN87wKvt6RWCEOVxYAgn8FdyzCBDBIRDrDJ9pMXwVh/KviXe70iKuyfJoXN4iB6g2KzwbA== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521 b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521 new file mode 100644 index 0000000000..7196f46e97 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHbAgEBBEFMadoz4ckEcClfqXa2tiUuYkJdDfwq+/iFQcpt8ESuEd26IY/vm47Q +9UzbPkO4ou8xkNsQ3WvCRQBBWtn5O2kUU6AHBgUrgQQAI6GBiQOBhgAEAde5BRu5 +01/jS0jRk212xsb2DxPrxNpgp6IMCV8TA4Eps+8bSqHB091nLiBcP422HXYfuCd7 +XDjSs8ihcmhp0hCRASLqZR9EzW9W/SOt876May1Huj5X+WSO6RLe7vPn9vmf7kHf +pip6m7M7qp2qGgQ3q2vRwS2K/O6156ohiOlmuuFs +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521.pub new file mode 100644 index 0000000000..8f059120bc --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_ecdsa521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHXuQUbudNf40tI0ZNtdsbG9g8T68TaYKeiDAlfEwOBKbPvG0qhwdPdZy4gXD+Nth12H7gne1w40rPIoXJoadIQkQEi6mUfRM1vVv0jrfO+jGstR7o+V/lkjukS3u7z5/b5n+5B36YqepuzO6qdqhoEN6tr0cEtivzuteeqIYjpZrrhbA== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/id_rsa b/lib/ssh/test/ssh_benchmark_SUITE_data/id_rsa new file mode 100644 index 0000000000..9d7e0dd5fb --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/id_rsa @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU +DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl +zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB +AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V +TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3 +CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK +SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p +z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd +WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39 +sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3 +xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ +dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x +ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak= +-----END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256 new file mode 100644 index 0000000000..2979ea88ed --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49 +AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s +VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256.pub new file mode 100644 index 0000000000..85dc419345 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384 b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384 new file mode 100644 index 0000000000..fb1a862ded --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDArxbDfh3p1okrD9wQw6jJ4d4DdlBPD5GqXE8bIeRJiK41Sh40LgvPw +mkqEDSXK++CgBwYFK4EEACKhZANiAAScl43Ih2lWTDKrSox5ve5uiTXil4smsup3 +CfS1XPjKxgBAmlfBim8izbdrT0BFdQzz2joduNMtpt61wO4rGs6jm0UP7Kim9PC7 +Hneb/99fIYopdMH5NMnk60zGO1uZ2vc= +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384.pub new file mode 100644 index 0000000000..428d5fb7d7 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBJyXjciHaVZMMqtKjHm97m6JNeKXiyay6ncJ9LVc+MrGAECaV8GKbyLNt2tPQEV1DPPaOh240y2m3rXA7isazqObRQ/sqKb08Lsed5v/318hiil0wfk0yeTrTMY7W5na9w== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521 b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521 new file mode 100644 index 0000000000..3e51ec2ecd --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIB8O1BFkl2HQjQLRLonEZ97da/h39DMa9/0/hvPZWAI8gUPEQcHxRx +U7b09p3Zh+EBbMFq8+1ae9ds+ZTxE4WFSvKgBwYFK4EEACOhgYkDgYYABAAlWVjq +Bzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/ +vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5 +ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== +-----END EC PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521.pub new file mode 100644 index 0000000000..017a29f4da --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_ecdsa_key521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAlWVjqBzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== uabhnil@elxadlj3q32 diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..75d2025c71 --- /dev/null +++ b/lib/ssh/test/ssh_benchmark_SUITE_data/ssh_host_rsa_key.pub @@ -0,0 +1,5 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8 +semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW +RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== +---- END SSH2 PUBLIC KEY ---- -- cgit v1.2.3 From ee18dff59a88407e66eb852e3226665cddc8080b Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 15 Dec 2015 21:05:39 +0100 Subject: ssh: ssh_benchmark_SUITE re-organized --- lib/ssh/test/ssh_benchmark_SUITE.erl | 251 +++++++++++++++++++++-------------- 1 file changed, 151 insertions(+), 100 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl index 0d7239c5b5..fe22aa9f20 100644 --- a/lib/ssh/test/ssh_benchmark_SUITE.erl +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -24,7 +24,10 @@ -include_lib("common_test/include/ct.hrl"). -include_lib("ssh/src/ssh.hrl"). +-include_lib("ssh/src/ssh_transport.hrl"). -include_lib("ssh/src/ssh_connect.hrl"). +-include_lib("ssh/src/ssh_userauth.hrl"). + suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}]. %%suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -115,14 +118,14 @@ openssh_client_shell(Config) -> Parent ! {self(),os:cmd(Cmd)} end), receive - {SlavePid, ClientResponse} -> -%% ct:pal("ClientResponse = ~p",[ClientResponse]), + {SlavePid, _ClientResponse} -> +%% ct:pal("ClientResponse = ~p",[_ClientResponse]), {ok, List} = get_trace_list(TracerPid), Times = find_times(List), - Algs = proplists:get_value(algorithms, List, #alg{}), - ct:pal("List = ~p~n~nAlgorithms = ~p~n~nTimes = ~p",[List,Algs,Times]), + Algs = find_algs(List), + ct:pal("Algorithms = ~p~n~nTimes = ~p",[Algs,Times]), lists:foreach( - fun({Tag0,MicroSeconds,Unit}) -> + fun({Tag0,Value,Unit}) -> Tag = case Tag0 of {A,B} -> lists:concat([A," ",B]); _ when is_list(Tag0) -> lists:concat(Tag0); @@ -130,7 +133,7 @@ openssh_client_shell(Config) -> end, DataName = ["Erl server ",Tag,sp(algo(Tag,Algs))," [",Unit,"]"], - EventData = [{value, MicroSeconds}, + EventData = [{value, Value}, {suite, ?MODULE}, {name, lists:concat(DataName)} ], @@ -155,56 +158,109 @@ sp(A) -> lists:concat([" ",A]). %%%================================================================ find_times(L) -> - [{accept_to_hello, find_time([tcp_accept, - {send,hello}], L, [])/1000, - millisec}, - {kex, find_time([{send,hello}, - {send,ssh_msg_newkeys}], L, []), - microsec}, - {kex_to_auth, find_time([{send,ssh_msg_newkeys}, - {recv,ssh_msg_userauth_request}], L, []), - microsec}, - {auth, find_time([{recv,ssh_msg_userauth_request}, - {send,ssh_msg_userauth_success}], L, []), - microsec}, - {to_prompt, find_time([tcp_accept, - {recv,{ssh_msg_channel_request,"env"}}], L, []), - microsec} - - | alg_times([encrypt,decrypt], L) - ]. - - -find_time([Event|Events], [{Event,T}|TraceList], Ts) -> - %% Important that the first one found is used! - find_time(Events, TraceList, [T|Ts]); -find_time([], _, [T1,T0]) -> - now2micro_sec(now_diff(T1,T0)); -find_time(Events, [_|TraceList], Ts) -> - find_time(Events, TraceList, Ts); -find_time(_, [], _Ts) -> - throw({error,not_found}). - + Xs = [accept_to_hello, kex, kex_to_auth, auth, to_prompt], + [find_time(X,L) || X <- Xs] ++ + crypto_algs_times_sizes([encrypt,decrypt], L). + +-record(call, { + mfa, + pid, + t_call, + t_return, + args, + result + }). +%%%---------------- +-define(send(M), fun(C=#call{mfa = {ssh_message,encode,1}, + args = [M]}) -> + C#call.t_return + end). + +-define(recv(M), fun(C=#call{mfa = {ssh_message,decode,1}, + result = M}) -> + C#call.t_call + end). + +find_time(accept_to_hello, L) -> + [T0,T1] = find([fun(C=#call{mfa = {ssh_acceptor,handle_connection,5}}) -> + C#call.t_call + end, + fun(C=#call{mfa = {ssh_connection_handler,hello,_}, + args = [socket_control|_]}) -> + C#call.t_return + end + ], L, []), + {accept_to_hello, now2micro_sec(now_diff(T1,T0)), microsec}; +find_time(kex, L) -> + [T0,T1] = find([fun(C=#call{mfa = {ssh_connection_handler,hello,_}, + args = [socket_control|_]}) -> + C#call.t_call + end, + ?send(#ssh_msg_newkeys{}) + ], L, []), + {kex, now2micro_sec(now_diff(T1,T0)), microsec}; +find_time(kex_to_auth, L) -> + [T0,T1] = find([?send(#ssh_msg_newkeys{}), + ?recv(#ssh_msg_userauth_request{}) + ], L, []), + {kex_to_auth, now2micro_sec(now_diff(T1,T0)), microsec}; +find_time(auth, L) -> + [T0,T1] = find([?recv(#ssh_msg_userauth_request{}), + ?send(#ssh_msg_userauth_success{}) + ], L, []), + {auth, now2micro_sec(now_diff(T1,T0)), microsec}; +find_time(to_prompt, L) -> + [T0,T1] = find([fun(C=#call{mfa = {ssh_acceptor,handle_connection,5}}) -> + C#call.t_call + end, + ?recv(#ssh_msg_channel_request{request_type="env"}) + ], L, []), + {to_prompt, now2micro_sec(now_diff(T1,T0)), microsec}. + + +find([F|Fs], [C|Cs], Acc) when is_function(F,1) -> + try + F(C) + of + T -> find(Fs, Cs, [T|Acc]) + catch + _:_ -> find([F|Fs], Cs, Acc) + end; +find([], _, Acc) -> + lists:reverse(Acc). -alg_times(Ops, L) -> - OpAlgs = lists:usort([{Op,Alg} || Op <- Ops, - {{{Op,Alg},_,_},_} <- L]), - [begin - {[Op,"(",Alg,")"], - sum_times(OpAlg, L, 0, 0), - "microsec/kbyte" - } - end || {Op,Alg} = OpAlg <- OpAlgs]. +find_algs(L) -> + {value,#call{result={ok,Algs}}} = + lists:keysearch({ssh_transport,select_algorithm,3}, #call.mfa, L), + Algs. -sum_times(T, [{{T,start,Id={_,Nbytes}},TS0}|Events], SumBytes, SumMicroSec) -> - TS1 = proplists:get_value({T,stop,Id}, Events), - sum_times(T, Events, SumBytes+Nbytes, SumMicroSec+now2micro_sec(now_diff(TS1,TS0))); -sum_times(T, [_|Events], SumBytes, SumMicroSec) -> - sum_times(T, Events, SumBytes, SumMicroSec); -sum_times(T, [], SumBytes, SumMicroSec) -> - round(1024*SumMicroSec / SumBytes). % Microseconds per 1k bytes. +%%%---------------- +crypto_algs_times_sizes(EncDecs, L) -> + Raw = [{_Algorithm = case EncDec of + encrypt -> [encrypt," ",S#ssh.encrypt]; + decrypt -> [decrypt," ",S#ssh.decrypt] + end, + size(Data), + now2micro_sec(now_diff(T1, T0)) + } + || EncDec <- EncDecs, + #call{mfa = {ssh_transport,ED,2}, + args = [S,Data], + t_call = T0, + t_return = T1} <- L, + ED == EncDec + ], + [{Alg, round(1024*Time/Size), "microsec/kbyte"} % Microseconds per 1k bytes. + || {Alg,Size,Time} <- lists:foldl(fun increment/2, [], Raw)]. + +increment({Alg,Sz,T}, [{Alg,SumSz,SumT}|Acc]) -> + [{Alg,SumSz+Sz,SumT+T} | Acc]; +increment(Spec, [X|Acc]) -> + [X | increment(Spec,Acc)]; % Not so many Alg, 2 or 3 +increment({Alg,Sz,T},[]) -> + [{Alg,Sz,T}]. %%%---------------------------------------------------------------- %%% @@ -213,26 +269,28 @@ sum_times(T, [], SumBytes, SumMicroSec) -> get_trace_list(TracerPid) -> TracerPid ! {get_trace_list,self()}, receive - {trace_list,L} -> {ok,lists:reverse(L)} + {trace_list,L} -> {ok, pair_events(lists:reverse(L))} after 5000 -> {error,no_reply} end. erlang_trace() -> TracerPid = spawn(fun trace_loop/0), 0 = erlang:trace(new, true, [call,timestamp,{tracer,TracerPid}]), - [init_trace(MFA, TP) - || {MFA,TP} <- [{{ssh_acceptor,handle_connection,5}, []}, - {{ssh_connection_handler,hello,2}, []}, - {{ssh_message,encode,1}, []}, - {{ssh_message,decode,1}, [{['_'], [], [{return_trace}]}]}, - {{ssh_transport,select_algorithm,3}, [{['_','_','_'], [], [{return_trace}]}]}, - {{ssh_transport,encrypt,2}, [{['_','_'], [], [{return_trace}]}]}, - {{ssh_transport,decrypt,2}, [{['_','_'], [], [{return_trace}]}]} - ]], + [init_trace(MFA, tp(MFA)) + || MFA <- [{ssh_acceptor,handle_connection,5}, + {ssh_connection_handler,hello,2}, + {ssh_message,encode,1}, + {ssh_message,decode,1}, + {ssh_transport,select_algorithm,3}, + {ssh_transport,encrypt,2}, + {ssh_transport,decrypt,2} + ]], {ok, TracerPid}. +tp({_M,_F,Arity}) -> + [{lists:duplicate(Arity,'_'), [], [{return_trace}]}]. -%%%---------------- +%%%---------------------------------------------------------------- init_trace(MFA = {Module,_,_}, TP) -> case code:is_loaded(Module) of false -> code:load_file(Module); @@ -246,50 +304,43 @@ trace_loop() -> trace_loop(L) -> receive - {trace_ts, Pid, call, {M,F,Args}, TS} = Ev -> - cond_pal(Ev), - trace_loop(save_event(call, Pid, {M,F,Args}, TS, L)); - {trace_ts, Pid, return_from, {M,F,Arity}, Ret, TS} = Ev -> - cond_pal(Ev), - trace_loop(save_event(return_from, Pid, {M,F,Arity,Ret}, TS, L)); {get_trace_list, From} -> From ! {trace_list, L}, - trace_loop(L) - - ; Other -> io:format('~p got ~p~n',[self(),Other]), trace_loop(L) + trace_loop(L); + Ev -> + trace_loop([Ev|L]) end. - -%%cond_pal(Ev) -> ct:pal("~p",[Ev]). -cond_pal(Ev) -> ok. - - -save_event(_Type, _Pid, MFA, TimeStamp, L) -> - try - event_name(MFA) - of - {Tag, 'TS'} -> [{Tag,TimeStamp} | L]; - Val -> [Val | L] - catch - _:_ -> L - end. - -event_name({ssh_acceptor,handle_connection,_}) -> {tcp_accept, 'TS'}; -event_name({ssh_connection_handler,hello,[socket_control|_]}) -> {{send,hello}, 'TS'}; -event_name({ssh_connection_handler,hello,[{version_exchange,_}|_]}) -> {{recv,hello}, 'TS'}; -event_name({ssh_message,encode,[Msg]}) -> {{send,element(1,Msg)}, 'TS'}; -event_name({ssh_message,decode,1, - #ssh_msg_channel_request{request_type=ReqType}}) -> {{recv,{ssh_msg_channel_request,ReqType}}, 'TS'}; -event_name({ssh_message,decode,1,Return}) -> {{recv,element(1,Return)}, 'TS'}; -event_name({ssh_transport,select_algorithm,3,{ok,Algs}}) -> {algorithms,Algs}; -event_name({ssh_transport,encrypt,[S,Data]}) -> {{{encrypt,S#ssh.encrypt},start, {S#ssh.send_sequence,size(Data)}}, 'TS'}; -event_name({ssh_transport,encrypt,2,{S,Ret}}) -> {{{encrypt,S#ssh.encrypt},stop, {S#ssh.send_sequence,size(Ret) }}, 'TS'}; -event_name({ssh_transport,decrypt,[S,Data]}) -> {{{decrypt,S#ssh.decrypt},start, {S#ssh.recv_sequence,size(Data)}}, 'TS'}; -event_name({ssh_transport,decrypt,2,{S,Ret}}) -> {{{decrypt,S#ssh.decrypt},stop, {S#ssh.recv_sequence,size(Ret) }}, 'TS'}. +pair_events(L) -> + pair_events(L, []). + +pair_events([{trace_ts,Pid,call,{M,F,Args},TS0} | L], Acc) -> + Arity = length(Args), + {ReturnValue,TS1} = find_return(Pid, {M,F,Arity}, L), + pair_events(L, [#call{mfa = {M,F,Arity}, + pid = Pid, + t_call = TS0, + t_return = TS1, + args = Args, + result = ReturnValue} | Acc]); +pair_events([_|L], Acc) -> + pair_events(L, Acc); +pair_events([], Acc) -> + lists:reverse(Acc). + + +find_return(Pid, MFA, + [{trace_ts, Pid, return_from, MFA, ReturnValue, TS}|_]) -> + {ReturnValue, TS}; +find_return(Pid, MFA, [_|L]) -> + find_return(Pid, MFA, L); +find_return(_, _, []) -> + {undefined, undefined}. +%%%---------------------------------------------------------------- now2sec({A,B,C}) -> A*1000000 + B + C/1000000. now2micro_sec({A,B,C}) -> (A*1000000 + B)*1000000 + C. now_diff({A1,B1,C1}, {A0,B0,C0}) -> {A1-A0, B1-B0, C1-C0}. - + -- cgit v1.2.3 From 2900f5787d81a5ad9f2f8ebcf0d51c7fe87eeb2c Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 15 Dec 2015 21:52:20 +0100 Subject: New structure of the report --- lib/ssh/test/ssh_benchmark_SUITE.erl | 47 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl index fe22aa9f20..0a11654116 100644 --- a/lib/ssh/test/ssh_benchmark_SUITE.erl +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -125,18 +125,25 @@ openssh_client_shell(Config) -> Algs = find_algs(List), ct:pal("Algorithms = ~p~n~nTimes = ~p",[Algs,Times]), lists:foreach( - fun({Tag0,Value,Unit}) -> - Tag = case Tag0 of - {A,B} -> lists:concat([A," ",B]); - _ when is_list(Tag0) -> lists:concat(Tag0); - _ when is_atom(Tag0) -> Tag0 - end, - DataName = - ["Erl server ",Tag,sp(algo(Tag,Algs))," [",Unit,"]"], - EventData = [{value, Value}, + fun({Tag,Value,Unit}) -> + EventData = + case Tag of + {A,B} when A==encrypt ; A==decrypt -> + [{value, Value}, {suite, ?MODULE}, - {name, lists:concat(DataName)} - ], + {name, mk_name(["Cipher ",A," ",B," [",Unit,"]"])} + ]; + kex -> + [{value, Value}, + {suite, ?MODULE}, + {name, mk_name(["Erl server kex ",Algs#alg.kex," [",Unit,"]"])} + ]; + _ when is_atom(Tag) -> + [{value, Value}, + {suite, ?MODULE}, + {name, mk_name(["Erl server ",Tag," [",Unit,"]"])} + ] + end, ct:pal("ct_event:notify ~p",[EventData]), ct_event:notify(#event{name = benchmark_data, data = EventData}) @@ -150,13 +157,13 @@ openssh_client_shell(Config) -> end. -algo(kex, #alg{kex=Alg} ) -> Alg; -algo(_, _) -> "". - -sp("") -> ""; -sp(A) -> lists:concat([" ",A]). - %%%================================================================ +mk_name(Name) -> [char(C) || C <- lists:concat(Name)]. + +char($-) -> $_; +char(C) -> C. + +%%%---------------------------------------------------------------- find_times(L) -> Xs = [accept_to_hello, kex, kex_to_auth, auth, to_prompt], [find_time(X,L) || X <- Xs] ++ @@ -239,8 +246,8 @@ find_algs(L) -> %%%---------------- crypto_algs_times_sizes(EncDecs, L) -> Raw = [{_Algorithm = case EncDec of - encrypt -> [encrypt," ",S#ssh.encrypt]; - decrypt -> [decrypt," ",S#ssh.decrypt] + encrypt -> {encrypt,S#ssh.encrypt}; + decrypt -> {decrypt,S#ssh.decrypt} end, size(Data), now2micro_sec(now_diff(T1, T0)) @@ -252,7 +259,7 @@ crypto_algs_times_sizes(EncDecs, L) -> t_return = T1} <- L, ED == EncDec ], - [{Alg, round(1024*Time/Size), "microsec/kbyte"} % Microseconds per 1k bytes. + [{Alg, round(1024*Time/Size), "microsec per kbyte"} % Microseconds per 1k bytes. || {Alg,Size,Time} <- lists:foldl(fun increment/2, [], Raw)]. increment({Alg,Sz,T}, [{Alg,SumSz,SumT}|Acc]) -> -- cgit v1.2.3 From 74faca0ac7e9e4f1d44ec43749aafe125d8a6371 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 16 Dec 2015 15:06:26 +0100 Subject: ssh: benchmark all common kex and cipher algorithms --- lib/ssh/test/ssh_benchmark_SUITE.erl | 81 ++++++++++++++++++++++++++++++++++-- lib/ssh/test/ssh_test_lib.erl | 35 +++++++++++++++- 2 files changed, 111 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl index 0a11654116..2add99de97 100644 --- a/lib/ssh/test/ssh_benchmark_SUITE.erl +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -47,6 +47,7 @@ init_per_suite(Config) -> catch crypto:stop(), try ok = crypto:start(), + report_client_algorithms(), ok = ssh:start(), {ok,TracerPid} = erlang_trace(), [{tracer_pid,TracerPid} | Config] @@ -95,6 +96,34 @@ end_per_testcase(_Func, _Conf) -> %%%================================================================ openssh_client_shell(Config) -> + CommonAlgs = ssh_test_lib:intersect_bi_dir( + ssh_test_lib:intersection(ssh:default_algorithms(), + ssh_test_lib:default_algorithms(sshc))), + KexVariants = + [ [{kex,[Kex]}] + || Kex <- proplists:get_value(kex, CommonAlgs)], + CipherVariants = + [ [{cipher,[{client2server,[Cipher]}, + {server2client,[Cipher]}]}] + || Cipher <- proplists:get_value(cipher, CommonAlgs)], + + + lists:foreach( + fun(PrefAlgs=[{kex,[Kex]}]) when Kex == 'diffie-hellman-group-exchange-sha256' -> + lists:foreach( + fun(Grp) -> + openssh_client_shell(Config, + [{preferred_algorithms, PrefAlgs}, + {dh_gex_groups, [Grp]} + ]) + end, moduli()); + (PrefAlgs) -> + openssh_client_shell(Config, + [{preferred_algorithms, PrefAlgs}]) + end, KexVariants ++ CipherVariants). + + +openssh_client_shell(Config, Options) -> SystemDir = ?config(data_dir, Config), UserDir = ?config(priv_dir, Config), KnownHosts = filename:join(UserDir, "known_hosts"), @@ -103,7 +132,8 @@ openssh_client_shell(Config) -> {ServerPid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {public_key_alg, ssh_dsa}, - {failfun, fun ssh_test_lib:failfun/2}]), + {failfun, fun ssh_test_lib:failfun/2} | + Options]), ct:sleep(500), Data = lists:duplicate(100000, $a), @@ -134,9 +164,10 @@ openssh_client_shell(Config) -> {name, mk_name(["Cipher ",A," ",B," [",Unit,"]"])} ]; kex -> + KexAlgStr = fmt_alg(Algs#alg.kex, List), [{value, Value}, {suite, ?MODULE}, - {name, mk_name(["Erl server kex ",Algs#alg.kex," [",Unit,"]"])} + {name, mk_name(["Erl server kex ",KexAlgStr," [",Unit,"]"])} ]; _ when is_atom(Tag) -> [{value, Value}, @@ -158,6 +189,20 @@ openssh_client_shell(Config) -> %%%================================================================ +fmt_alg(Alg, List) when is_atom(Alg) -> + fmt_alg(atom_to_list(Alg), List); +fmt_alg(Alg = "diffie-hellman-group-exchange-sha" ++ _, List) -> + try + integer_to_list(find_gex_size_string(List)) + of + GexSize -> lists:concat([Alg," ",GexSize]) + catch + _:_ -> Alg + end; +fmt_alg(Alg, List) -> + Alg. + +%%%---------------------------------------------------------------- mk_name(Name) -> [char(C) || C <- lists:concat(Name)]. char($-) -> $_; @@ -239,10 +284,16 @@ find([], _, Acc) -> find_algs(L) -> - {value,#call{result={ok,Algs}}} = + {value, #call{result={ok,Algs}}} = lists:keysearch({ssh_transport,select_algorithm,3}, #call.mfa, L), Algs. +find_gex_size_string(L) -> + %% server + {value, #call{result={ok,{Size, _}}}} = + lists:keysearch({public_key,dh_gex_group,4}, #call.mfa, L), + Size. + %%%---------------- crypto_algs_times_sizes(EncDecs, L) -> Raw = [{_Algorithm = case EncDec of @@ -290,7 +341,8 @@ erlang_trace() -> {ssh_message,decode,1}, {ssh_transport,select_algorithm,3}, {ssh_transport,encrypt,2}, - {ssh_transport,decrypt,2} + {ssh_transport,decrypt,2}, + {public_key,dh_gex_group,4} % To find dh_gex group size ]], {ok, TracerPid}. @@ -345,9 +397,30 @@ find_return(_, _, []) -> {undefined, undefined}. %%%---------------------------------------------------------------- +report_client_algorithms() -> + try + ssh_test_lib:extract_algos( ssh_test_lib:default_algorithms(sshc) ) + of + ClientAlgs -> + ct:pal("The client supports:~n~p",[ClientAlgs]) + catch + Cls:Err -> + ct:pal("Testing client about algorithms failed:~n~p ~p",[Cls,Err]) + end. + +%%%---------------------------------------------------------------- + + now2sec({A,B,C}) -> A*1000000 + B + C/1000000. now2micro_sec({A,B,C}) -> (A*1000000 + B)*1000000 + C. now_diff({A1,B1,C1}, {A0,B0,C0}) -> {A1-A0, B1-B0, C1-C0}. +%%%================================================================ +moduli() -> + [{1023, 5, 16#CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D182EB7}, + {2047, 5, 16#F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE5E381EF}, + {4095, 2, 16#C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BA7321EB}, + {6143, 5, 16#FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C3BEB637}, + {8191, 2, 16#DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE37347869A3}]. diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index ed76f4f795..2db55b97b4 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -541,7 +541,6 @@ default_algorithms(sshc, DaemonOptions) -> ct:fail("No server respons 2") end. - run_fake_ssh({ok,InitialState}) -> KexInitPattern = #ssh_msg_kexinit{ @@ -583,6 +582,40 @@ run_fake_ssh({ok,InitialState}) -> {server2client, to_atoms(CompS2C)}]}]. +%%%---------------------------------------------------------------- +extract_algos(Spec) -> + [{Tag,get_atoms(List)} || {Tag,List} <- Spec]. + +get_atoms(L) -> + lists:usort( + [ A || X <- L, + A <- case X of + {_,L1} when is_list(L1) -> L1; + Y when is_atom(Y) -> [Y] + end]). + + +intersection(AlgoSpec1, AlgoSpec2) -> intersect(sort_spec(AlgoSpec1), sort_spec(AlgoSpec2)). + +intersect([{Tag,S1}|Ss1], [{Tag,S2}|Ss2]) -> + [{Tag,intersect(S1,S2)} | intersect(Ss1,Ss2)]; +intersect(L1=[A1|_], L2=[A2|_]) when is_atom(A1),is_atom(A2) -> + Diff = L1 -- L2, + L1 -- Diff; +intersect(_, _) -> + []. + +intersect_bi_dir([{Tag,[{client2server,L1},{server2client,L2}]}|T]) -> + [{Tag,intersect(L1,L2)} | intersect_bi_dir(T)]; +intersect_bi_dir([H={_,[A|_]}|T]) when is_atom(A) -> + [H | intersect_bi_dir(T)]; +intersect_bi_dir([]) -> + []. + + +sort_spec(L = [{_,_}|_] ) -> [{Tag,sort_spec(Es)} || {Tag,Es} <- L]; +sort_spec(L) -> lists:usort(L). + %%-------------------------------------------------------------------- sshc(Tag) -> to_atoms( -- cgit v1.2.3 From 0f41fa2ed0f9ac4fea2756fd29361f5e160bd3dc Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 22 Dec 2015 09:14:21 +0100 Subject: ssh: fix error (wrong suite) in test/ssh.spec --- lib/ssh/test/ssh.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec index a3296d97a1..271a5ecbaf 100644 --- a/lib/ssh/test/ssh.spec +++ b/lib/ssh/test/ssh.spec @@ -1,6 +1,6 @@ {suites,"../ssh_test",all}. {skip_cases, "../ssh_test", - ssl_benchmark_SUITE, [openssh_shell,erl_shell], + ssh_benchmark_SUITE, [openssh_shell,erl_shell], "Benchmarks run separately"}. {skip_cases,"../ssh_test",ssh_ssh_SUITE, [ssh], -- cgit v1.2.3 From 537ba0cfc4cb9640f912d382a4c7730736696376 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 22 Dec 2015 10:00:10 +0100 Subject: ssh: clean test specs --- lib/ssh/test/ssh.spec | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec index 271a5ecbaf..0076fc275e 100644 --- a/lib/ssh/test/ssh.spec +++ b/lib/ssh/test/ssh.spec @@ -1,10 +1,6 @@ {suites,"../ssh_test",all}. -{skip_cases, "../ssh_test", - ssh_benchmark_SUITE, [openssh_shell,erl_shell], - "Benchmarks run separately"}. -{skip_cases,"../ssh_test",ssh_ssh_SUITE, - [ssh], - "Current implementation is timingdependent and\nhence will succeed/fail on a whim"}. -{skip_cases,"../ssh_test",ssh_ssh_SUITE, - [ssh_compressed], - "Current implementation is timingdependent hence will succeed/fail on a whim"}. + +{skip_suites, "../ssh_test", [ssh_benchmark_SUITE], + "Benchmarks run separately"}. + + -- cgit v1.2.3 From 7c72e25926e153811ff099057bea649afa0be376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 17 Dec 2015 14:50:43 +0100 Subject: beam_bool: Fix unsafe optimization beam_bool would make the following code unsafe (which would be reported by beam_validator): scotland(Echo) -> found(case Echo of Echo when true; Echo, Echo, Echo -> Echo; echo -> [] end, Echo = placed). found(_, _) -> million. Basically, beam_bool would see that the 'case' would always return the value of Echo. Thus: scotland(Echo) -> found(Echo, Echo = placed). The only problem is that beam_bool would also remove a 'move' instruction that would save Echo to the stack. Here is the assembly code for part of the function: {allocate_zero,1,1}. {move,{x,0},{y,0}}. %% Save Echo on stack. {bif,'=:=',{f,7},[{x,0},{atom,true}],{x,1}}. {bif,'=:=',{f,7},[{x,0},{atom,true}],{x,2}}. {bif,'=:=',{f,7},[{x,0},{atom,true}],{x,3}}. {bif,'and',{f,7},[{x,2},{x,3}],{x,2}}. {bif,'and',{f,7},[{x,1},{x,2}],{x,1}}. {jump,{f,8}}. {label,7}. {move,{atom,false},{x,1}}. {label,8}. {bif,'or',{f,6},[{atom,true},{x,1}],{x,1}}. {test,is_eq_exact,{f,6},[{x,1},{atom,true}]}. %% Jump never taken. {jump,{f,5}}. {label,6}. {test,is_eq_exact,{f,9},[{x,0},{atom,echo}]}. {move,nil,{x,0}}. {jump,{f,5}}. {label,9}. {test_heap,3,0}. {put_tuple,2,{x,0}}. {put,{atom,case_clause}}. {put,{y,0}}. {line,[{location,"t.erl",5}]}. {call_ext,1,{extfunc,erlang,error,1}}. {jump,{f,5}}. {label,5}. {test,is_eq_exact,{f,12},[{atom,placed},{y,0}]}. beam_bool would see that the is_eq_exact test at label 8 would always succeed. It could therefore remove most of the code before the jump to label 5. Unfortunately it also removed the essential move of Echo to the stack: {allocate_zero,1,1}. %% Instruction incorrectly removed: {move,{x,0},{y,0}}. {jump,{f,5}}. {label,5}. {test,is_eq_exact,{f,12},[{atom,placed},{y,0}]}. The root cause of the problem is that the 'move' instruction is included in the block of 'bif' instructions before label 8. Normally the 'move' instruction would not have been discarded, but because the left operand to the 'or' BIF is 'true', the entire block with 'bif' instructions are dropped. As far as I can see, there is no gain by including 'move' instructions in the first place. There is no way that better code will be produced. In fact, the entire optimization can be given up if 'move' instructions are found in the block. Thus we can fix this bug by never including any 'move' instructions in the block of 'bif' instructions. We can also remove all the code that deals with 'move' instructions within blocks. Reported-by: Thomas Arts --- lib/compiler/src/beam_bool.erl | 50 ++------------------------------------- lib/compiler/test/guard_SUITE.erl | 27 +++++++++++++++++++-- 2 files changed, 27 insertions(+), 50 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl index 14b6381230..d14be83496 100644 --- a/lib/compiler/src/beam_bool.erl +++ b/lib/compiler/src/beam_bool.erl @@ -142,11 +142,6 @@ bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) -> throw:not_boolean_expr -> failed; - %% The block contains a 'move' instruction that could - %% not be handled. - throw:move -> - failed; - %% The optimization is not safe. (A register %% used by the instructions following the %% optimized code is either not assigned a @@ -215,37 +210,14 @@ ensure_opt_safe(Bl, NewCode, OldIs, Fail, PrecedingCode, St) -> false -> throw(all_registers_not_killed); true -> ok end, - Same = assigned_same_value(Bl, NewCode), MustBeUnused = ordsets:subtract(ordsets:union(NotSet, NewDst), - ordsets:union(MustBeKilled, Same)), + MustBeKilled), case none_used(MustBeUnused, OldIs, Fail, St) of false -> throw(registers_used); true -> ok end, ok. -%% assigned_same_value(OldCode, NewCodeReversed) -> [DestinationRegs] -%% Return an ordset with a list of all y registers that are always -%% assigned the same value in the old and new code. Currently, we -%% are very conservative in that we only consider identical move -%% instructions in the same order. -%% -assigned_same_value(Old, New) -> - case reverse(New) of - [{block,Bl}|_] -> - assigned_same_value(Old, Bl, []); - _ -> - ordsets:new() - end. - -assigned_same_value([{set,[{y,_}=D],[S],move}|T1], - [{set,[{y,_}=D],[S],move}|T2], Acc) -> - assigned_same_value(T1, T2, [D|Acc]); -assigned_same_value(_, _, Acc) -> - ordsets:from_list(Acc). - -update_fail_label([{set,_,_,move}=I|Is], Fail, Acc) -> - update_fail_label(Is, Fail, [I|Acc]); update_fail_label([{set,Ds,As,{bif,N,{f,_}}}|Is], Fail, Acc) -> update_fail_label(Is, Fail, [{set,Ds,As,{bif,N,{f,Fail}}}|Acc]); update_fail_label([{set,Ds,As,{alloc,Regs,{gc_bif,N,{f,_}}}}|Is], Fail, Acc) -> @@ -314,8 +286,6 @@ split_block_1(Is, Fail, ProhibitFailLabel) -> end end. -split_block_2([{set,_,_,move}=I|Is], Fail, Acc) -> - split_block_2(Is, Fail, [I|Acc]); split_block_2([{set,[_],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) -> split_block_2(Is, Fail, [I|Acc]); split_block_2([{set,[_],_,{alloc,_,{gc_bif,_,{f,Fail}}}}=I|Is], Fail, Acc) -> @@ -343,8 +313,6 @@ dst_regs([{set,[D],_,{bif,_,{f,_}}}|Is], Acc) -> dst_regs(Is, [D|Acc]); dst_regs([{set,[D],_,{alloc,_,{gc_bif,_,{f,_}}}}|Is], Acc) -> dst_regs(Is, [D|Acc]); -dst_regs([{set,[D],_,move}|Is], Acc) -> - dst_regs(Is, [D|Acc]); dst_regs([_|Is], Acc) -> dst_regs(Is, Acc); dst_regs([], Acc) -> ordsets:from_list(Acc). @@ -411,13 +379,6 @@ bopt_tree([{protected,[Dst],Code,_}|Is], Forest0, Pre) -> _Res -> throw(not_boolean_expr) end; -bopt_tree([{set,[Dst],[Src],move}=Move|Is], Forest, Pre) -> - case {Src,Dst} of - {{tmp,_},_} -> throw(move); - {_,{tmp,_}} -> throw(move); - _ -> ok - end, - bopt_tree(Is, Forest, [Move|Pre]); bopt_tree([{set,[Dst],As,{bif,N,_}}=Bif|Is], Forest0, Pre) -> Ar = length(As), case safe_bool_op(N, Ar) of @@ -589,10 +550,6 @@ free_variables(Is) -> E = gb_sets:empty(), free_vars_1(Is, E, E, E). -free_vars_1([{set,Ds,As,move}|Is], F0, N0, A) -> - F = gb_sets:union(F0, gb_sets:difference(var_list(As), N0)), - N = gb_sets:union(N0, var_list(Ds)), - free_vars_1(Is, F, N, A); free_vars_1([{set,Ds,As,{bif,_,_}}|Is], F0, N0, A) -> F = gb_sets:union(F0, gb_sets:difference(var_list(As), N0)), N = gb_sets:union(N0, var_list(Ds)), @@ -632,8 +589,6 @@ free_vars_regs(X) -> [{x,X-1}|free_vars_regs(X-1)]. rename_regs(Is, Regs) -> rename_regs(Is, Regs, []). -rename_regs([{set,_,_,move}=I|Is], Regs, Acc) -> - rename_regs(Is, Regs, [I|Acc]); rename_regs([{set,[Dst0],Ss0,{alloc,_,Info}}|Is], Regs0, Acc) -> Live = live_regs(Regs0), Ss = rename_sources(Ss0, Regs0), @@ -737,8 +692,7 @@ ssa_assign({x,_}=R, #ssa{sub=Sub0}=Ssa0) -> Sub1 = gb_trees:update(R, NewReg, Sub0), Sub = gb_trees:insert(NewReg, NewReg, Sub1), Ssa#ssa{sub=Sub} - end; -ssa_assign(_, Ssa) -> Ssa. + end. ssa_sub_list(List, Sub) -> [ssa_sub(E, Sub) || E <- List]. diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl index b3b67155b3..3f073d79cb 100644 --- a/lib/compiler/test/guard_SUITE.erl +++ b/lib/compiler/test/guard_SUITE.erl @@ -34,7 +34,7 @@ tricky/1,rel_ops/1,rel_op_combinations/1,literal_type_tests/1, basic_andalso_orelse/1,traverse_dcd/1, check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1, - bad_constants/1,bad_guards/1]). + bad_constants/1,bad_guards/1,scotland/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -52,7 +52,7 @@ groups() -> rel_ops,rel_op_combinations, literal_type_tests,basic_andalso_orelse,traverse_dcd, check_qlc_hrl,andalso_semi,t_tuple_size,binary_part, - bad_constants,bad_guards]}]. + bad_constants,bad_guards,scotland]}]. init_per_suite(Config) -> Config. @@ -1831,6 +1831,29 @@ bad_guards_2(M, [_]) when M#{a := 0, b => 0}, map_size(M) -> bad_guards_3(M, [_]) when is_map(M) andalso M#{a := 0, b => 0}, length(M) -> ok. +%% beam_bool would remove the initialization of {y,0}. +%% (Thanks to Thomas Arts and QuickCheck.) + +scotland(_Config) -> + million = do_scotland(placed), + {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(false)), + {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(true)), + {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(echo)), + ok. + +do_scotland(Echo) -> + found(case Echo of + Echo when true; Echo, Echo, Echo -> + Echo; + echo -> + [] + end, + Echo = placed). + +found(_, _) -> million. + + + %% Call this function to turn off constant propagation. id(I) -> I. -- cgit v1.2.3 From 04a9f3d11d15035c583dbf3ff3009f186611faac Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 8 Jan 2016 13:00:26 +0100 Subject: ssh: testcase for abnormal keyboard-interactive authentication --- lib/ssh/test/ssh_protocol_SUITE.erl | 81 ++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 5af60adfae..98a196d705 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -48,6 +48,7 @@ all() -> [{group,tool_tests}, {group,kex}, {group,service_requests}, + {group,authentication}, {group,packet_size_error}, {group,field_size_error} ]. @@ -78,7 +79,9 @@ groups() -> bad_very_long_service_name, empty_service_name, bad_service_name_then_correct - ]} + ]}, + {authentication, [], [client_handles_keyboard_interactive_0_pwds + ]} ]. @@ -516,6 +519,82 @@ bad_service_name_length(Config, LengthExcess) -> receive_msg} ], InitialState). +%%%-------------------------------------------------------------------- +%%% This is due to a fault report (OTP-13255) with OpenSSH-6.6.1 +client_handles_keyboard_interactive_0_pwds(Config) -> + {User,_Pwd} = server_user_password(Config), + + %% Create a listening socket as server socket: + {ok,InitialState} = ssh_trpt_test_lib:exec(listen), + HostPort = ssh_trpt_test_lib:server_host_port(InitialState), + + %% Start a process handling one connection on the server side: + spawn_link( + fun() -> + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_messages]}, + {accept, [{system_dir, system_dir(Config)}, + {user_dir, user_dir(Config)}]}, + receive_hello, + {send, hello}, + + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + + {match, #ssh_msg_kexdh_init{_='_'}, receive_msg}, + {send, ssh_msg_kexdh_reply}, + + {send, #ssh_msg_newkeys{}}, + {match, #ssh_msg_newkeys{_='_'}, receive_msg}, + + {match, #ssh_msg_service_request{name="ssh-userauth"}, receive_msg}, + {send, #ssh_msg_service_accept{name="ssh-userauth"}}, + + {match, #ssh_msg_userauth_request{service="ssh-connection", + method="none", + user=User, + _='_'}, receive_msg}, + {send, #ssh_msg_userauth_failure{authentications = "keyboard-interactive", + partial_success = false}}, + + {match, #ssh_msg_userauth_request{service="ssh-connection", + method="keyboard-interactive", + user=User, + _='_'}, receive_msg}, + {send, #ssh_msg_userauth_info_request{name = "", + instruction = "", + language_tag = "", + num_prompts = 1, + data = <<0,0,0,10,80,97,115,115,119,111,114,100,58,32,0>> + }}, + {match, #ssh_msg_userauth_info_response{num_responses = 1, + _='_'}, receive_msg}, + + %% the next is strange, but openssh 6.6.1 does this and this is what this testcase is about + {send, #ssh_msg_userauth_info_request{name = "", + instruction = "", + language_tag = "", + num_prompts = 0, + data = <<>> + }}, + {match, #ssh_msg_userauth_info_response{num_responses = 0, + data = <<>>, + _='_'}, receive_msg}, + %% Here we know that the tested fault is fixed + {send, #ssh_msg_userauth_success{}}, + close_socket, + print_state + ], + InitialState) + end), + + %% and finally connect to it with a regular Erlang SSH client: + {ok,_} = std_connect(HostPort, Config, + [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}] + ). + + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ -- cgit v1.2.3 From ed7d29ca3b6e8a165bdeb182799cbba5e204326f Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 7 Jan 2016 15:21:45 +0100 Subject: ssh: handle secondary ssh_msg_userauth_info_request message --- lib/ssh/src/ssh_auth.erl | 2 +- lib/ssh/src/ssh_connection_handler.erl | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index fdbb5c152a..b71bed033a 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -477,7 +477,7 @@ keyboard_interact_get_responses(_, undefined, Password, _, _, _, _, _, 1) when Password =/= undefined -> [Password]; %% Password auth implemented with keyboard-interaction and passwd is known keyboard_interact_get_responses(_, _, _, _, _, _, _, _, 0) -> - [""]; + []; keyboard_interact_get_responses(false, undefined, undefined, _, _, _, [Prompt|_], Opts, _) -> ssh_no_io:read_line(Prompt, Opts); %% Throws error as keyboard interaction is not allowed keyboard_interact_get_responses(true, undefined, _,IoCb, Name, Instr, PromptInfos, Opts, _) -> diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index f082db136c..ce1931e4f4 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -648,10 +648,12 @@ userauth_keyboard_interactive(Msg = #ssh_msg_userauth_failure{}, userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_failure{}, #state{ssh_params = #ssh{role = client}} = State) -> userauth(Msg, State); - userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_success{}, #state{ssh_params = #ssh{role = client}} = State) -> - userauth(Msg, State). + userauth(Msg, State); +userauth_keyboard_interactive_info_response(Msg=#ssh_msg_userauth_info_request{}, + #state{ssh_params = #ssh{role = client}} = State) -> + userauth_keyboard_interactive(Msg, State). %%-------------------------------------------------------------------- -spec connected({#ssh_msg_kexinit{}, binary()}, %%| %% #ssh_msg_kexdh_init{}, -- cgit v1.2.3 From 9394c572a28d08f3c564d6f388152c9c41968565 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 8 Jan 2016 10:42:45 +0100 Subject: ssh: update vsn.mk to 4.2.1 --- lib/ssh/vsn.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 25b19133b1..55d12abffe 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.2 +SSH_VSN = 4.2.1 APP_VSN = "ssh-$(SSH_VSN)" -- cgit v1.2.3 From 9498322e15bf1cc049996813f3422462fd402502 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 8 Jan 2016 13:09:36 +0100 Subject: Update release notes --- lib/ssh/doc/src/notes.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'lib') diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 8fb689fdd5..75e1615c09 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,24 @@ notes.xml +
Ssh 4.2.1 + +
Fixed Bugs and Malfunctions + + +

+ The authentication method 'keyboard-interactive' failed + in the Erlang client when the server after successful + authentication continued by asking for zero more + passwords.

+

+ Own Id: OTP-13225

+
+
+
+ +
+
Ssh 4.2
Fixed Bugs and Malfunctions -- cgit v1.2.3 From 1117dd3651be3cf763abf6fedcd4e06a6444fa04 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 8 Jan 2016 15:22:52 +0100 Subject: erts: Allow -fvisibility=hidden for NIFs and drivers as is strongly recommended by gcc man page. We use __attribute__ ((visibility("default"))) to make sure the init functions are properly exported. --- lib/crypto/c_src/crypto_callback.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index aab43232c9..af9545bd63 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -43,6 +43,10 @@ #ifdef __WIN32__ # define DLLEXPORT __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define DLLEXPORT __attribute__ ((visibility("default"))) +#elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# define DLLEXPORT __global #else # define DLLEXPORT #endif -- cgit v1.2.3 From f0bc967c38d8859ff794e93082e9d2fb495f34d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 7 Jan 2016 15:25:26 +0100 Subject: Eliminate crash in v3_codegen The following code would crash v3_codegen: order(From) -> catch if From#{[] => sufficient} -> saint end. Before explaining the crash, first some background on the stack frame and the Y registers. Certain instructions, most notably the 'call' instructions, clobber all X registers. Before any such instruction, all X registers that have values that will be used after the call must be saved to Y registers (i.e. to the stack frame). adjust_stack/4 will be called when X registers must be saved. There is also another situation when X registers must be saved, namely within a 'catch' if we are about to execute any instruction that may cause an exception. Examples of such instructions are some guard BIFs (such as length/1) and construction of binaries or maps. Within a 'catch', X registers must be be saved because if an exception is thrown and catched all X registers will be destroyed. The same adjust_stack/4 function will be called for those instructions, but only if they occur within a 'catch'. There is actually one more complication. If there is code in a guard within a catch, the X registers should not be saved, because the code in a guard never clobbers any X registers that were alive before the guard code was entered. v3_codegen is written with the implicit assumption that code in guards never cause anything to be saved to Y registers. The code for building maps and binaries would incorrectly save X registers within a guard inside a 'catch'. For construction of binaries, that would mean that a useless but harmelss 'move' instruction was generated. But for construction of maps, the saving of the Y register would not be harmless. There would be a crash when attempting to merge #sr{} records. #sr{} records keeps track of the contents of X and Y registers. When two separate code paths are joined (e.g. at the end of 'case' statement), the register descriptors must be reconciled. Basically, the register descriptors for both paths must be identical. The #sr{} record for one path must not claim that {y,0} contains a certain value, while another path claims that {y,0} is dead. Thus, the crash occurs in sr_merge/2 when failing to reconcile the Y registers. To fix this bug this bug we will introduce a new function called maybe_adjust_stack/5. It will save X registers on the stack only if the code is inside a catch but not inside a guard. We will change all existing code to use this new function when appropriate. Reported-by: Thomas Arts --- lib/compiler/src/v3_codegen.erl | 58 +++++++++++++++++++-------------------- lib/compiler/test/guard_SUITE.erl | 56 +++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index 34c67b16ca..2a89305f4d 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -1327,12 +1327,13 @@ bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) -> %% that we save any variable that will be live after this BIF call. MayFail = not erl_bifs:is_safe(erlang, Bif, length(As)), - {Sis,Int0} = case St0#cg.in_catch andalso - St0#cg.bfail =:= 0 andalso - MayFail of - true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb); - false -> {[],Bef} - end, + {Sis,Int0} = + case MayFail of + true -> + maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0); + false -> + {[],Bef} + end, Int1 = clear_dead(Int0, Le#l.i, Vdb), Reg = put_reg(V, Int1#sr.reg), Int = Int1#sr{reg=Reg}, @@ -1363,11 +1364,7 @@ gc_bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) -> %% Currently, we are somewhat pessimistic in %% that we save any variable that will be live after this BIF call. - {Sis,Int0} = - case St0#cg.in_catch andalso St0#cg.bfail =:= 0 of - true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb); - false -> {[],Bef} - end, + {Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0), Int1 = clear_dead(Int0, Le#l.i, Vdb), Reg = put_reg(V, Int1#sr.reg), @@ -1512,8 +1509,7 @@ set_cg([{var,R}], {cons,Es}, Le, Vdb, Bef, St) -> Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)}, Ret = fetch_reg(R, Int1#sr.reg), {[{put_list,S1,S2,Ret}], Int1, St}; -set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, - #cg{in_catch=InCatch, bfail=Bfail}=St) -> +set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, #cg{bfail=Bfail}=St) -> %% At run-time, binaries are constructed in three stages: %% 1) First the size of the binary is calculated. %% 2) Then the binary is allocated. @@ -1532,11 +1528,7 @@ set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, %% First generate the code that constructs each field. Fail = {f,Bfail}, PutCode = cg_bin_put(Segs, Fail, Bef), - {Sis,Int1} = - case InCatch of - true -> adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb); - false -> {[],Int0} - end, + {Sis,Int1} = maybe_adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb, St), MaxRegs = max_reg(Bef#sr.reg), Aft = clear_dead(Int1, Le#l.i, Vdb), @@ -1545,14 +1537,11 @@ set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, {Sis++Code,Aft,St}; % Map single variable key set_cg([{var,R}], {map,Op,Map,[{map_pair,{var,_}=K,V}]}, Le, Vdb, Bef, - #cg{in_catch=InCatch,bfail=Bfail}=St) -> + #cg{bfail=Bfail}=St) -> Fail = {f,Bfail}, - {Sis,Int0} = - case InCatch of - true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb); - false -> {[],Bef} - end, + {Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St), + SrcReg = cg_reg_arg(Map,Int0), Line = line(Le#l.a), @@ -1573,17 +1562,13 @@ set_cg([{var,R}], {map,Op,Map,[{map_pair,{var,_}=K,V}]}, Le, Vdb, Bef, % Map (possibly) multiple literal keys set_cg([{var,R}], {map,Op,Map,Es}, Le, Vdb, Bef, - #cg{in_catch=InCatch,bfail=Bfail}=St) -> + #cg{bfail=Bfail}=St) -> %% assert key literals [] = [Var||{map_pair,{var,_}=Var,_} <- Es], Fail = {f,Bfail}, - {Sis,Int0} = - case InCatch of - true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb); - false -> {[],Bef} - end, + {Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St), SrcReg = cg_reg_arg(Map,Int0), Line = line(Le#l.a), @@ -2038,6 +2023,19 @@ trim_free([R|Rs0]) -> end; trim_free([]) -> []. +%% maybe_adjust_stack(Bef, FirstBefore, LastFrom, Vdb, St) -> {[Ainstr],Aft}. +%% Adjust the stack, but only if the code is inside a catch and not +%% inside a guard. Use this funtion before instructions that may +%% cause an exception. + +maybe_adjust_stack(Bef, Fb, Lf, Vdb, St) -> + case St of + #cg{in_catch=true,bfail=0} -> + adjust_stack(Bef, Fb, Lf, Vdb); + #cg{} -> + {[],Bef} + end. + %% adjust_stack(Bef, FirstBefore, LastFrom, Vdb) -> {[Ainstr],Aft}. %% Do complete stack adjustment by compressing stack and adding %% variables to be saved. Try to optimise ordering on stack by diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl index 3f073d79cb..47eb1ba78b 100644 --- a/lib/compiler/test/guard_SUITE.erl +++ b/lib/compiler/test/guard_SUITE.erl @@ -34,7 +34,8 @@ tricky/1,rel_ops/1,rel_op_combinations/1,literal_type_tests/1, basic_andalso_orelse/1,traverse_dcd/1, check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1, - bad_constants/1,bad_guards/1,scotland/1]). + bad_constants/1,bad_guards/1,scotland/1, + guard_in_catch/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -52,7 +53,7 @@ groups() -> rel_ops,rel_op_combinations, literal_type_tests,basic_andalso_orelse,traverse_dcd, check_qlc_hrl,andalso_semi,t_tuple_size,binary_part, - bad_constants,bad_guards,scotland]}]. + bad_constants,bad_guards,scotland,guard_in_catch]}]. init_per_suite(Config) -> Config. @@ -1852,6 +1853,57 @@ do_scotland(Echo) -> found(_, _) -> million. +%% Building maps in a guard in a 'catch' would crash v3_codegen. + +guard_in_catch(_Config) -> + {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{}), + {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{a=>b}), + {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(atom), + + {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{}), + {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{a=>b}), + {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(atom), + + {'EXIT',{if_clause,_}} = (catch do_guard_in_catch_map_3()), + + {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(42), + {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(<<1,2,3>>), + {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(atom), + {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(#{}), + + ok. + +do_guard_in_catch_map_1(From) -> + catch + if + From#{[] => sufficient} -> + saint + end. + +do_guard_in_catch_map_2(From) -> + catch + if + From#{From => sufficient} -> + saint + end. + +do_guard_in_catch_map_3() -> + try + if [] -> solo end + catch + Friendly when Friendly#{0 => []} -> minutes + after + membership + end. + +do_guard_in_catch_bin(From) -> + %% Would not crash v3_codegen, but there would be an unnecessary + %% 'move' to a Y register. + catch + if + <> -> + saint + end. %% Call this function to turn off constant propagation. -- cgit v1.2.3 From ff2ef4278045c985738e3ddb4af6127c7db933e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 11 Jan 2016 15:58:57 +0100 Subject: Fix crash when attempting to update a fun as if it were a map The following example would cause an internal consistency failure in the compiler: f() -> ok. update() -> (fun f/0)#{u => 42}. The reason is that internally, v3_core will (incorrectly) rewrite update/0 to code similar to this: update() -> if is_map(fun f/0) -> maps:update(u, 42, fun f/0) end. Since funs are not allowed to be created in guards, incorrect and unsafe code would be generated. It is easy to fix the bug. There already is a is_valid_map_src/1 function in v3_core that tests whether the argument for the map update operation can possibly be a valid map. A fun is represented as a variable with a special name in Core Erlang, so it would not be recognized as unsafe. All we'll need to do to fix the bug is to look closer at variables to ensure they don't represent funs. That will ensure that the code is rewritten in the correct way: update() -> error({badmap,fun f/0}) end. Reported-by: Thomas Arts --- lib/compiler/src/v3_core.erl | 2 +- lib/compiler/test/map_SUITE.erl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 0941ad5dd5..7d93e2ae16 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -804,7 +804,7 @@ map_op(map_field_assoc) -> #c_literal{val=assoc}; map_op(map_field_exact) -> #c_literal{val=exact}. is_valid_map_src(#c_literal{val = M}) when is_map(M) -> true; -is_valid_map_src(#c_var{}) -> true; +is_valid_map_src(#c_var{}=Var) -> not cerl:is_c_fname(Var); is_valid_map_src(_) -> false. %% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}. diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index 411b15eebe..cff3b5deb4 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -883,6 +883,9 @@ t_update_map_expressions(Config) when is_list(Config) -> %% Error cases. {'EXIT',{{badmap,<<>>},_}} = (catch (id(<<>>))#{ a := 42, b => 2 }), {'EXIT',{{badmap,[]},_}} = (catch (id([]))#{ a := 42, b => 2 }), + {'EXIT',{{badmap,_},_}} = + (catch (fun t_update_map_expressions/1)#{u => 42}), + ok. -- cgit v1.2.3 From cfb668cc624a1fe9a2411a41a8fe747e327d4d02 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 11 Jan 2016 10:30:27 +0100 Subject: stdlib: fix erl_eval not using non-local function handler See also ERL-32 at bugs.erlang.org. Thanks to Ben Paxton. --- lib/stdlib/src/erl_eval.erl | 31 ++++++++++++++++--------------- lib/stdlib/test/erl_eval_SUITE.erl | 13 +++++++++++-- 2 files changed, 27 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 568eb1c852..40a34aa30f 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -415,7 +415,7 @@ expr({call,_,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs) -> {As,Bs} = expr_list(As0, Bs0, Lf, Ef), bif(Func, As, Bs, Ef, RBs); false -> - local_func(Func, As0, Bs0, Lf, RBs) + local_func(Func, As0, Bs0, Lf, Ef, RBs) end; expr({call,_,Func0,As0}, Bs0, Lf, Ef, RBs) -> % function or {Mod,Fun} {value,Func,Bs1} = expr(Func0, Bs0, Lf, Ef, none), @@ -542,33 +542,34 @@ unhide_calls([E | Es], MaxLine, D) -> unhide_calls(E, _MaxLine, _D) -> E. -%% local_func(Function, Arguments, Bindings, LocalFuncHandler, RBs) -> +%% local_func(Function, Arguments, Bindings, LocalFuncHandler, +%% ExternalFuncHandler, RBs) -> %% {value,Value,Bindings} | Value when %% LocalFuncHandler = {value,F} | {value,F,Eas} | %% {eval,F} | {eval,F,Eas} | none. -local_func(Func, As0, Bs0, {value,F}, value) -> - {As1,_Bs1} = expr_list(As0, Bs0, {value,F}), +local_func(Func, As0, Bs0, {value,F}, Ef, value) -> + {As1,_Bs1} = expr_list(As0, Bs0, {value,F}, Ef), %% Make tail recursive calls when possible. F(Func, As1); -local_func(Func, As0, Bs0, {value,F}, RBs) -> - {As1,Bs1} = expr_list(As0, Bs0, {value,F}), +local_func(Func, As0, Bs0, {value,F}, Ef, RBs) -> + {As1,Bs1} = expr_list(As0, Bs0, {value,F}, Ef), ret_expr(F(Func, As1), Bs1, RBs); -local_func(Func, As0, Bs0, {value,F,Eas}, RBs) -> +local_func(Func, As0, Bs0, {value,F,Eas}, Ef, RBs) -> Fun = fun(Name, Args) -> apply(F, [Name,Args|Eas]) end, - local_func(Func, As0, Bs0, {value, Fun}, RBs); -local_func(Func, As, Bs, {eval,F}, RBs) -> + local_func(Func, As0, Bs0, {value, Fun}, Ef, RBs); +local_func(Func, As, Bs, {eval,F}, _Ef, RBs) -> local_func2(F(Func, As, Bs), RBs); -local_func(Func, As, Bs, {eval,F,Eas}, RBs) -> +local_func(Func, As, Bs, {eval,F,Eas}, _Ef, RBs) -> local_func2(apply(F, [Func,As,Bs|Eas]), RBs); %% These two clauses are for backwards compatibility. -local_func(Func, As0, Bs0, {M,F}, RBs) -> - {As1,Bs1} = expr_list(As0, Bs0, {M,F}), +local_func(Func, As0, Bs0, {M,F}, Ef, RBs) -> + {As1,Bs1} = expr_list(As0, Bs0, {M,F}, Ef), ret_expr(M:F(Func,As1), Bs1, RBs); -local_func(Func, As, _Bs, {M,F,Eas}, RBs) -> +local_func(Func, As, _Bs, {M,F,Eas}, _Ef, RBs) -> local_func2(apply(M, F, [Func,As|Eas]), RBs); %% Default unknown function handler to undefined function. -local_func(Func, As0, _Bs0, none, _RBs) -> +local_func(Func, As0, _Bs0, none, _Ef, _RBs) -> erlang:raise(error, undef, [{erl_eval,Func,length(As0)}|stacktrace()]). local_func2({value,V,Bs}, RBs) -> diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index 50fc62a00e..c21c4e61ee 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ otp_7550/1, otp_8133/1, otp_10622/1, + otp_13228/1, funs/1, try_catch/1, eval_expr_5/1, @@ -83,7 +84,8 @@ all() -> pattern_expr, match_bin, guard_3, guard_4, guard_5, lc, simple_cases, unary_plus, apply_atom, otp_5269, otp_6539, otp_6543, otp_6787, otp_6977, otp_7550, - otp_8133, otp_10622, funs, try_catch, eval_expr_5, zero_width, + otp_8133, otp_10622, otp_13228, + funs, try_catch, eval_expr_5, zero_width, eep37, eep43]. groups() -> @@ -1042,6 +1044,13 @@ otp_10622(Config) when is_list(Config) -> ok. +otp_13228(doc) -> + ["OTP-13228. ERL-32: non-local function handler bug."]; +otp_13228(_Config) -> + LFH = {value, fun(foo, [io_fwrite]) -> worked end}, + EFH = {value, fun({io, fwrite}, [atom]) -> io_fwrite end}, + {value, worked, []} = parse_and_run("foo(io:fwrite(atom)).", LFH, EFH). + funs(doc) -> ["Simple cases, just to cover some code."]; funs(suite) -> -- cgit v1.2.3 From 82d5a5cecd0a3a5f4b9446bf0703873a812c6ede Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 11 Jan 2016 13:55:31 +0100 Subject: stdlib: Fix linter crash due to missing -module declaration The Erlang Code Linter no longer crashes if there is a -deprecated() attribute but no -module() declaration. See also ERL-62 at bugs.erlang.org. --- lib/stdlib/src/erl_lint.erl | 6 +++--- lib/stdlib/test/erl_lint_SUITE.erl | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 5678e7eebe..e940ad6956 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -100,7 +100,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> %% 'called' and 'exports' contain {Line, {Function, Arity}}, %% the other function collections contain {Function, Arity}. -record(lint, {state=start :: 'start' | 'attribute' | 'function', - module=[], %Module + module='', %Module behaviour=[], %Behaviour exports=gb_sets:empty() :: gb_sets:set(fa()),%Exports imports=[] :: [fa()], %Imports, an orddict() @@ -729,7 +729,7 @@ start_state(Form, St) -> %% attribute_state(Form, State) -> %% State' -attribute_state({attribute,_L,module,_M}, #lint{module=[]}=St) -> +attribute_state({attribute,_L,module,_M}, #lint{module=''}=St) -> St; attribute_state({attribute,L,module,_M}, St) -> add_error(L, redefine_module, St); diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 5347ccaf1f..375fb6bc93 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2015. All Rights Reserved. +%% Copyright Ericsson AB 1999-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -65,7 +65,7 @@ too_many_arguments/1, basic_errors/1,bin_syntax_errors/1, predef/1, - maps/1,maps_type/1,otp_11851/1,otp_12195/1 + maps/1,maps_type/1,otp_11851/1,otp_12195/1, otp_13230/1 ]). % Default timetrap timeout (set in init_per_testcase). @@ -94,7 +94,7 @@ all() -> bif_clash, behaviour_basic, behaviour_multiple, otp_11861, otp_7550, otp_8051, format_warn, {group, on_load}, too_many_arguments, basic_errors, bin_syntax_errors, predef, - maps, maps_type, otp_11851, otp_12195]. + maps, maps_type, otp_11851, otp_12195, otp_13230]. groups() -> [{unused_vars_warn, [], @@ -3877,6 +3877,15 @@ otp_12195(Config) when is_list(Config) -> [] = run(Config, Ts), ok. +otp_13230(doc) -> + "OTP-13230: -deprecated without -module"; +otp_13230(Config) when is_list(Config) -> + Abstr = <<"-deprecated([{frutt,0,next_version}]).">>, + {errors,[{1,erl_lint,undefined_module}, + {1,erl_lint,{bad_deprecated,{frutt,0}}}], + []} = run_test2(Config, Abstr, []), + ok. + run(Config, Tests) -> F = fun({N,P,Ws,E}, BadL) -> case catch run_test(Config, P, Ws) of -- cgit v1.2.3 From f31ae20fbb2af0eeb9c87cfa1243abafbe7773cd Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 11 Jan 2016 12:59:33 +0100 Subject: stdlib: Let dets:open_file() crash when given raw file name See also ERL-55. --- lib/stdlib/src/dets.erl | 6 ++++-- lib/stdlib/test/dets_SUITE.erl | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl index 6d07f4018a..7036316242 100644 --- a/lib/stdlib/src/dets.erl +++ b/lib/stdlib/src/dets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1124,7 +1124,9 @@ repl({delayed_write, {Delay,Size} = C}, Defs) Defs#open_args{delayed_write = C}; repl({estimated_no_objects, I}, Defs) -> repl({min_no_slots, I}, Defs); -repl({file, File}, Defs) -> +repl({file, File}, Defs) when is_list(File) -> + Defs#open_args{file = File}; +repl({file, File}, Defs) when is_atom(File) -> Defs#open_args{file = to_list(File)}; repl({keypos, P}, Defs) when is_integer(P), P > 0 -> Defs#open_args{keypos =P}; diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl index 7f5e06524a..e061e16e4c 100644 --- a/lib/stdlib/test/dets_SUITE.erl +++ b/lib/stdlib/test/dets_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2014. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -53,7 +53,7 @@ simultaneous_open/1, insert_new/1, repair_continuation/1, otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1, otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1, - otp_8923/1, otp_9282/1, otp_11245/1, otp_11709/1]). + otp_8923/1, otp_9282/1, otp_11245/1, otp_11709/1, otp_13229/1]). -export([dets_dirty_loop/0]). @@ -110,7 +110,8 @@ all() -> many_clients, otp_4906, otp_5402, simultaneous_open, insert_new, repair_continuation, otp_5487, otp_6206, otp_6359, otp_4738, otp_7146, otp_8070, otp_8856, otp_8898, - otp_8899, otp_8903, otp_8923, otp_9282, otp_11245, otp_11709 + otp_8899, otp_8903, otp_8923, otp_9282, otp_11245, otp_11709, + otp_13229 ]. groups() -> @@ -3988,6 +3989,18 @@ otp_11709(Config) when is_list(Config) -> _ = file:delete(File), ok. +otp_13229(doc) -> + ["OTP-13229. open_file() exits with badarg when given binary file name."]; +otp_13229(_Config) -> + F = <<"binfile.tab">>, + try dets:open_file(name, [{file, F}]) of + R -> + exit({open_succeeded, R}) + catch + error:badarg -> + ok + end. + %% %% Parts common to several test cases %% -- cgit v1.2.3 From ebe42ec76748546f464076d8cf5d1238a56baf91 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 15 Dec 2015 16:37:10 +0100 Subject: erts: Introduce erts_code_purger as a system process with preloaded code. --- lib/kernel/test/init_SUITE.erl | 8 +++++++- lib/sasl/src/systools_make.erl | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index 3fe618ea4c..f90eb69ef1 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -401,6 +401,7 @@ restart(Config) when is_list(Config) -> %% Ok, the node is up, now the real test test begins. ?line erlang:monitor_node(Node, true), ?line InitPid = rpc:call(Node, erlang, whereis, [init]), + ?line PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]), ?line Procs = rpc:call(Node, erlang, processes, []), ?line MaxPid = lists:last(Procs), ?line ok = rpc:call(Node, init, restart, []), @@ -418,8 +419,13 @@ restart(Config) when is_list(Config) -> InitP = pid_to_list(InitPid), ?line InitP = pid_to_list(InitPid1), + %% and same purger process! + ?line PurgerPid1 = rpc:call(Node, erlang, whereis, [erts_code_purger]), + PurgerP = pid_to_list(PurgerPid), + ?line PurgerP = pid_to_list(PurgerPid1), + ?line NewProcs0 = rpc:call(Node, erlang, processes, []), - NewProcs = lists:delete(InitPid1, NewProcs0), + NewProcs = NewProcs0 -- [InitPid1, PurgerPid1], ?line case check_processes(NewProcs, MaxPid) of true -> ok; diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl index 8132034172..d207dc15bb 100644 --- a/lib/sasl/src/systools_make.erl +++ b/lib/sasl/src/systools_make.erl @@ -1469,7 +1469,9 @@ mandatory_modules() -> preloaded() -> %% Sorted - [erl_prim_loader,erlang,erts_internal,init,otp_ring0,prim_eval,prim_file, + [erl_prim_loader,erlang, + erts_code_purger, + erts_internal,init,otp_ring0,prim_eval,prim_file, prim_inet,prim_zip,zlib]. %%______________________________________________________________________ -- cgit v1.2.3 From c612edf4ada1f00b2bdb8404103e0d8307dc8f4c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 11 Jan 2016 19:17:04 +0100 Subject: erts: Refactor code:purge/1 and code:soft_purge/1 by moving code from code_server to erts_code_purger. This is more or less a copy-paste from code_server.erl to erts_code_purger.erl. All the inner mechanics of code:purge/1 and code:soft_purge/1 are unchanged. --- lib/kernel/src/code_server.erl | 250 ++--------------------------------------- lib/kernel/test/code_SUITE.erl | 1 + 2 files changed, 10 insertions(+), 241 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 4361bb7b60..1a42cc0e9f 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1281,254 +1281,22 @@ absname_vr([[X, $:]|Name], _, _AbsBase) -> absname(filename:join(Name), Dcwd). -%% do_purge(Module) -%% Kill all processes running code from *old* Module, and then purge the -%% module. Return true if any processes killed, else false. -do_purge(Mod0) -> - Mod = to_atom(Mod0), - case erlang:check_old_code(Mod) of - false -> - false; - true -> - true = erlang:copy_literals(Mod, true), - Res = check_proc_code(erlang:processes(), Mod, true), - true = erlang:copy_literals(Mod, false), - try - erlang:purge_module(Mod) - catch - _:_ -> ignore - end, - Res +is_loaded(M, Db) -> + case ets:lookup(Db, M) of + [{M,File}] -> {file,File}; + [] -> false end. -%% do_soft_purge(Module) -%% Purge old code only if no procs remain that run old code. -%% Return true in that case, false if procs remain (in this -%% case old code is not purged) +do_purge(Mod0) -> + Mod = to_atom(Mod0), + {_WasOld, DidKill} = erts_code_purger:purge(Mod), + DidKill. do_soft_purge(Mod0) -> Mod = to_atom(Mod0), - case erlang:check_old_code(Mod) of - false -> - true; - true -> - true = erlang:copy_literals(Mod, true), - case check_proc_code(erlang:processes(), Mod, false) of - false -> - true = erlang:copy_literals(Mod, false), - false; - true -> - true = erlang:copy_literals(Mod, false), - try - erlang:purge_module(Mod) - catch - _:_ -> ignore - end, - true - end - end. - -%% -%% check_proc_code(Pids, Mod, Hard) - Send asynchronous -%% requests to all processes to perform a check_process_code -%% operation. Each process will check their own state and -%% reply with the result. If 'Hard' equals -%% - true, processes that refer 'Mod' will be killed. If -%% any processes were killed true is returned; otherwise, -%% false. -%% - false, and any processes refer 'Mod', false will -%% returned; otherwise, true. -%% -%% Requests will be sent to all processes identified by -%% Pids at once, but without allowing GC to be performed. -%% Check process code operations that are aborted due to -%% GC need, will be restarted allowing GC. However, only -%% ?MAX_CPC_GC_PROCS outstanding operation allowing GC at -%% a time will be allowed. This in order not to blow up -%% memory wise. -%% -%% We also only allow ?MAX_CPC_NO_OUTSTANDING_KILLS -%% outstanding kills. This both in order to avoid flooding -%% our message queue with 'DOWN' messages and limiting the -%% amount of memory used to keep references to all -%% outstanding kills. -%% - -%% We maybe should allow more than two outstanding -%% GC requests, but for now we play it safe... --define(MAX_CPC_GC_PROCS, 2). --define(MAX_CPC_NO_OUTSTANDING_KILLS, 10). - --record(cpc_static, {hard, module, tag}). - --record(cpc_kill, {outstanding = [], - no_outstanding = 0, - waiting = [], - killed = false}). - -check_proc_code(Pids, Mod, Hard) -> - Tag = erlang:make_ref(), - CpcS = #cpc_static{hard = Hard, - module = Mod, - tag = Tag}, - check_proc_code(CpcS, cpc_init(CpcS, Pids, 0), 0, [], #cpc_kill{}, true). - -check_proc_code(#cpc_static{hard = true}, 0, 0, [], - #cpc_kill{outstanding = [], waiting = [], killed = Killed}, - true) -> - %% No outstanding requests. We did a hard check, so result is whether or - %% not we killed any processes... - Killed; -check_proc_code(#cpc_static{hard = false}, 0, 0, [], _KillState, Success) -> - %% No outstanding requests and we did a soft check... - Success; -check_proc_code(#cpc_static{hard = false, tag = Tag} = CpcS, NoReq0, NoGcReq0, - [], _KillState, false) -> - %% Failed soft check; just cleanup the remaining replies corresponding - %% to the requests we've sent... - {NoReq1, NoGcReq1} = receive - {check_process_code, {Tag, _P, GC}, _Res} -> - case GC of - false -> {NoReq0-1, NoGcReq0}; - true -> {NoReq0, NoGcReq0-1} - end - end, - check_proc_code(CpcS, NoReq1, NoGcReq1, [], _KillState, false); -check_proc_code(#cpc_static{tag = Tag} = CpcS, NoReq0, NoGcReq0, NeedGC0, - KillState0, Success) -> - - %% Check if we should request a GC operation - {NoGcReq1, NeedGC1} = case NoGcReq0 < ?MAX_CPC_GC_PROCS of - GcOpAllowed when GcOpAllowed == false; - NeedGC0 == [] -> - {NoGcReq0, NeedGC0}; - _ -> - {NoGcReq0+1, cpc_request_gc(CpcS,NeedGC0)} - end, - - %% Wait for a cpc reply or 'DOWN' message - {NoReq1, NoGcReq2, Pid, Result, KillState1} = cpc_recv(Tag, - NoReq0, - NoGcReq1, - KillState0), - - %% Check the result of the reply - case Result of - aborted -> - %% Operation aborted due to the need to GC in order to - %% determine if the process is referring the module. - %% Schedule the operation for restart allowing GC... - check_proc_code(CpcS, NoReq1, NoGcReq2, [Pid|NeedGC1], KillState1, - Success); - false -> - %% Process not referring the module; done with this process... - check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1, KillState1, - Success); - true -> - %% Process referring the module... - case CpcS#cpc_static.hard of - false -> - %% ... and soft check. The whole operation failed so - %% no point continuing; clean up and fail... - check_proc_code(CpcS, NoReq1, NoGcReq2, [], KillState1, - false); - true -> - %% ... and hard check; schedule kill of it... - check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1, - cpc_sched_kill(Pid, KillState1), Success) - end; - 'DOWN' -> - %% Handled 'DOWN' message - check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1, - KillState1, Success) - end. - -cpc_recv(Tag, NoReq, NoGcReq, #cpc_kill{outstanding = []} = KillState) -> - receive - {check_process_code, {Tag, Pid, GC}, Res} -> - cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState) - end; -cpc_recv(Tag, NoReq, NoGcReq, - #cpc_kill{outstanding = [R0, R1, R2, R3, R4 | _]} = KillState) -> - receive - {'DOWN', R, process, _, _} when R == R0; - R == R1; - R == R2; - R == R3; - R == R4 -> - cpc_handle_down(NoReq, NoGcReq, R, KillState); - {check_process_code, {Tag, Pid, GC}, Res} -> - cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState) - end; -cpc_recv(Tag, NoReq, NoGcReq, #cpc_kill{outstanding = [R|_]} = KillState) -> - receive - {'DOWN', R, process, _, _} -> - cpc_handle_down(NoReq, NoGcReq, R, KillState); - {check_process_code, {Tag, Pid, GC}, Res} -> - cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState) - end. - -cpc_handle_down(NoReq, NoGcReq, R, #cpc_kill{outstanding = Rs, - no_outstanding = N} = KillState) -> - {NoReq, NoGcReq, undefined, 'DOWN', - cpc_sched_kill_waiting(KillState#cpc_kill{outstanding = cpc_list_rm(R, Rs), - no_outstanding = N-1})}. - -cpc_list_rm(R, [R|Rs]) -> - Rs; -cpc_list_rm(R0, [R1|Rs]) -> - [R1|cpc_list_rm(R0, Rs)]. - -cpc_handle_cpc(NoReq, NoGcReq, false, Pid, Res, KillState) -> - {NoReq-1, NoGcReq, Pid, Res, KillState}; -cpc_handle_cpc(NoReq, NoGcReq, true, Pid, Res, KillState) -> - {NoReq, NoGcReq-1, Pid, Res, KillState}. - -cpc_sched_kill_waiting(#cpc_kill{waiting = []} = KillState) -> - KillState; -cpc_sched_kill_waiting(#cpc_kill{outstanding = Rs, - no_outstanding = N, - waiting = [P|Ps]} = KillState) -> - R = erlang:monitor(process, P), - exit(P, kill), - KillState#cpc_kill{outstanding = [R|Rs], - no_outstanding = N+1, - waiting = Ps, - killed = true}. - -cpc_sched_kill(Pid, #cpc_kill{no_outstanding = N, waiting = Pids} = KillState) - when N >= ?MAX_CPC_NO_OUTSTANDING_KILLS -> - KillState#cpc_kill{waiting = [Pid|Pids]}; -cpc_sched_kill(Pid, - #cpc_kill{outstanding = Rs, no_outstanding = N} = KillState) -> - R = erlang:monitor(process, Pid), - exit(Pid, kill), - KillState#cpc_kill{outstanding = [R|Rs], - no_outstanding = N+1, - killed = true}. - -cpc_request(#cpc_static{tag = Tag, module = Mod}, Pid, AllowGc) -> - erlang:check_process_code(Pid, Mod, [{async, {Tag, Pid, AllowGc}}, - {allow_gc, AllowGc}]). - -cpc_request_gc(CpcS, [Pid|Pids]) -> - cpc_request(CpcS, Pid, true), - Pids. - -cpc_init(_CpcS, [], NoReqs) -> - NoReqs; -cpc_init(CpcS, [Pid|Pids], NoReqs) -> - cpc_request(CpcS, Pid, false), - cpc_init(CpcS, Pids, NoReqs+1). - -% end of check_proc_code() implementation. + erts_code_purger:soft_purge(Mod). -is_loaded(M, Db) -> - case ets:lookup(Db, M) of - [{M,File}] -> {file,File}; - [] -> false - end. %% ------------------------------------------------------- %% The on_load functionality. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index dfcb20d594..071f8d1d3b 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -766,6 +766,7 @@ analyse([], [This={M,F,A}|Path], Visited, ErrCnt0) -> OK = [erlang, os, prim_file, erl_prim_loader, init, ets, code_server, lists, lists_sort, unicode, binary, filename, gb_sets, gb_trees, hipe_unified_loader, hipe_bifs, + erts_code_purger, prim_zip, zlib], ErrCnt1 = case lists:member(M, OK) or erlang:is_builtin(M,F,A) of -- cgit v1.2.3 From fa44f865c3fc6253cf4691cf94839c303a3ee40f Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 15 Dec 2015 20:32:39 +0100 Subject: erts: Make erlang:purge_module/1 safe Problem: erlang:purge_module/1 is not safe in the sense that very bad things may happen if the code to be purged is still referred to by live processes. Introduce erts_internal:purge_module which is the same as the old erlang:purge_module BIF (except it returns false if no such old module). Implement erlang:purge_module in Erlang and let it invoke erts_code_purger for safe purging where all clogging processes first are killed. --- lib/kernel/test/code_SUITE.erl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 071f8d1d3b..772a1e6b14 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -380,8 +380,23 @@ purge(Config) when is_list(Config) -> purge_many_exits(Config) when is_list(Config) -> OldFlag = process_flag(trap_exit, true), + code:purge(code_b_test), {'EXIT',_} = (catch code:purge({})), + + CodePurgeF = fun(M, Exp) -> Exp = code:purge(M) end, + purge_many_exits_do(CodePurgeF), + + %% Let's repeat test for erlang:purge_module as it does the same thing + %% now in erts-8.0 (except for return value). + ErlangPurgeF = fun(M, _Exp) -> erlang:purge_module(M) end, + purge_many_exits_do(ErlangPurgeF), + + process_flag(trap_exit, OldFlag), + ok. + + +purge_many_exits_do(PurgeF) -> false = code:purge(code_b_test), TPids = lists:map(fun (_) -> {code_b_test:do_spawn(), @@ -400,7 +415,7 @@ purge_many_exits(Config) when is_list(Config) -> false = code_b_test:check_exit(Pid1), true = erlang:is_process_alive(Pid2) end, TPids), - true = code:purge(code_b_test), + PurgeF(code_b_test, true), lists:foreach(fun ({Pid1, Pid2}) -> false = erlang:is_process_alive(Pid1), true = code_b_test:check_exit(Pid1), @@ -409,9 +424,7 @@ purge_many_exits(Config) when is_list(Config) -> end, TPids), lists:foreach(fun ({_Pid1, Pid2}) -> receive {'EXIT', Pid2, _} -> ok end - end, TPids), - process_flag(trap_exit, OldFlag), - ok. + end, TPids). soft_purge(suite) -> []; -- cgit v1.2.3 From fea8e2cade3de24f044c834e0b62f58921a4e9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 14 Jan 2016 14:44:06 +0100 Subject: dialyzer: Update Maps tests --- lib/dialyzer/test/small_SUITE_data/results/maps1 | 4 ++++ lib/dialyzer/test/small_SUITE_data/src/maps1.erl | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 lib/dialyzer/test/small_SUITE_data/results/maps1 (limited to 'lib') diff --git a/lib/dialyzer/test/small_SUITE_data/results/maps1 b/lib/dialyzer/test/small_SUITE_data/results/maps1 new file mode 100644 index 0000000000..5a78d66a92 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/maps1 @@ -0,0 +1,4 @@ + +maps1.erl:43: Function t3/0 has no local return +maps1.erl:44: The call maps1:foo(~{'greger'=>3, ~{'arne'=>'anka'}~=>45}~,1) will never return since it differs in the 2nd argument from the success typing arguments: (#{},'b') +maps1.erl:52: The call Mod:'function'(~{'literal'=>'map'}~,'another_arg') requires that Mod is of type atom() | tuple() not #{} diff --git a/lib/dialyzer/test/small_SUITE_data/src/maps1.erl b/lib/dialyzer/test/small_SUITE_data/src/maps1.erl index 06ced5b69e..bb2f66a498 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/maps1.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/maps1.erl @@ -39,3 +39,15 @@ t2() -> ok. update(#{ id := Id, val := Val } = M, X) when is_integer(Id) -> M#{ val := [Val,X] }. + +t3() -> + foo(#{greger => 3, #{arne=>anka} => 45}, 1). + +foo(#{} = M, b) -> %% Error + M#{alfa => 42, beta := 1337}. + +t4() -> + case #{} of + #{} -> ok; + Mod -> Mod:function(#{literal => map}, another_arg) %% Error + end. -- cgit v1.2.3 From e593432c9e590c29971a4e0dc1c6692d82c2a1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 14 Jan 2016 11:58:40 +0100 Subject: hipe: Fix map pretty printing of pairs In commit f667931e2905797ffab63e224e56eaf07f77178a the core format changed for map pairs. Let dialyzer and hipe pretty printing of maps also adhere to those changes. An Erlang map update, M#{foo := 1, bar => 2} will now be printed as: ~{ 'foo' := 1, 'bar' => 2 | M }~ --- lib/hipe/cerl/cerl_prettypr.erl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/hipe/cerl/cerl_prettypr.erl b/lib/hipe/cerl/cerl_prettypr.erl index 7e8b7f60bd..729143eba9 100644 --- a/lib/hipe/cerl/cerl_prettypr.erl +++ b/lib/hipe/cerl/cerl_prettypr.erl @@ -627,12 +627,10 @@ lay_map_pair(Node, Ctxt) -> K = map_pair_key(Node), V = map_pair_val(Node), OpTxt = case concrete(map_pair_op(Node)) of - assoc -> "::<"; - exact -> "~<" + assoc -> "=>"; + exact -> ":=" end, - beside(floating(text(OpTxt)), - beside(lay(K,Ctxt),beside(floating(text(",")), beside(lay(V,Ctxt), - floating(text(">")))))). + beside(lay(K,Ctxt),beside(floating(text(OpTxt)),lay(V,Ctxt))). lay_let(Node, Ctxt) -> V = lay_value_list(let_vars(Node), Ctxt), -- cgit v1.2.3 From 48e25dfef23a51d02629b2c9fa9963fd3ba7788c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 14 Jan 2016 13:10:00 +0100 Subject: compiler, hipe: Fix pretty printing of Core Maps Literal maps could cause dialyzer to crash when pretty printing the results. Reported-by: Chris McGrath --- lib/compiler/src/cerl.erl | 11 +++++++++-- lib/hipe/cerl/cerl_prettypr.erl | 10 +++------- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index 010327b5e3..e7a2b8177a 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -1598,13 +1598,20 @@ is_c_map(#c_literal{val = V}) when is_map(V) -> is_c_map(_) -> false. --spec map_es(c_map()) -> [c_map_pair()]. +-spec map_es(c_map() | c_literal()) -> [c_map_pair()]. +map_es(#c_literal{anno=As,val=M}) when is_map(M) -> + [ann_c_map_pair(As, + #c_literal{anno=As,val='assoc'}, + #c_literal{anno=As,val=K}, + #c_literal{anno=As,val=V}) || {K,V} <- maps:to_list(M)]; map_es(#c_map{es = Es}) -> Es. --spec map_arg(c_map()) -> c_map() | c_literal(). +-spec map_arg(c_map() | c_literal()) -> c_map() | c_literal(). +map_arg(#c_literal{anno=As,val=M}) when is_map(M) -> + #c_literal{anno=As,val=#{}}; map_arg(#c_map{arg=M}) -> M. diff --git a/lib/hipe/cerl/cerl_prettypr.erl b/lib/hipe/cerl/cerl_prettypr.erl index 729143eba9..1a6e6999fe 100644 --- a/lib/hipe/cerl/cerl_prettypr.erl +++ b/lib/hipe/cerl/cerl_prettypr.erl @@ -64,8 +64,8 @@ seq_arg/1, seq_body/1, string_lit/1, try_arg/1, try_body/1, try_vars/1, try_evars/1, try_handler/1, tuple_es/1, type/1, values_es/1, var_name/1, - c_map/1, map_arg/1, map_es/1, is_c_map_empty/1, - c_map_pair/2, map_pair_key/1, map_pair_val/1, map_pair_op/1 + map_arg/1, map_es/1, is_c_map_empty/1, + map_pair_key/1, map_pair_val/1, map_pair_op/1 ]). -define(PAPER, 76). @@ -499,12 +499,8 @@ lay_literal(Node, Ctxt) -> lay_cons(Node, Ctxt); V when is_tuple(V) -> lay_tuple(Node, Ctxt); - M when is_map(M), map_size(M) =:= 0 -> - text("~{}~"); M when is_map(M) -> - lay_map(c_map([c_map_pair(abstract(K),abstract(V)) - || {K,V} <- maps:to_list(M)]), - Ctxt) + lay_map(Node, Ctxt) end. lay_var(Node, Ctxt) -> -- cgit v1.2.3 From 64248a85e221a905aa37fbb8dd0ab1d4f4551be0 Mon Sep 17 00:00:00 2001 From: Andrew Bennett Date: Thu, 14 Jan 2016 18:26:28 +0100 Subject: crypto: Fix bug for multiple blocks for AES-ECB --- lib/crypto/c_src/crypto.c | 5 ++++- lib/crypto/test/crypto_SUITE.erl | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 9de8dc74c2..3c73c318ed 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -2042,6 +2042,7 @@ static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ErlNifBinary key_bin, data_bin; AES_KEY aes_key; int i; + int j; unsigned char* ret_ptr; ERL_NIF_TERM ret; @@ -2064,7 +2065,9 @@ static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a } ret_ptr = enif_make_new_binary(env, data_bin.size, &ret); - AES_ecb_encrypt(data_bin.data, ret_ptr, &aes_key, i); + for (j = 0; j < data_bin.size; j += 16) { + AES_ecb_encrypt(data_bin.data+j, ret_ptr+j, &aes_key, i); + } CONSUME_REDS(env,data_bin); return ret; } diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index e84f5e1075..802c8a4df4 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1301,7 +1301,23 @@ aes_ecb() -> <<"0000000000000000">>}, {aes_ecb, <<"FEDCBA9876543210">>, - <<"FFFFFFFFFFFFFFFF">>} + <<"FFFFFFFFFFFFFFFF">>}, + %% AES ECB test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + %% F.1.1 ECB-AES128.Encrypt, F.1.2 ECB-AES128.Decrypt + {aes_ecb, + hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710")}, + %% F.1.5 ECB-AES256.Encrypt, F.1.6 ECB-AES256.Decrypt + {aes_ecb, + hexstr2bin("603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710")} ]. aes_ige256() -> -- cgit v1.2.3 From dd16a879b9012f4d2182eb780e002f47183e17ff Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 17 Dec 2015 13:02:21 +0100 Subject: dialyzer: Correct handling of parameters of opaque types Correction of commit d57f5e. --- lib/hipe/cerl/erl_types.erl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index cd2d2fe207..7a2abc226f 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -2711,7 +2711,6 @@ is_compat_args([A1|Args1], [A2|Args2]) -> is_compat_args([], []) -> true; is_compat_args(_, _) -> false. -is_compat_arg(A, A) -> true; is_compat_arg(A1, A2) -> is_specialization(A1, A2) orelse is_specialization(A2, A1). @@ -2722,6 +2721,7 @@ is_compat_arg(A1, A2) -> %% any(). For example, {_,_} is a specialization of any(), but not of %% tuple(). Does not handle variables, but any() and unions (sort of). +is_specialization(T, T) -> true; is_specialization(_, ?any) -> true; is_specialization(?any, _) -> false; is_specialization(?function(Domain1, Range1), ?function(Domain2, Range2)) -> @@ -2747,8 +2747,8 @@ is_specialization(?tuple(Elements1, Arity, _), specialization_list(Elements1, sup_tuple_elements(List)); is_specialization(?tuple_set(List1), ?tuple_set(List2)) -> try - specialization_list(lists:append([T || {_Arity, T} <- List1]), - lists:append([T || {_Arity, T} <- List2])) + specialization_list_list([sup_tuple_elements(T) || {_Arity, T} <- List1], + [sup_tuple_elements(T) || {_Arity, T} <- List2]) catch _:_ -> false end; is_specialization(?union(List1)=T1, ?union(List2)=T2) -> @@ -2772,13 +2772,19 @@ is_specialization(T1, ?opaque(_) = T2) -> is_specialization(T1, t_opaque_structure(T2)); is_specialization(?var(_), _) -> exit(error); is_specialization(_, ?var(_)) -> exit(error); -is_specialization(T, T) -> true; is_specialization(?none, _) -> false; is_specialization(_, ?none) -> false; is_specialization(?unit, _) -> false; is_specialization(_, ?unit) -> false; is_specialization(#c{}, #c{}) -> false. +specialization_list_list(LL1, LL2) -> + length(LL1) =:= length(LL2) andalso specialization_list_list1(LL1, LL2). + +specialization_list_list1([], []) -> true; +specialization_list_list1([L1|LL1], [L2|LL2]) -> + specialization_list(L1, L2) andalso specialization_list_list1(LL1, LL2). + specialization_list(L1, L2) -> length(L1) =:= length(L2) andalso specialization_list1(L1, L2). -- cgit v1.2.3 From 898b4e182837ad5540afe6dad389d193a64f6a38 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 14 Jan 2016 10:35:01 +0100 Subject: edoc: Assign correct names to list arguments Bug reported by Josemic. See also ERL-63. --- lib/edoc/src/edoc_specs.erl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index bb98e8b04f..f2e5891c2e 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -270,12 +270,8 @@ parms([], []) -> parms([A | As], [D | Ds]) -> [param(A, D) | parms(As, Ds)]. -param(#t_list{type = Type}, Default) -> - param(Type, Default); param(#t_paren{type = Type}, Default) -> param(Type, Default); -param(#t_nonempty_list{type = Type}, Default) -> - param(Type, Default); param(#t_record{name = #t_atom{val = Name}}, _Default) -> list_to_atom(capitalize(atom_to_list(Name))); param(T, Default) -> -- cgit v1.2.3 From 2f0941478ed566949eae5d09b4cb16edcbaaec63 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 22 Dec 2015 13:24:24 +0100 Subject: ssh: added sftp server benchmark --- lib/ssh/test/ssh_benchmark_SUITE.erl | 144 +++++++++++++++++++++++++++++------ 1 file changed, 122 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl index 2add99de97..24927805e4 100644 --- a/lib/ssh/test/ssh_benchmark_SUITE.erl +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -37,8 +37,8 @@ all() -> [{group, opensshc_erld} ]. groups() -> - [{opensshc_erld, [{repeat, 3}], [openssh_client_shell]}, - {erlc_opensshd, [{repeat, 3}], [erl_shell]} + [{opensshc_erld, [{repeat, 3}], [openssh_client_shell, + openssh_client_sftp]} ]. @@ -50,7 +50,7 @@ init_per_suite(Config) -> report_client_algorithms(), ok = ssh:start(), {ok,TracerPid} = erlang_trace(), - [{tracer_pid,TracerPid} | Config] + [{tracer_pid,TracerPid} | init_sftp_dirs(Config)] catch C:E -> {skip, io_lib:format("Couldn't start ~p:~p",[C,E])} @@ -71,8 +71,12 @@ init_per_group(opensshc_erld, Config) -> ssh_test_lib:setup_dsa(DataDir, UserDir), ssh_test_lib:setup_rsa(DataDir, UserDir), ssh_test_lib:setup_ecdsa("256", DataDir, UserDir), + Common = ssh_test_lib:intersect_bi_dir( + ssh_test_lib:intersection(ssh:default_algorithms(), + ssh_test_lib:default_algorithms(sshc))), [{c_kexs, ssh_test_lib:sshc(kex)}, - {c_ciphers, ssh_test_lib:sshc(cipher)} + {c_ciphers, ssh_test_lib:sshc(cipher)}, + {common_algs, Common} | Config]; _ -> {skip, "No OpenSsh client found"} @@ -94,20 +98,21 @@ init_per_testcase(_Func, Conf) -> end_per_testcase(_Func, _Conf) -> ok. + +init_sftp_dirs(Config) -> + UserDir = ?config(priv_dir, Config), + SrcDir = filename:join(UserDir, "sftp_src"), + ok = file:make_dir(SrcDir), + SrcFile = "big_data", + DstDir = filename:join(UserDir, "sftp_dst"), + ok = file:make_dir(DstDir), + N = 100 * 1024*1024, + ok = file:write_file(filename:join(SrcDir,SrcFile), crypto:rand_bytes(N)), + [{sftp_src_dir,SrcDir}, {sftp_dst_dir,DstDir}, {src_file,SrcFile}, {sftp_size,N} + | Config]. + %%%================================================================ openssh_client_shell(Config) -> - CommonAlgs = ssh_test_lib:intersect_bi_dir( - ssh_test_lib:intersection(ssh:default_algorithms(), - ssh_test_lib:default_algorithms(sshc))), - KexVariants = - [ [{kex,[Kex]}] - || Kex <- proplists:get_value(kex, CommonAlgs)], - CipherVariants = - [ [{cipher,[{client2server,[Cipher]}, - {server2client,[Cipher]}]}] - || Cipher <- proplists:get_value(cipher, CommonAlgs)], - - lists:foreach( fun(PrefAlgs=[{kex,[Kex]}]) when Kex == 'diffie-hellman-group-exchange-sha256' -> lists:foreach( @@ -120,7 +125,8 @@ openssh_client_shell(Config) -> (PrefAlgs) -> openssh_client_shell(Config, [{preferred_algorithms, PrefAlgs}]) - end, KexVariants ++ CipherVariants). + end, variants(kex,Config) ++ variants(cipher,Config) + ). openssh_client_shell(Config, Options) -> @@ -151,7 +157,7 @@ openssh_client_shell(Config, Options) -> {SlavePid, _ClientResponse} -> %% ct:pal("ClientResponse = ~p",[_ClientResponse]), {ok, List} = get_trace_list(TracerPid), - Times = find_times(List), + Times = find_times(List, [accept_to_hello, kex, kex_to_auth, auth, to_prompt]), Algs = find_algs(List), ct:pal("Algorithms = ~p~n~nTimes = ~p",[Algs,Times]), lists:foreach( @@ -189,6 +195,95 @@ openssh_client_shell(Config, Options) -> %%%================================================================ +openssh_client_sftp(Config) -> + lists:foreach( + fun(PrefAlgs) -> + openssh_client_sftp(Config, [{preferred_algorithms,PrefAlgs}]) + end, variants(cipher,Config)). + + +openssh_client_sftp(Config, Options) -> + SystemDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + SftpSrcDir = ?config(sftp_src_dir, Config), + SrcFile = ?config(src_file, Config), + SrcSize = ?config(sftp_size, Config), + KnownHosts = filename:join(UserDir, "known_hosts"), + + {ok, TracerPid} = erlang_trace(), + {ServerPid, _Host, Port} = + ssh_test_lib:daemon([{system_dir, SystemDir}, + {public_key_alg, ssh_dsa}, + {subsystems,[ssh_sftpd:subsystem_spec([%{cwd, SftpSrcDir}, + {root, SftpSrcDir}])]}, + {failfun, fun ssh_test_lib:failfun/2} + | Options]), + ct:sleep(500), + Cmd = lists:concat(["sftp", + " -b -", + " -P ",Port, + " -o UserKnownHostsFile=", KnownHosts, + " -o \"StrictHostKeyChecking no\"", + " localhost:",SrcFile + ]), +%% ct:pal("Cmd = ~p",[Cmd]), + + Parent = self(), + SlavePid = spawn(fun() -> + Parent ! {self(),os:cmd(Cmd)} + end), + receive + {SlavePid, _ClientResponse} -> + ct:pal("ClientResponse = ~p",[_ClientResponse]), + {ok, List} = get_trace_list(TracerPid), +%%ct:pal("List=~p",[List]), + Times = find_times(List, [channel_open_close]), + Algs = find_algs(List), + ct:pal("Algorithms = ~p~n~nTimes = ~p",[Algs,Times]), + lists:foreach( + fun({{A,B},Value,Unit}) when A==encrypt ; A==decrypt -> + Data = [{value, Value}, + {suite, ?MODULE}, + {name, mk_name(["Sftp Cipher ",A," ",B," [",Unit,"]"])} + ], + ct:pal("sftp ct_event:notify ~p",[Data]), + ct_event:notify(#event{name = benchmark_data, + data = Data}); + ({channel_open_close,Value,Unit}) -> + Data = [{value, round( (1024*Value) / SrcSize )}, + {suite, ?MODULE}, + {name, mk_name(["Sftp transfer [",Unit," per kbyte]"])} + ], + ct:pal("sftp ct_event:notify ~p",[Data]), + ct_event:notify(#event{name = benchmark_data, + data = Data}); + (_) -> + skip + end, Times), + ssh:stop_daemon(ServerPid), + ok + after 10000 -> + ssh:stop_daemon(ServerPid), + exit(SlavePid, kill), + {fail, timeout} + end. + +%%%================================================================ +variants(Tag, Config) -> + TagType = + case proplists:get_value(Tag, ssh:default_algorithms()) of + [{_,_}|_] -> one_way; + [A|_] when is_atom(A) -> two_way + end, + [ [{Tag,tag_value(TagType,Alg)}] + || Alg <- proplists:get_value(Tag, ?config(common_algs,Config)) + ]. + +tag_value(two_way, Alg) -> [Alg]; +tag_value(one_way, Alg) -> [{client2server,[Alg]}, + {server2client,[Alg]}]. + +%%%---------------------------------------------------------------- fmt_alg(Alg, List) when is_atom(Alg) -> fmt_alg(atom_to_list(Alg), List); fmt_alg(Alg = "diffie-hellman-group-exchange-sha" ++ _, List) -> @@ -199,7 +294,7 @@ fmt_alg(Alg = "diffie-hellman-group-exchange-sha" ++ _, List) -> catch _:_ -> Alg end; -fmt_alg(Alg, List) -> +fmt_alg(Alg, _List) -> Alg. %%%---------------------------------------------------------------- @@ -209,8 +304,7 @@ char($-) -> $_; char(C) -> C. %%%---------------------------------------------------------------- -find_times(L) -> - Xs = [accept_to_hello, kex, kex_to_auth, auth, to_prompt], +find_times(L, Xs) -> [find_time(X,L) || X <- Xs] ++ crypto_algs_times_sizes([encrypt,decrypt], L). @@ -268,7 +362,13 @@ find_time(to_prompt, L) -> end, ?recv(#ssh_msg_channel_request{request_type="env"}) ], L, []), - {to_prompt, now2micro_sec(now_diff(T1,T0)), microsec}. + {to_prompt, now2micro_sec(now_diff(T1,T0)), microsec}; +find_time(channel_open_close, L) -> + [T0,T1] = find([?recv(#ssh_msg_channel_request{request_type="subsystem"}), + ?send(#ssh_msg_channel_close{}) + ], L, []), + {channel_open_close, now2micro_sec(now_diff(T1,T0)), microsec}. + find([F|Fs], [C|Cs], Acc) when is_function(F,1) -> -- cgit v1.2.3 From 95f121ed04a632257cd0e429cb16ba9d9a7110bb Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 22 Dec 2015 15:10:00 +0100 Subject: ssh: added cipher name to transfer speed report --- lib/ssh/test/ssh_benchmark_SUITE.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl index 24927805e4..781230e728 100644 --- a/lib/ssh/test/ssh_benchmark_SUITE.erl +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -250,9 +250,10 @@ openssh_client_sftp(Config, Options) -> ct_event:notify(#event{name = benchmark_data, data = Data}); ({channel_open_close,Value,Unit}) -> + Cipher = fmt_alg(Algs#alg.encrypt, List), Data = [{value, round( (1024*Value) / SrcSize )}, {suite, ?MODULE}, - {name, mk_name(["Sftp transfer [",Unit," per kbyte]"])} + {name, mk_name(["Sftp transfer ",Cipher," [",Unit," per kbyte]"])} ], ct:pal("sftp ct_event:notify ~p",[Data]), ct_event:notify(#event{name = benchmark_data, -- cgit v1.2.3 From 02c266f80b87e690203b764bd518e347386fae7e Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 4 Jan 2016 15:17:41 +0100 Subject: ssh: encode/decode benchmark suites --- lib/ssh/test/ssh_benchmark_SUITE.erl | 38 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/ssh/test/ssh_benchmark_SUITE.erl b/lib/ssh/test/ssh_benchmark_SUITE.erl index 781230e728..e90bfa3d16 100644 --- a/lib/ssh/test/ssh_benchmark_SUITE.erl +++ b/lib/ssh/test/ssh_benchmark_SUITE.erl @@ -307,7 +307,10 @@ char(C) -> C. %%%---------------------------------------------------------------- find_times(L, Xs) -> [find_time(X,L) || X <- Xs] ++ - crypto_algs_times_sizes([encrypt,decrypt], L). + function_algs_times_sizes([{ssh_transport,encrypt,2}, + {ssh_transport,decrypt,2}, + {ssh_message,decode,1}, + {ssh_message,encode,1}], L). -record(call, { mfa, @@ -396,24 +399,31 @@ find_gex_size_string(L) -> Size. %%%---------------- -crypto_algs_times_sizes(EncDecs, L) -> - Raw = [{_Algorithm = case EncDec of - encrypt -> {encrypt,S#ssh.encrypt}; - decrypt -> {decrypt,S#ssh.decrypt} - end, - size(Data), - now2micro_sec(now_diff(T1, T0)) - } +function_algs_times_sizes(EncDecs, L) -> + Raw = [begin + {Tag,Size} = function_ats_result(EncDec, C), + {Tag, Size, now2micro_sec(now_diff(T1,T0))} + end || EncDec <- EncDecs, - #call{mfa = {ssh_transport,ED,2}, - args = [S,Data], - t_call = T0, - t_return = T1} <- L, + C = #call{mfa = ED, + args = Args, %%[S,Data], + t_call = T0, + t_return = T1} <- L, ED == EncDec ], [{Alg, round(1024*Time/Size), "microsec per kbyte"} % Microseconds per 1k bytes. || {Alg,Size,Time} <- lists:foldl(fun increment/2, [], Raw)]. +function_ats_result({ssh_transport,encrypt,2}, #call{args=[S,Data]}) -> + {{encrypt,S#ssh.encrypt}, size(Data)}; +function_ats_result({ssh_transport,decrypt,2}, #call{args=[S,Data]}) -> + {{decrypt,S#ssh.decrypt}, size(Data)}; +function_ats_result({ssh_message,encode,1}, #call{result=Data}) -> + {encode, size(Data)}; +function_ats_result({ssh_message,decode,1}, #call{args=[Data]}) -> + {decode, size(Data)}. + + increment({Alg,Sz,T}, [{Alg,SumSz,SumT}|Acc]) -> [{Alg,SumSz+Sz,SumT+T} | Acc]; increment(Spec, [X|Acc]) -> @@ -443,6 +453,8 @@ erlang_trace() -> {ssh_transport,select_algorithm,3}, {ssh_transport,encrypt,2}, {ssh_transport,decrypt,2}, + {ssh_message,encode,1}, + {ssh_message,decode,1}, {public_key,dh_gex_group,4} % To find dh_gex group size ]], {ok, TracerPid}. -- cgit v1.2.3 From b9b704f8b584994cbbb4975133d6032d5d0d294e Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Mon, 4 Jan 2016 15:21:51 +0100 Subject: ssh: Optimization - inline encoding in ssh_message:encode/1, now 8 times faster. Also fixes minor error in ssh_protocol_SUITE that the new encoder found. --- lib/ssh/src/ssh_bits.erl | 141 +++++------------------------- lib/ssh/src/ssh_message.erl | 169 ++++++++++++++++++++---------------- lib/ssh/src/ssh_transport.erl | 48 +++++----- lib/ssh/test/ssh_protocol_SUITE.erl | 2 +- 4 files changed, 135 insertions(+), 225 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl index 4da3a6018b..101bf76cd3 100644 --- a/lib/ssh/src/ssh_bits.erl +++ b/lib/ssh/src/ssh_bits.erl @@ -26,52 +26,30 @@ -include("ssh.hrl"). --export([encode/2]). --export([mpint/1, string/1, name_list/1]). +-export([mpint/1, name_list/1]). -export([random/1]). --define(name_list(X), - (fun(B) -> ?binary(B) end)(list_to_binary(name_concat(X)))). - - -name_concat([Name]) when is_atom(Name) -> atom_to_list(Name); -name_concat([Name]) when is_list(Name) -> Name; -name_concat([Name|Ns]) -> - if is_atom(Name) -> - [atom_to_list(Name),"," | name_concat(Ns)]; - is_list(Name) -> - [Name,"," | name_concat(Ns)] - end; -name_concat([]) -> []. - - -name_list(Ns) -> - ?name_list(Ns). +%%%---------------------------------------------------------------- +name_list([Name]) -> to_bin(Name); +name_list([Name|Ns]) -> <<(to_bin(Name))/binary, ",", (name_list(Ns))/binary>>; +name_list([]) -> <<>>. + +to_bin(A) when is_atom(A) -> list_to_binary(atom_to_list(A)); +to_bin(S) when is_list(S) -> list_to_binary(S); +to_bin(B) when is_binary(B) -> B. + +%%%---------------------------------------------------------------- +%%% Multi Precision Integer encoding +mpint(-1) -> <<0,0,0,1,16#ff>>; +mpint(0) -> <<0,0,0,0>>; +mpint(X) when X < 0 -> mpint_neg(X,0,[]); +mpint(X) -> mpint_pos(X,0,[]). - -string(Str) -> - ?string(Str). - - -%% MP representaion (SSH2) -mpint(X) when X < 0 -> - if X == -1 -> - <<0,0,0,1,16#ff>>; - true -> - mpint_neg(X,0,[]) - end; -mpint(X) -> - if X == 0 -> - <<0,0,0,0>>; - true -> - mpint_pos(X,0,[]) - end. - mpint_neg(-1,I,Ds=[MSB|_]) -> if MSB band 16#80 =/= 16#80 -> <>; true -> - (<>) + <> end; mpint_neg(X,I,Ds) -> mpint_neg(X bsr 8,I+1,[(X band 255)|Ds]). @@ -80,96 +58,17 @@ mpint_pos(0,I,Ds=[MSB|_]) -> if MSB band 16#80 == 16#80 -> <>; true -> - (<>) + <> end; mpint_pos(X,I,Ds) -> mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]). -encode(List, Types) -> - list_to_binary(enc(List, Types)). - -%% -%% Encode record element -%% -enc(Xs, Ts) -> - enc(Xs, Ts, 0). - -enc(Xs, [boolean|Ts], Offset) -> - X = hd(Xs), - [?boolean(X) | enc(tl(Xs), Ts, Offset+1)]; -enc(Xs, [byte|Ts], Offset) -> - X = hd(Xs), - [?byte(X) | enc(tl(Xs), Ts,Offset+1)]; -enc(Xs, [uint16|Ts], Offset) -> - X = hd(Xs), - [?uint16(X) | enc(tl(Xs), Ts,Offset+2)]; -enc(Xs, [uint32 |Ts], Offset) -> - X = hd(Xs), - [?uint32(X) | enc(tl(Xs), Ts,Offset+4)]; -enc(Xs, [uint64|Ts], Offset) -> - X = hd(Xs), - [?uint64(X) | enc(tl(Xs), Ts,Offset+8)]; -enc(Xs, [mpint|Ts], Offset) -> - Y = mpint(hd(Xs)), - [Y | enc(tl(Xs), Ts,Offset+size(Y))]; -enc(Xs, [string|Ts], Offset) -> - X0 = hd(Xs), - Y = ?string(X0), - [Y | enc(tl(Xs),Ts,Offset+size(Y))]; -enc(Xs, [string_utf8|Ts], Offset) -> - X0 = hd(Xs), - Y = ?string_utf8(X0), - [Y | enc(tl(Xs),Ts,Offset+size(Y))]; -enc(Xs, [binary|Ts], Offset) -> - X0 = hd(Xs), - Y = ?binary(X0), - [Y | enc(tl(Xs), Ts,Offset+size(Y))]; -enc(Xs, [name_list|Ts], Offset) -> - X0 = hd(Xs), - Y = ?name_list(X0), - [Y | enc(tl(Xs), Ts, Offset+size(Y))]; -enc(Xs, [cookie|Ts], Offset) -> - [random(16) | enc(tl(Xs), Ts, Offset+16)]; -enc(Xs, [{pad,N}|Ts], Offset) -> - K = (N - (Offset rem N)) rem N, - [fill_bits(K,0) | enc(Xs, Ts, Offset+K)]; -enc(Xs, ['...'| []], _Offset) -> - X = hd(Xs), - if is_binary(X) -> - [X]; - is_list(X) -> - [list_to_binary(X)]; - X==undefined -> - [] - end; -enc([], [],_) -> - []. - - -%% -%% Create a binary with constant bytes -%% -fill_bits(N,C) -> - list_to_binary(fill(N,C)). - -fill(0,_C) -> []; -fill(1,C) -> [C]; -fill(N,C) -> - Cs = fill(N div 2, C), - Cs1 = [Cs,Cs], - if N band 1 == 0 -> - Cs1; - true -> - [C,Cs,Cs] - end. - - +%%%---------------------------------------------------------------- %% random/1 %% Generate N random bytes %% -random(N) -> - crypto:strong_rand_bytes(N). +random(N) -> crypto:strong_rand_bytes(N). diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index b6c4496be2..a0e9a4961c 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -32,16 +32,44 @@ -export([encode/1, decode/1, decode_keyboard_interactive_prompts/2]). +-define('2bin'(X), (if is_binary(X) -> X; + is_list(X) -> list_to_binary(X); + X==undefined -> <<>> + end) ). + +-define('E...'(X), ?'2bin'(X)/binary ). +-define(Eboolean(X), ?BOOLEAN(case X of + true -> ?TRUE; + false -> ?FALSE + end) ). +-define(Ebyte(X), ?BYTE(X) ). +-define(Euint32(X), ?UINT32(X) ). +-define(Estring(X), ?STRING(?'2bin'(X)) ). +-define(Estring_utf8(X), ?string_utf8(X)/binary ). +-define(Ename_list(X), ?STRING(ssh_bits:name_list(X)) ). +-define(Empint(X), (ssh_bits:mpint(X))/binary ). +-define(Ebinary(X), ?STRING(X) ). + +%% encode(Msg) -> +%% try encode1(Msg) +%% catch +%% C:E -> +%% io:format('***********************~n~p:~p ~p~n',[C,E,Msg]), +%% error(E) +%% end. + encode(#ssh_msg_global_request{ name = Name, want_reply = Bool, data = Data}) -> - ssh_bits:encode([?SSH_MSG_GLOBAL_REQUEST, - Name, Bool, Data], [byte, string, boolean, '...']); + <>; + encode(#ssh_msg_request_success{data = Data}) -> - <>; + <>; + encode(#ssh_msg_request_failure{}) -> - <>; + <>; + encode(#ssh_msg_channel_open{ channel_type = Type, sender_channel = Sender, @@ -49,9 +77,8 @@ encode(#ssh_msg_channel_open{ maximum_packet_size = Max, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN, - Type, Sender, Window, Max, Data], [byte, string, uint32, - uint32, uint32, '...']); + <>; + encode(#ssh_msg_channel_open_confirmation{ recipient_channel = Recipient, sender_channel = Sender, @@ -59,60 +86,63 @@ encode(#ssh_msg_channel_open_confirmation{ maximum_packet_size = MaxPacketSize, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN_CONFIRMATION, Recipient, - Sender, InitWindowSize, MaxPacketSize, Data], - [byte, uint32, uint32, uint32, uint32, '...']); + <>; + encode(#ssh_msg_channel_open_failure{ recipient_channel = Recipient, reason = Reason, description = Desc, lang = Lang }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN_FAILURE, Recipient, - Reason, Desc, Lang], [byte, uint32, uint32, string, string]); + <>; + encode(#ssh_msg_channel_window_adjust{ recipient_channel = Recipient, bytes_to_add = Bytes }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_WINDOW_ADJUST, Recipient, Bytes], - [byte, uint32, uint32]); + <>; + encode(#ssh_msg_channel_data{ recipient_channel = Recipient, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_DATA, Recipient, Data], [byte, uint32, binary]); + <>; encode(#ssh_msg_channel_extended_data{ recipient_channel = Recipient, data_type_code = DataType, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_EXTENDED_DATA, Recipient, - DataType, Data], [byte, uint32, uint32, binary]); + <>; encode(#ssh_msg_channel_eof{recipient_channel = Recipient }) -> - <>; + <>; + encode(#ssh_msg_channel_close{ recipient_channel = Recipient }) -> - <>; + <>; + encode(#ssh_msg_channel_request{ recipient_channel = Recipient, request_type = Type, want_reply = Bool, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_REQUEST, Recipient, Type, Bool, Data], - [byte, uint32, string, boolean, '...']); + <>; + encode(#ssh_msg_channel_success{ recipient_channel = Recipient }) -> - <>; + <>; + encode(#ssh_msg_channel_failure{ recipient_channel = Recipient }) -> - <>; + <>; encode(#ssh_msg_userauth_request{ user = User, @@ -120,36 +150,33 @@ encode(#ssh_msg_userauth_request{ method = Method, data = Data }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_REQUEST, User, Service, Method, Data], - [byte, string_utf8, string, string, '...']); + <>; + encode(#ssh_msg_userauth_failure{ authentications = Auths, partial_success = Bool }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_FAILURE, Auths, Bool], - [byte, string, boolean]); + <>; + encode(#ssh_msg_userauth_success{}) -> - <>; + <>; encode(#ssh_msg_userauth_banner{ message = Banner, language = Lang }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_BANNER, Banner, Lang], - [byte, string_utf8, string]); + <>; encode(#ssh_msg_userauth_pk_ok{ algorithm_name = Alg, key_blob = KeyBlob }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_PK_OK, Alg, KeyBlob], - [byte, string, binary]); + <>; encode(#ssh_msg_userauth_passwd_changereq{prompt = Prompt, languge = Lang })-> - ssh_bits:encode([?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, Prompt, Lang], - [byte, string, string]); + <>; encode(#ssh_msg_userauth_info_request{ name = Name, @@ -157,41 +184,37 @@ encode(#ssh_msg_userauth_info_request{ language_tag = Lang, num_prompts = NumPromtps, data = Data}) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_INFO_REQUEST, Name, Inst, Lang, NumPromtps, Data], - [byte, string, string, string, uint32, '...']); + <>; encode(#ssh_msg_userauth_info_response{ num_responses = Num, data = Data}) -> - Responses = lists:map(fun("") -> - <<>>; - (Response) -> - ssh_bits:encode([Response], [string]) - end, Data), - Start = ssh_bits:encode([?SSH_MSG_USERAUTH_INFO_RESPONSE, Num], - [byte, uint32]), - iolist_to_binary([Start, Responses]); + lists:foldl(fun %%("", Acc) -> Acc; % commented out since it seem wrong + (Response, Acc) -> <> + end, + <>, + Data); encode(#ssh_msg_disconnect{ code = Code, description = Desc, language = Lang }) -> - ssh_bits:encode([?SSH_MSG_DISCONNECT, Code, Desc, Lang], - [byte, uint32, string, string]); + <>; encode(#ssh_msg_service_request{ name = Service }) -> - ssh_bits:encode([?SSH_MSG_SERVICE_REQUEST, Service], [byte, string]); + <>; encode(#ssh_msg_service_accept{ name = Service }) -> - ssh_bits:encode([?SSH_MSG_SERVICE_ACCEPT, Service], [byte, string]); + <>; encode(#ssh_msg_newkeys{}) -> - <>; + <>; encode(#ssh_msg_kexinit{ cookie = Cookie, @@ -208,19 +231,13 @@ encode(#ssh_msg_kexinit{ first_kex_packet_follows = Bool, reserved = Reserved }) -> - ssh_bits:encode([?SSH_MSG_KEXINIT, Cookie, KeyAlgs, HostKeyAlgs, EncAlgC2S, EncAlgS2C, - MacAlgC2S, MacAlgS2C, CompAlgS2C, CompAlgC2S, LangC2S, LangS2C, Bool, - Reserved], - [byte, cookie, - name_list, name_list, - name_list, name_list, - name_list, name_list, - name_list, name_list, - name_list, name_list, - boolean, uint32]); + <>; encode(#ssh_msg_kexdh_init{e = E}) -> - ssh_bits:encode([?SSH_MSG_KEXDH_INIT, E], [byte, mpint]); + <>; encode(#ssh_msg_kexdh_reply{ public_host_key = Key, @@ -229,25 +246,23 @@ encode(#ssh_msg_kexdh_reply{ }) -> EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Signature), - ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); + <>; encode(#ssh_msg_kex_dh_gex_request{ min = Min, n = N, max = Max }) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST, Min, N, Max], - [byte, uint32, uint32, uint32]); + <>; + encode(#ssh_msg_kex_dh_gex_request_old{n = N}) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST_OLD, N], - [byte, uint32]); + <>; encode(#ssh_msg_kex_dh_gex_group{p = Prime, g = Generator}) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_GROUP, Prime, Generator], - [byte, mpint, mpint]); + <>; encode(#ssh_msg_kex_dh_gex_init{e = Public}) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_INIT, Public], [byte, mpint]); + <>; encode(#ssh_msg_kex_dh_gex_reply{ %% Will be private key encode_host_key extracts only the public part! @@ -257,26 +272,26 @@ encode(#ssh_msg_kex_dh_gex_reply{ }) -> EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Signature), - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); + <>; encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) -> - ssh_bits:encode([?SSH_MSG_KEX_ECDH_INIT, Q_c], [byte, mpint]); + <>; encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) -> EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Sign), - ssh_bits:encode([?SSH_MSG_KEX_ECDH_REPLY, EncKey, Q_s, EncSign], [byte, binary, mpint, binary]); + <>; encode(#ssh_msg_ignore{data = Data}) -> - ssh_bits:encode([?SSH_MSG_IGNORE, Data], [byte, string]); + <>; encode(#ssh_msg_unimplemented{sequence = Seq}) -> - ssh_bits:encode([?SSH_MSG_UNIMPLEMENTED, Seq], [byte, uint32]); + <>; encode(#ssh_msg_debug{always_display = Bool, message = Msg, language = Lang}) -> - ssh_bits:encode([?SSH_MSG_DEBUG, Bool, Msg, Lang], [byte, boolean, string, string]). + <>. %% Connection Messages @@ -553,10 +568,10 @@ decode_signature(<>) -> encode_signature(#'RSAPublicKey'{}, Signature) -> - ssh_bits:encode(["ssh-rsa", Signature],[string, binary]); + <>), ?Ebinary(Signature)>>; encode_signature({_, #'Dss-Parms'{}}, Signature) -> - ssh_bits:encode(["ssh-dss", Signature],[string, binary]); + <>), ?Ebinary(Signature)>>; encode_signature({#'ECPoint'{}, {namedCurve,OID}}, Signature) -> CurveName = public_key:oid2ssh_curvename(OID), - ssh_bits:encode([<<"ecdsa-sha2-",CurveName/binary>>, Signature], [binary,binary]). + <>), ?Ebinary(Signature)>>. diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 18037b8461..a648c7af3d 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -52,6 +52,14 @@ -export([pack/3]). -export([decompress/2, decrypt_blocks/3, is_valid_mac/3 ]). % FIXME: remove +-define(Estring(X), ?STRING((if is_binary(X) -> X; + is_list(X) -> list_to_binary(X); + X==undefined -> <<>> + end))). +-define(Empint(X), (ssh_bits:mpint(X))/binary ). +-define(Ebinary(X), ?STRING(X) ). +-define(Euint32(X), ?UINT32(X) ). + %%%---------------------------------------------------------------------------- %%% %%% There is a difference between supported and default algorithms. The @@ -1084,7 +1092,7 @@ sign(SigData, Hash, #'DSAPrivateKey'{} = Key) -> sign(SigData, Hash, Key = #'ECPrivateKey'{}) -> DerEncodedSign = public_key:sign(SigData, Hash, Key), #'ECDSA-Sig-Value'{r=R, s=S} = public_key:der_decode('ECDSA-Sig-Value', DerEncodedSign), - ssh_bits:encode([R,S], [mpint,mpint]); + <>; sign(SigData, Hash, Key) -> public_key:sign(SigData, Hash, Key). @@ -1584,21 +1592,16 @@ hash(K, H, Ki, N, HASH) -> kex_h(SSH, Key, E, F, K) -> KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), - L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version, - SSH#ssh.c_keyinit, SSH#ssh.s_keyinit, - KeyBin, E,F,K], - [string,string,binary,binary,binary, - mpint,mpint,mpint]), + L = <>, crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). -%% crypto:hash(sha,L). kex_h(SSH, Curve, Key, Q_c, Q_s, K) -> KeyBin = public_key:ssh_encode(Key, ssh2_pubkey), - L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version, - SSH#ssh.c_keyinit, SSH#ssh.s_keyinit, - KeyBin, Q_c, Q_s, K], - [string,string,binary,binary,binary, - mpint,mpint,mpint]), + L = <>, crypto:hash(sha(Curve), L). kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> @@ -1607,21 +1610,14 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) -> %% flag from 'ssh_msg_kex_dh_gex_request_old' %% It was like this before that message was supported, %% why? - Ts = [string,string,binary,binary,binary, - uint32, - mpint,mpint,mpint,mpint,mpint], - ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version, - SSH#ssh.c_keyinit,SSH#ssh.s_keyinit, - KeyBin, NBits, Prime, Gen, E,F,K], - Ts); + <>; true -> - Ts = [string,string,binary,binary,binary, - uint32,uint32,uint32, - mpint,mpint,mpint,mpint,mpint], - ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version, - SSH#ssh.c_keyinit,SSH#ssh.s_keyinit, - KeyBin, Min, NBits, Max, - Prime, Gen, E,F,K], Ts) + <> end, crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L). diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index fe197f8672..6b78a32a9b 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -307,7 +307,7 @@ no_common_alg_client_disconnects(Config) -> {send, hello}, {match, #ssh_msg_kexinit{_='_'}, receive_msg}, {send, #ssh_msg_kexinit{ % with unsupported "SOME-UNSUPPORTED" - cookie = 247381486335508958743193106082599558706, + cookie = <<80,158,95,51,174,35,73,130,246,141,200,49,180,190,82,234>>, kex_algorithms = ["diffie-hellman-group1-sha1"], server_host_key_algorithms = ["SOME-UNSUPPORTED"], % SIC! encryption_algorithms_client_to_server = ["aes128-ctr"], -- cgit v1.2.3 From 1bb8e4ae6eaf2f18d3b2ccc8e77cd7228e1c6e8a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 14 Jan 2016 10:39:17 +0100 Subject: ssh: Experimental options for ssh_sftp:start_channel to set packet_size or window_size --- lib/ssh/src/ssh_sftp.erl | 28 ++++++++++++++++------------ lib/ssh/src/ssh_xfer.erl | 22 ++++++++++++++++------ 2 files changed, 32 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl index dbacf730cc..eb99406626 100644 --- a/lib/ssh/src/ssh_sftp.erl +++ b/lib/ssh/src/ssh_sftp.erl @@ -99,8 +99,8 @@ start_channel(Host) when is_list(Host) -> start_channel(Host, []). start_channel(Cm, Opts) when is_pid(Cm) -> Timeout = proplists:get_value(timeout, Opts, infinity), - {_, SftpOpts} = handle_options(Opts, [], []), - case ssh_xfer:attach(Cm, []) of + {_, ChanOpts, SftpOpts} = handle_options(Opts, [], [], []), + case ssh_xfer:attach(Cm, [], ChanOpts) of {ok, ChannelId, Cm} -> case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm, ChannelId, SftpOpts]) of @@ -123,9 +123,9 @@ start_channel(Cm, Opts) when is_pid(Cm) -> start_channel(Host, Opts) -> start_channel(Host, 22, Opts). start_channel(Host, Port, Opts) -> - {SshOpts, SftpOpts} = handle_options(Opts, [], []), + {SshOpts, ChanOpts, SftpOpts} = handle_options(Opts, [], [], []), Timeout = proplists:get_value(timeout, SftpOpts, infinity), - case ssh_xfer:connect(Host, Port, SshOpts, Timeout) of + case ssh_xfer:connect(Host, Port, SshOpts, ChanOpts, Timeout) of {ok, ChannelId, Cm} -> case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm, ChannelId, SftpOpts]) of @@ -842,14 +842,18 @@ terminate(_Reason, State) -> %%==================================================================== %% Internal functions %%==================================================================== -handle_options([], Sftp, Ssh) -> - {Ssh, Sftp}; -handle_options([{timeout, _} = Opt | Rest], Sftp, Ssh) -> - handle_options(Rest, [Opt | Sftp], Ssh); -handle_options([{sftp_vsn, _} = Opt| Rest], Sftp, Ssh) -> - handle_options(Rest, [Opt | Sftp], Ssh); -handle_options([Opt | Rest], Sftp, Ssh) -> - handle_options(Rest, Sftp, [Opt | Ssh]). +handle_options([], Sftp, Chan, Ssh) -> + {Ssh, Chan, Sftp}; +handle_options([{timeout, _} = Opt | Rest], Sftp, Chan, Ssh) -> + handle_options(Rest, [Opt|Sftp], Chan, Ssh); +handle_options([{sftp_vsn, _} = Opt| Rest], Sftp, Chan, Ssh) -> + handle_options(Rest, [Opt|Sftp], Chan, Ssh); +handle_options([{window_size, _} = Opt| Rest], Sftp, Chan, Ssh) -> + handle_options(Rest, Sftp, [Opt|Chan], Ssh); +handle_options([{packet_size, _} = Opt| Rest], Sftp, Chan, Ssh) -> + handle_options(Rest, Sftp, [Opt|Chan], Ssh); +handle_options([Opt|Rest], Sftp, Chan, Ssh) -> + handle_options(Rest, Sftp, Chan, [Opt|Ssh]). call(Pid, Msg, TimeOut) -> ssh_channel:call(Pid, {{timeout, TimeOut}, Msg}, infinity). diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl index b8dff1c533..e7dd8e7098 100644 --- a/lib/ssh/src/ssh_xfer.erl +++ b/lib/ssh/src/ssh_xfer.erl @@ -24,7 +24,7 @@ -module(ssh_xfer). --export([attach/2, connect/3, connect/4]). +-export([attach/2, attach/3, connect/3, connect/4, connect/5]). -export([open/6, opendir/3, readdir/3, close/3, read/5, write/5, rename/5, remove/3, mkdir/4, rmdir/3, realpath/3, extended/4, stat/4, fstat/4, lstat/4, setstat/4, @@ -51,24 +51,34 @@ -define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE). attach(CM, Opts) -> - open_xfer(CM, Opts). + open_xfer(CM, Opts, []). + +attach(CM, Opts, ChanOpts) -> + open_xfer(CM, Opts, ChanOpts). + connect(Host, Port, Opts) -> case ssh:connect(Host, Port, Opts) of - {ok, CM} -> open_xfer(CM, Opts); + {ok, CM} -> open_xfer(CM, Opts, []); Error -> Error end. connect(Host, Port, Opts, Timeout) -> + connect(Host, Port, Opts, [], Timeout). + +connect(Host, Port, Opts, ChanOpts, Timeout) -> case ssh:connect(Host, Port, Opts, Timeout) of - {ok, CM} -> open_xfer(CM, [{timeout, Timeout}|Opts]); + {ok, CM} -> open_xfer(CM, [{timeout, Timeout}|Opts], ChanOpts); {error, Timeout} -> {error, timeout}; Error -> Error end. -open_xfer(CM, Opts) -> + +open_xfer(CM, Opts, ChanOpts) -> TMO = proplists:get_value(timeout, Opts, infinity), - case ssh_connection:session_channel(CM, ?XFER_WINDOW_SIZE, ?XFER_PACKET_SIZE, TMO) of + WindowSize = proplists:get_value(window_size, ChanOpts, ?XFER_WINDOW_SIZE), + PacketSize = proplists:get_value(packet_size, ChanOpts, ?XFER_PACKET_SIZE), + case ssh_connection:session_channel(CM, WindowSize, PacketSize, TMO) of {ok, ChannelId} -> {ok, ChannelId, CM}; Error -> -- cgit v1.2.3 From 8abcda0fa16bb06db5020f5dcd22e09aa37f412a Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Fri, 15 Jan 2016 17:57:28 +0100 Subject: ssh: Adjusted default packet and window sizes --- lib/ssh/src/ssh_connect.hrl | 5 +++-- lib/ssh/src/ssh_xfer.erl | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl index 9f9f3de8fa..0c9ddad641 100644 --- a/lib/ssh/src/ssh_connect.hrl +++ b/lib/ssh/src/ssh_connect.hrl @@ -24,8 +24,9 @@ -type channel_id() :: integer(). --define(DEFAULT_PACKET_SIZE, 32768). --define(DEFAULT_WINDOW_SIZE, 2*?DEFAULT_PACKET_SIZE). +-define(DEFAULT_PACKET_SIZE, 65536). +-define(DEFAULT_WINDOW_SIZE, 10*?DEFAULT_PACKET_SIZE). + -define(DEFAULT_TIMEOUT, 5000). -define(MAX_PROTO_VERSION, 255). diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl index e7dd8e7098..259dc71aa5 100644 --- a/lib/ssh/src/ssh_xfer.erl +++ b/lib/ssh/src/ssh_xfer.erl @@ -47,8 +47,8 @@ -define(is_set(F, Bits), ((F) band (Bits)) == (F)). --define(XFER_PACKET_SIZE, 32768). --define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE). +-define(XFER_PACKET_SIZE, 65536). +-define(XFER_WINDOW_SIZE, 20*?XFER_PACKET_SIZE). attach(CM, Opts) -> open_xfer(CM, Opts, []). -- cgit v1.2.3 From f1e687312daa91591a2cee5038a2d9434e7db209 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 11 Dec 2015 12:04:56 +0100 Subject: stdlib: Correct a type --- lib/stdlib/src/io.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl index 5dc8b4541e..f510f61e9f 100644 --- a/lib/stdlib/src/io.erl +++ b/lib/stdlib/src/io.erl @@ -444,7 +444,7 @@ scan_erl_form(Io, Prompt, Pos0, Options) -> %% Parsing Erlang code. -type parse_ret() :: {'ok', - ExprList :: erl_parse:abstract_expr(), + ExprList :: [erl_parse:abstract_expr()], EndLocation :: location()} | {'eof', EndLocation :: location()} | {'error', -- cgit v1.2.3 From 2bf8c4726dfdf94bd6c190f1236c33a064238e02 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 11 Dec 2015 12:00:36 +0100 Subject: syntax_tools: Correct a type --- lib/syntax_tools/src/erl_recomment.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/syntax_tools/src/erl_recomment.erl b/lib/syntax_tools/src/erl_recomment.erl index 72e1e2d2f5..5ce533285d 100644 --- a/lib/syntax_tools/src/erl_recomment.erl +++ b/lib/syntax_tools/src/erl_recomment.erl @@ -611,12 +611,15 @@ expand_comment(C) -> attrs :: erl_syntax:syntaxTreeAttributes(), precomments = [] :: [erl_syntax:syntaxTree()], postcomments = [] :: [erl_syntax:syntaxTree()], - subtrees = [] :: [erl_syntax:syntaxTree()]}). + subtrees = [] :: [extendedSyntaxTree()]}). + -record(list, {min = 0 :: integer(), max = 0 :: integer(), subtrees = [] :: [erl_syntax:syntaxTree()]}). +-type extendedSyntaxTree() :: #tree{} | #leaf{} | #list{}. + leaf_node(Min, Max, Value) -> #leaf{min = Min, max = Max, -- cgit v1.2.3 From 3bd648f66080d1074533ba18fece0ea7de568d45 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 17 Dec 2015 12:09:24 +0100 Subject: dialyzer: Improve a type --- lib/dialyzer/src/dialyzer_utils.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index 7fe982a992..557e10eed7 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -83,7 +83,7 @@ print_types1([{record, _Name} = Key|T], RecDict) -> %% ---------------------------------------------------------------------------- --type abstract_code() :: [tuple()]. %% XXX: import from somewhere +-type abstract_code() :: [erl_parse:abstract_form()]. -type comp_options() :: [compile:option()]. -type mod_or_fname() :: module() | file:filename(). -type fa() :: {atom(), arity()}. -- cgit v1.2.3 From 034e28c340d38a34c0e00590321380c407ff5faf Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 17 Dec 2015 12:29:51 +0100 Subject: hipe: Improve types --- lib/hipe/cerl/erl_types.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 67cdcd35e3..69654088d5 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -316,7 +316,7 @@ %% Auxiliary types and convenient macros %% --type parse_form() :: {atom(), _, _} | {atom(), _, _, _} | {'op', _, _, _, _}. %% XXX: Temporarily +-type parse_form() :: erl_parse:abstract_expr(). -type rng_elem() :: 'pos_inf' | 'neg_inf' | integer(). -record(int_set, {set :: [integer()]}). @@ -365,8 +365,8 @@ -type type_key() :: {'type' | 'opaque', atom(), arity()}. -type record_value() :: [{atom(), erl_parse:abstract_expr(), erl_type()}]. -type type_value() :: {module(), erl_type(), atom()}. --type type_table() :: dict:dict(record_key(), record_value()) - | dict:dict(type_key(), type_value()). +-type type_table() :: dict:dict(record_key() | type_key(), + record_value() | type_value()). -type var_table() :: dict:dict(atom(), erl_type()). -- cgit v1.2.3 From 130eb1e9f3af384f13c38e93365c5917f25fd798 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 17 Dec 2015 15:49:33 +0100 Subject: compiler: Improve type and specs --- lib/compiler/src/compile.erl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index b61c104b3c..72f1a767ed 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -40,6 +40,8 @@ %%---------------------------------------------------------------------- +-type abstract_code() :: [erl_parse:abstract_form()]. + -type option() :: atom() | {atom(), term()} | {'d', atom(), term()}. -type err_info() :: {erl_anno:line() | 'none', @@ -48,6 +50,9 @@ -type warnings() :: [{file:filename(), [err_info()]}]. -type mod_ret() :: {'ok', module()} | {'ok', module(), cerl:c_module()} %% with option 'to_core' + | {'ok', %% with option 'to_pp' + module() | [], %% module() if 'to_exp' + abstract_code()} | {'ok', module(), warnings()}. -type bin_ret() :: {'ok', module(), binary()} | {'ok', module(), binary(), warnings()}. @@ -78,7 +83,11 @@ file(File, Opts) when is_list(Opts) -> file(File, Opt) -> file(File, [Opt|?DEFAULT_OPTIONS]). -forms(File) -> forms(File, ?DEFAULT_OPTIONS). +-spec forms(abstract_code()) -> comp_ret(). + +forms(Forms) -> forms(Forms, ?DEFAULT_OPTIONS). + +-spec forms(abstract_code(), [option()] | option()) -> comp_ret(). forms(Forms, Opts) when is_list(Opts) -> do_compile({forms,Forms}, [binary|Opts++env_default_opts()]); @@ -106,6 +115,8 @@ noenv_file(File, Opts) when is_list(Opts) -> noenv_file(File, Opt) -> noenv_file(File, [Opt|?DEFAULT_OPTIONS]). +-spec noenv_forms(abstract_code(), [option()] | option()) -> comp_ret(). + noenv_forms(Forms, Opts) when is_list(Opts) -> do_compile({forms,Forms}, [binary|Opts]); noenv_forms(Forms, Opt) when is_atom(Opt) -> -- cgit v1.2.3 From c92ec9ea35209d443c2fb6393a1610f94ffccc1c Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 17 Dec 2015 12:40:43 +0100 Subject: stdlib: Refine the types of the abstract format --- lib/stdlib/src/erl_parse.yrl | 414 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 410 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index e07ab2efc2..a525c2ae82 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -527,12 +527,418 @@ Erlang code. -compile([{hipe,[{regalloc,linear_scan}]}]). -export_type([abstract_clause/0, abstract_expr/0, abstract_form/0, - error_info/0]). + abstract_type/0, error_info/0]). + +%% Start of Abstract Format + +-type anno() :: erl_anno:anno(). + +-type abstract_form() :: af_module() + | af_behavior() + | af_behaviour() + | af_export() + | af_import() + | af_export_type() + | af_optional_callbacks() + | af_compile() + | af_file() + | af_record_decl() + | af_type_decl() + | af_function_spec() + | af_wild_attribute() + | af_function_decl(). + +-type af_module() :: {'attribute', anno(), 'module', module()}. + +-type af_behavior() :: {'attribute', anno(), 'behavior', behaviour()}. + +-type af_behaviour() :: {'attribute', anno(), 'behaviour', behaviour()}. + +-type behaviour() :: atom(). + +-type af_export() :: {'attribute', anno(), 'export', af_fa_list()}. + +-type af_import() :: {'attribute', anno(), 'import', af_fa_list()}. + +-type af_fa_list() :: [{function_name(), arity()}]. + +-type af_export_type() :: {'attribute', anno(), 'export_type', af_ta_list()}. + +-type af_ta_list() :: [{type_name(), arity()}]. + +-type af_optional_callbacks() :: + {'attribute', anno(), 'optional_callbacks', af_fa_list()}. + +-type af_compile() :: {'attribute', anno(), 'compile', any()}. + +-type af_file() :: {'attribute', anno(), 'file', {string(), anno()}}. + +-type af_record_decl() :: + {'attribute', anno(), 'record', {record_name(), [af_field_decl()]}}. + +-type af_field_decl() :: af_typed_field() | af_field(). + +-type af_typed_field() :: + {'typed_record_field', af_field(), abstract_type()}. + +-type af_field() :: {'record_field', anno(), af_field_name()} + | {'record_field', anno(), af_field_name(), abstract_expr()}. + +-type af_type_decl() :: {'attribute', anno(), type_attr(), + {type_name(), abstract_type(), [af_variable()]}}. + +-type type_attr() :: 'opaque' | 'type'. + +-type af_function_spec() :: {'attribute', anno(), spec_attr(), + {{function_name(), arity()}, + af_function_type_list()}} + | {'attribute', anno(), 'spec', + {{module(), function_name(), arity()}, + af_function_type_list()}}. + +-type spec_attr() :: 'callback' | 'spec'. + +-type af_wild_attribute() :: {'attribute', anno(), atom(), any()}. + +-type af_function_decl() :: + {'function', anno(), function_name(), arity(), af_clause_seq()}. + +-type abstract_expr() :: af_literal() + | af_match(abstract_expr()) + | af_variable() + | af_tuple(abstract_expr()) + | af_nil() + | af_cons(abstract_expr()) + | af_bin(abstract_expr()) + | af_binary_op(abstract_expr()) + | af_unary_op(abstract_expr()) + | af_record_access(abstract_expr()) + | af_record_update(abstract_expr()) + | af_record_index() + | af_record_field_access(abstract_expr()) + | af_map_access(abstract_expr()) + | af_map_update(abstract_expr()) + | af_catch() + | af_local_call() + | af_remote_call() + | af_list_comprehension() + | af_binary_comprehension() + | af_block() + | af_if() + | af_case() + | af_try() + | af_receive() + | af_local_fun() + | af_remote_fun() + | af_fun() + | af_named_fun(). + +-type af_record_update(T) :: {'record', + anno(), + abstract_expr(), + record_name(), + [af_record_field(T)]}. + +-type af_catch() :: {'catch', anno(), abstract_expr()}. + +-type af_local_call() :: {'call', anno(), af_local_function(), af_args()}. + +-type af_remote_call() :: {'call', anno(), af_remote_function(), af_args()}. + +-type af_args() :: [abstract_expr()]. + +-type af_local_function() :: abstract_expr(). + +-type af_remote_function() :: + {'remote', anno(), abstract_expr(), abstract_expr()}. + +-type af_list_comprehension() :: + {'lc', anno(), af_template(), af_qualifier_seq()}. + +-type af_binary_comprehension() :: + {'bc', anno(), af_template(), af_qualifier_seq()}. + +-type af_template() :: abstract_expr(). + +-type af_qualifier_seq() :: [af_qualifier()]. + +-type af_qualifier() :: af_generator() | af_filter(). + +-type af_generator() :: {'generate', anno(), af_pattern(), abstract_expr()} + | {'b_generate', anno(), af_pattern(), abstract_expr()}. + +-type af_filter() :: abstract_expr(). + +-type af_block() :: {'block', anno(), af_body()}. + +-type af_if() :: {'if', anno(), af_clause_seq()}. + +-type af_case() :: {'case', anno(), abstract_expr(), af_clause_seq()}. + +-type af_try() :: {'try', + anno(), + af_body() | [], + af_clause_seq() | [], + af_clause_seq() | [], + af_body() | []}. + +-type af_clause_seq() :: [af_clause(), ...]. + +-type af_receive() :: + {'receive', anno(), af_clause_seq()} + | {'receive', anno(), af_clause_seq(), abstract_expr(), af_body()}. + +-type af_local_fun() :: + {'fun', anno(), {'function', function_name(), arity()}}. + +-type af_remote_fun() :: + {'fun', anno(), {'function', module(), function_name(), arity()}} + | {'fun', anno(), {'function', af_atom(), af_atom(), af_integer()}}. + +-type af_fun() :: {'fun', anno(), {'clauses', af_clause_seq()}}. + +-type af_named_fun() :: {'named_fun', anno(), fun_name(), af_clause_seq()}. + +-type fun_name() :: atom(). + +-type abstract_clause() :: af_clause(). + +-type af_clause() :: + {'clause', anno(), [af_pattern()], af_guard_seq(), af_body()}. + +-type af_body() :: [abstract_expr(), ...]. + +-type af_guard_seq() :: [af_guard()]. + +-type af_guard() :: [af_guard_test(), ...]. + +-type af_guard_test() :: af_literal() + | af_variable() + | af_tuple(af_guard_test()) + | af_nil() + | af_cons(af_guard_test()) + | af_bin(af_guard_test()) + | af_binary_op(af_guard_test()) + | af_unary_op(af_guard_test()) + | af_record_access(af_guard_test()) + | af_record_index() + | af_record_field_access(af_guard_test()) + | af_map_access(abstract_expr()) % FIXME + | af_map_update(abstract_expr()) % FIXME + | af_guard_call() + | af_remote_guard_call(). + +-type af_record_field_access(T) :: + {'record_field', anno(), T, record_name(), af_field_name()}. + +-type af_map_access(T) :: {'map', anno(), [af_map_field(T)]}. + +-type af_map_update(T) :: {'map', anno(), T, [af_map_field(T)]}. + +-type af_map_field(T) :: af_map_field_assoc(T) | af_map_field_exact(T). + +-type af_map_field_assoc(T) :: {'map_field_assoc', anno(), T, T}. + +-type af_map_field_exact(T) :: {'map_field_exact', anno(), T, T}. + +-type af_guard_call() :: {'call', anno(), function_name(), [af_guard_test()]}. + +-type af_remote_guard_call() :: + {'call', anno(), + {'remote', anno(), af_lit_atom('erlang'), af_atom()}, + [af_guard_test()]}. + +-type af_pattern() :: af_literal() + | af_match(af_pattern()) + | af_variable() + | af_tuple(af_pattern()) + | af_nil() + | af_cons(af_pattern()) + | af_bin(af_pattern()) + | af_binary_op(af_pattern()) + | af_unary_op(af_pattern()) + | af_record_access(af_pattern()) + | af_record_index() + | af_map_pattern(). + +-type af_record_index() :: + {'record_index', anno(), record_name(), af_field_name()}. + +-type af_record_access(T) :: + {'record', anno(), record_name(), [af_record_field(T)]}. + +-type af_record_field(T) :: {'record_field', anno(), af_field_name(), T}. + +-type af_map_pattern() :: + {'map', anno(), [af_map_field_exact(abstract_expr)]}. % FIXME? + +-type abstract_type() :: af_annotated_type() + | af_atom() + | af_bitstring_type() + | af_empty_list_type() + | af_fun_type() + | af_integer_range_type() + | af_map_type() + | af_predefined_type() + | af_record_type() + | af_remote_type() + | af_singleton_integer_type() + | af_tuple_type() + | af_type_union() + | af_type_variable() + | af_user_defined_type(). + +-type af_annotated_type() :: + {'ann_type', anno(), [af_anno() | abstract_type()]}. % [Var, Type] + +-type af_anno() :: af_variable(). + +-type af_bitstring_type() :: + {'type', anno(), 'binary', [af_singleton_integer_type()]}. + +-type af_empty_list_type() :: {'type', anno(), 'nil', []}. + +-type af_fun_type() :: {'type', anno(), 'fun', []} + | {'type', anno(), 'fun', [{'type', anno(), 'any'} | + abstract_type()]} + | {'type', anno(), 'fun', af_function_type()}. + +-type af_integer_range_type() :: + {'type', anno(), 'range', [af_singleton_integer_type()]}. + +-type af_map_type() :: {'type', anno(), 'map', 'any'} + | {'type', anno(), 'map', [af_map_pair_type()]}. + +-type af_map_pair_type() :: + {'type', anno(), 'map_field_assoc', [abstract_type()]}. + +-type af_predefined_type() :: + {'type', anno(), type_name(), [abstract_type()]}. + +-type af_record_type() :: + {'type', anno(), 'record', [(Name :: af_atom()) % [Name, T1, ... Tk] + | af_record_field_type()]}. + +-type af_record_field_type() :: + {'type', anno(), 'field_type', [(Name :: af_atom()) | + abstract_type()]}. % [Name, Type] + +-type af_remote_type() :: + {'remote_type', anno(), [(Module :: af_atom()) | + (TypeName :: af_atom()) | + [abstract_type()]]}. % [Module, Name, [T]] + +-type af_tuple_type() :: {'type', anno(), 'tuple', 'any'} + | {'type', anno(), 'tuple', [abstract_type()]}. + +-type af_type_union() :: {'type', anno(), 'union', [abstract_type()]}. + +-type af_type_variable() :: {'var', anno(), atom()}. % except '_' + +-type af_user_defined_type() :: + {'user_type', anno(), type_name(), [abstract_type()]}. + +-type af_function_type_list() :: [af_constrained_function_type() | + af_function_type()]. + +-type af_constrained_function_type() :: + {'type', anno(), 'bounded_fun', [af_function_type() | % [Ft, Fc] + af_function_constraint()]}. + +-type af_function_type() :: + {'type', anno(), 'fun', + [{'type', anno(), 'product', [abstract_type()]} | abstract_type()]}. + +-type af_function_constraint() :: [af_constraint()]. + +-type af_constraint() :: {'type', anno(), 'constraint', + af_lit_atom('is_subtype'), + [af_type_variable() | abstract_type()]}. % [V, T] + +-type af_singleton_integer_type() :: af_integer() + | af_unary_op(af_singleton_integer_type()) + | af_binary_op(af_singleton_integer_type()). + +-type af_literal() :: af_atom() | af_integer() | af_float() | af_string(). + +-type af_atom() :: af_lit_atom(atom()). + +-type af_lit_atom(A) :: {'atom', anno(), A}. + +-type af_integer() :: {'integer', anno(), non_neg_integer()}. + +-type af_float() :: {'float', anno(), float()}. + +-type af_string() :: {'string', anno(), string()}. + +-type af_match(T) :: {'match', anno(), af_pattern(), T}. + +-type af_variable() :: {'var', anno(), atom()}. % | af_anon_variable() + +%-type af_anon_variable() :: {'var', anno(), '_'}. + +-type af_tuple(T) :: {'tuple', anno(), [T]}. + +-type af_nil() :: {'nil', anno()}. + +-type af_cons(T) :: {'cons', anno(), T, T}. + +-type af_bin(T) :: {'bin', anno(), [af_binelement(T)]}. + +-type af_binelement(T) :: {'bin_element', + anno(), + T, + af_binelement_size(), + type_specifier_list()}. + +-type af_binelement_size() :: 'default' | abstract_expr(). + +-type af_binary_op(T) :: {'op', anno(), binary_op(), T, T}. + +-type binary_op() :: '/' | '*' | 'div' | 'rem' | 'band' | 'and' | '+' | '-' + | 'bor' | 'bxor' | 'bsl' | 'bsr' | 'or' | 'xor' | '++' + | '--' | '==' | '/=' | '=<' | '<' | '>=' | '>' | '=:=' + | '=/='. + +-type af_unary_op(T) :: {'op', anno(), unary_op(), T}. + +-type unary_op() :: '+' | '*' | 'bnot' | 'not'. + +%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}. +-type type_specifier_list() :: 'default' | [type_specifier(), ...]. + +-type type_specifier() :: type() + | signedness() + | endianness() + | unit(). + +-type type() :: 'integer' + | 'float' + | 'binary' + | 'bytes' + | 'bitstring' + | 'bits' + | 'utf8' + | 'utf16' + | 'utf32'. + +-type signedness() :: 'signed' | 'unsigned'. + +-type endianness() :: 'big' | 'little' | 'native'. + +-type unit() :: {'unit', 1..256}. + +-type record_name() :: atom(). + +-type af_field_name() :: af_atom(). + +-type function_name() :: atom(). + +-type type_name() :: atom(). + +%% End of Abstract Format %% XXX. To be refined. --type abstract_clause() :: term(). --type abstract_expr() :: term(). --type abstract_form() :: term(). -type error_description() :: term(). -type error_info() :: {erl_anno:line(), module(), error_description()}. -type token() :: erl_scan:token(). -- cgit v1.2.3 From b21f71c1bb79d3979505ad6ad1e496472b38c6b9 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 17 Dec 2015 12:41:44 +0100 Subject: stdlib: Update erl_parse(3) Calls to map_anno(), fold_anno(), and mapfold_anno() with lists of erl_parse trees have been replaced. Those functions accept lists of erl_parse trees, but it was not the intention when the functions were introduced, and it is not documented. --- lib/stdlib/doc/src/erl_parse.xml | 120 ++++++++++++++++++++++++--------------- lib/stdlib/src/erl_lint.erl | 5 ++ lib/stdlib/src/erl_parse.yrl | 25 ++++---- lib/stdlib/src/qlc_pt.erl | 34 ++++++----- 4 files changed, 114 insertions(+), 70 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml index 0938b5dec3..13be488c33 100644 --- a/lib/stdlib/doc/src/erl_parse.xml +++ b/lib/stdlib/doc/src/erl_parse.xml @@ -4,7 +4,7 @@
- 19962015 + 19962016 Ericsson AB. All Rights Reserved. @@ -44,20 +44,32 @@ - -

Parse tree for Erlang clause.

+ abstract_clause() +

+ Abstract form of an Erlang clause.

- -

Parse tree for Erlang expression.

+ abstract_expr() +

+ Abstract form of an Erlang expression.

- -

Parse tree for Erlang form.

+ abstract_form() +

+ Abstract form of an Erlang form.

+ + abstract_type() +

+ Abstract form of an Erlang type.

+
+
+ + + @@ -180,7 +192,7 @@

Converts the Erlang data structure Data into an abstract form of type AbsTerm.

The Line option is the line that will - be assigned to each node of the abstract form.

+ be assigned to each node of AbsTerm.

The Encoding option is used for selecting which integer lists will be considered as strings. The default is to use the encoding returned by @@ -196,47 +208,53 @@ - Map a function over the annotations of an abstract form + Map a function over the annotations of a erl_parse tree -

Modifies the abstract form Abstr by applying - Fun on every collection of annotations of the - abstract form. The abstract form is traversed in a - depth-first, left-to-right, fashion. +

Modifies the erl_parse tree Abstr + by applying Fun on each collection of + annotations of the nodes of the erl_parse tree. The + erl_parse tree is traversed in a depth-first, + left-to-right, fashion.

- Fold a function over the annotations of an abstract form + Fold a function over the annotations of a erl_parse tree -

Updates an accumulator by applying Fun on - every collection of annotations of the abstract form - Abstr. The first call to Fun has - AccIn as argument, and the returned accumulator - AccOut is passed to the next call, and so on. - The final value of the accumulator is returned. The abstract - form is traversed in a depth-first, left-to-right, fashion. +

Updates an accumulator by applying Fun on + each collection of annotations of the erl_parse tree + Abstr. The first call to + Fun has AccIn as + argument, and the returned accumulator + AccOut is passed to the next call, and + so on. The final value of the accumulator is returned. The + erl_parse tree is traversed in a depth-first, left-to-right, + fashion.

- Map and fold a function over the annotations of an abstract form + Map and fold a function over the annotations of a + erl_parse tree -

Modifies the abstract form Abstr by applying - Fun on every collection of annotations of the - abstract form, while at the same time updating an - accumulator. The first call to Fun has - AccIn as second argument, and the returned - accumulator AccOut is passed to the next call, - and so on. The modified abstract form as well as the the - final value of the accumulator is returned. The abstract - form is traversed in a depth-first, left-to-right, fashion. +

Modifies the erl_parse tree Abstr + by applying Fun on each collection of + annotations of the nodes of the erl_parse tree, while + at the same time updating an accumulator. The first call to + Fun has AccIn as + second argument, and the returned accumulator + AccOut is passed to the next call, and + so on. The modified erl_parse tree as well as the the + final value of the accumulator are returned. The + erl_parse tree is traversed in a depth-first, + left-to-right, fashion.

@@ -246,12 +264,15 @@ Create new annotations -

Creates an abstract form from a term which has the same - structure as an abstract form, but locations where the - abstract form has annotations. For each location, erl_anno:new/1 is - called, and the annotations replace the location. +

Assumes that Term is a term with the same + structure as a erl_parse tree, but with locations where a + erl_parse tree has collections of annotations. + Returns a erl_parse tree where each location L + has been replaced by the value returned by erl_anno:new(L). + The term Term is traversed in a + depth-first, left-to-right, fashion.

@@ -261,12 +282,14 @@ Return annotations as terms -

Assumes that Term is a term with the same - structure as an abstract form, but with terms, T say, on - those places where an abstract form has annotations. Returns - an abstract form where every term T has been replaced by the - value returned by calling erl_anno:from_term(T). The - term Term is traversed in a depth-first, +

Assumes that Term is a term with the same + structure as a erl_parse tree, but with terms, + T say, where a erl_parse tree has collections + of annotations. Returns a erl_parse tree where each + term T has been replaced by the value returned by + + erl_anno:from_term(T). The term + Term is traversed in a depth-first, left-to-right, fashion.

@@ -277,10 +300,13 @@ Return the representation of annotations -

Returns a term where every collection of annotations Anno of - Abstr has been replaced by the term returned by - calling erl_anno:to_term(Anno). The abstract form is - traversed in a depth-first, left-to-right, fashion. +

Returns a term where each collection of annotations + Anno of the nodes of the erl_parse tree + Abstr has been replaced by the term + returned by + erl_anno:to_term(Anno). The + erl_parse tree is traversed in a depth-first, + left-to-right, fashion.

diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 4a42754d92..9ef4acdf5f 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -696,7 +696,12 @@ set_form_file({function,L,N,A,C}, File) -> set_form_file(Form, _File) -> Form. +set_file(Ts, File) when is_list(Ts) -> + [anno_set_file(T, File) || T <- Ts]; set_file(T, File) -> + anno_set_file(T, File). + +anno_set_file(T, File) -> F = fun(Anno) -> erl_anno:set_file(File, Anno) end, erl_parse:map_anno(F, T). diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index a525c2ae82..b1c574ea60 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1489,11 +1489,16 @@ type_preop_prec('-') -> {600,700}; type_preop_prec('bnot') -> {600,700}; type_preop_prec('#') -> {700,800}. +-type erl_parse_tree() :: abstract_clause() + | abstract_expr() + | abstract_form() + | abstract_type(). + -spec map_anno(Fun, Abstr) -> NewAbstr when Fun :: fun((Anno) -> Anno), Anno :: erl_anno:anno(), - Abstr :: abstract_form() | abstract_expr(), - NewAbstr :: abstract_form() | abstract_expr(). + Abstr :: erl_parse_tree(), + NewAbstr :: erl_parse_tree(). map_anno(F0, Abstr) -> F = fun(A, Acc) -> {F0(A), Acc} end, @@ -1506,8 +1511,8 @@ map_anno(F0, Abstr) -> Acc0 :: term(), AccIn :: term(), AccOut :: term(), - Abstr :: abstract_form() | abstract_expr(), - NewAbstr :: abstract_form() | abstract_expr(). + Abstr :: erl_parse_tree(), + NewAbstr :: erl_parse_tree(). fold_anno(F0, Acc0, Abstr) -> F = fun(A, Acc) -> {A, F0(A, Acc)} end, @@ -1521,26 +1526,26 @@ fold_anno(F0, Acc0, Abstr) -> Acc1 :: term(), AccIn :: term(), AccOut :: term(), - Abstr :: abstract_form() | abstract_expr(), - NewAbstr :: abstract_form() | abstract_expr(). + Abstr :: erl_parse_tree(), + NewAbstr :: erl_parse_tree(). mapfold_anno(F, Acc0, Abstr) -> modify_anno1(Abstr, Acc0, F). -spec new_anno(Term) -> Abstr when Term :: term(), - Abstr :: abstract_form() | abstract_expr(). + Abstr :: erl_parse_tree(). new_anno(Term) -> map_anno(fun erl_anno:new/1, Term). -spec anno_to_term(Abstr) -> term() when - Abstr :: abstract_form() | abstract_expr(). + Abstr :: erl_parse_tree(). anno_to_term(Abstract) -> map_anno(fun erl_anno:to_term/1, Abstract). --spec anno_from_term(Term) -> abstract_form() | abstract_expr() when +-spec anno_from_term(Term) -> erl_parse_tree() when Term :: term(). anno_from_term(Term) -> diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl index 9577d17a85..9f69cd5003 100644 --- a/lib/stdlib/src/qlc_pt.erl +++ b/lib/stdlib/src/qlc_pt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2015. All Rights Reserved. +%% Copyright Ericsson AB 2004-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -200,7 +200,7 @@ exclude_integers_from_unique_line_numbers(Forms, NodeInfo) -> find_integers(Forms) -> F = fun(A) -> - Fs1 = erl_parse:map_anno(fun(_) -> A end, Forms), + Fs1 = map_anno(fun(_) -> A end, Forms), ordsets:from_list(integers(Fs1, [])) end, ordsets:to_list(ordsets:intersection(F(anno0()), F(anno1()))). @@ -319,13 +319,13 @@ badarg(Forms, State) -> E0. lc_nodes(E, NodeInfo) -> - erl_parse:map_anno(fun(Anno) -> - N = erl_anno:line(Anno), - [{N, Data}] = ets:lookup(NodeInfo, N), - NData = Data#{inside_lc => true}, - true = ets:insert(NodeInfo, {N, NData}), - Anno - end, E). + map_anno(fun(Anno) -> + N = erl_anno:line(Anno), + [{N, Data}] = ets:lookup(NodeInfo, N), + NData = Data#{inside_lc => true}, + true = ets:insert(NodeInfo, {N, NData}), + Anno + end, E). used_genvar_messages(MsL, S) -> [{File,[{Loc,?APIMOD,{used_generator_variable,V}}]} @@ -416,7 +416,7 @@ intro_anno(LC, Where, QId, NodeInfo) -> true = ets:insert(NodeInfo, {Location,Data}), Anno end, - erl_parse:map_anno(Fun, save_anno(LC, NodeInfo)). + map_anno(Fun, save_anno(LC, NodeInfo)). compile_errors(FormsNoShadows) -> case compile_forms(FormsNoShadows, []) of @@ -1650,7 +1650,7 @@ reset_anno(T) -> set_anno(T, anno0()). set_anno(T, A) -> - erl_parse:map_anno(fun(_L) -> A end, T). + map_anno(fun(_L) -> A end, T). -record(fstate, {state, bind_fun, imported}). @@ -2609,7 +2609,7 @@ save_anno(Abstr, NodeInfo) -> true = ets:insert(NodeInfo, Data), erl_anno:new(N) end, - erl_parse:map_anno(F, Abstr). + map_anno(F, Abstr). next_slot(T) -> I = ets:update_counter(T, var_n, 1), @@ -2633,7 +2633,7 @@ restore_anno(Abstr, NodeInfo) -> Anno end end, - erl_parse:map_anno(F, Abstr). + map_anno(F, Abstr). restore_loc(Location, #state{node_info = NodeInfo}) -> case ets:lookup(NodeInfo, Location) of @@ -2872,6 +2872,14 @@ var_mapfold(F, A0, [E0 | Es0]) -> var_mapfold(_F, A, E) -> {E, A}. +map_anno(F, AbstrList) when is_list(AbstrList) -> + [map_anno1(F, Abstr) || Abstr <- AbstrList]; +map_anno(F, Abstr) -> + map_anno1(F, Abstr). + +map_anno1(F, Abstr) -> + erl_parse:map_anno(F, Abstr). + family_list(L) -> sofs:to_external(family(L)). -- cgit v1.2.3 From 56eded8ac675bf0e6f955c291be845f668d2b795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 13 Jan 2016 15:11:43 +0100 Subject: erl_prim_loader: Rename release_archives/0 Rename release_archives/0 to purge_archive_cache/0 to make it clearer what it does and what it doesn't do. Also add a comment about its intended purpose. Note that release_archives/0 is not documented and is part of the experimental archive feature. Furthermore, the only uses I could find were in the test suite. I did not find any uses in the external applications relx and rebar3 applications that are known to use archives. Therefore, I think that the increased clarity is worth the small risk of breaking code. --- lib/kernel/test/erl_prim_loader_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index ffcde5e458..e9ff79af19 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -392,7 +392,7 @@ local_archive(Config) when is_list(Config) -> ?line ok = test_archive(Node, Archive, KernelDir, BeamName), %% Cleanup - ?line ok = rpc:call(Node, erl_prim_loader, release_archives, []), + ok = rpc:call(Node, erl_prim_loader, purge_archive_cache, []), ?line ok = file:delete(Archive), ok. @@ -550,7 +550,7 @@ virtual_dir_in_archive(Config) when is_list(Config) -> ?line {ok, [EbinBase]} = erl_prim_loader:list_dir(AppDir), %% Cleanup - ?line ok = erl_prim_loader:release_archives(), + ok = erl_prim_loader:purge_archive_cache(), ?line ok = file:delete(Archive), ok. -- cgit v1.2.3 From 907618a797dcdbbcaa020edcdb2c0305eba2bb0f Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 20 Jan 2016 14:04:03 +0100 Subject: dialyzer: Correct a test case --- lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl index b6cab5e24b..1677b4efb8 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl @@ -781,7 +781,8 @@ add_mod_info({attribute,_Line,record,{RecName,Fields}}, true -> ModInfo; false -> - TypedRecord = {attribute,0,type,{{record,RecName},Fields,[]}}, + A = erl_anno:new(0), + TypedRecord = {attribute,A,type,{{record,RecName},Fields,[]}}, add_mod_info(TypedRecord, ModInfo) end; add_mod_info({attribute,_Line,Kind,{Name,TypeForm,VarForms}}, -- cgit v1.2.3 From 1b883a0a8163545f107c7f315990417726b54235 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 20 Jan 2016 15:01:06 +0100 Subject: common_test: Fix a Dialyzer warning --- lib/common_test/src/ct_make.erl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl index f4b81a0ef6..e7a9cfa843 100644 --- a/lib/common_test/src/ct_make.erl +++ b/lib/common_test/src/ct_make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2013. All Rights Reserved. +%% Copyright Ericsson AB 2009-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -324,10 +324,11 @@ check_includes(File, IncludePath, ObjMTime) -> end. check_includes2(Epp, File, ObjMTime) -> + A1 = erl_anno:new(1), case epp:parse_erl_form(Epp) of - {ok, {attribute, 1, file, {File, 1}}} -> + {ok, {attribute, A1, file, {File, A1}}} -> check_includes2(Epp, File, ObjMTime); - {ok, {attribute, 1, file, {IncFile, 1}}} -> + {ok, {attribute, A1, file, {IncFile, A1}}} -> case file:read_file_info(IncFile) of {ok, #file_info{mtime=MTime}} when MTime>ObjMTime -> epp:close(Epp), -- cgit v1.2.3 From e5949b5cd2a6d0f691097de189e0f95f34ac404d Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 20 Jan 2016 15:01:18 +0100 Subject: tools: Fix a Dialyzer warning --- lib/tools/src/make.erl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl index 5d5a1ef2bd..26378f28a0 100644 --- a/lib/tools/src/make.erl +++ b/lib/tools/src/make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -299,10 +299,11 @@ check_includes(File, IncludePath, ObjMTime) -> end. check_includes2(Epp, File, ObjMTime) -> + A1 = erl_anno:new(1), case epp:parse_erl_form(Epp) of - {ok, {attribute, 1, file, {File, 1}}} -> + {ok, {attribute, A1, file, {File, A1}}} -> check_includes2(Epp, File, ObjMTime); - {ok, {attribute, 1, file, {IncFile, 1}}} -> + {ok, {attribute, A1, file, {IncFile, A1}}} -> case file:read_file_info(IncFile) of {ok, #file_info{mtime=MTime}} when MTime>ObjMTime -> epp:close(Epp), -- cgit v1.2.3 From 3fab95dc101e5765db66ae8b8479c181a934912d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 19 Jan 2016 16:36:08 +0100 Subject: ssl: In interop tests always check if SSL/TLS version is supported by OpenSSL As sslv3 is being faced out we need to test for old version support as well as newer versions. --- lib/ssl/test/ssl_test_lib.erl | 62 +++++++++++++++++++++++++---------- lib/ssl/test/ssl_to_openssl_SUITE.erl | 33 ++++--------------- 2 files changed, 51 insertions(+), 44 deletions(-) (limited to 'lib') diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 9a76d603b1..77c29668b5 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1158,23 +1158,27 @@ cipher_restriction(Config0) -> end. check_sane_openssl_version(Version) -> - case {Version, os:cmd("openssl version")} of - {_, "OpenSSL 1.0.2" ++ _} -> - true; - {_, "OpenSSL 1.0.1" ++ _} -> - true; - {'tlsv1.2', "OpenSSL 1.0" ++ _} -> - false; - {'tlsv1.1', "OpenSSL 1.0" ++ _} -> - false; - {'tlsv1.2', "OpenSSL 0" ++ _} -> - false; - {'tlsv1.1', "OpenSSL 0" ++ _} -> - false; - {_, _} -> - true + case supports_ssl_tls_version(Version) of + true -> + case {Version, os:cmd("openssl version")} of + {_, "OpenSSL 1.0.2" ++ _} -> + true; + {_, "OpenSSL 1.0.1" ++ _} -> + true; + {'tlsv1.2', "OpenSSL 1.0" ++ _} -> + false; + {'tlsv1.1', "OpenSSL 1.0" ++ _} -> + false; + {'tlsv1.2', "OpenSSL 0" ++ _} -> + false; + {'tlsv1.1', "OpenSSL 0" ++ _} -> + false; + {_, _} -> + true + end; + false -> + false end. - enough_openssl_crl_support("OpenSSL 0." ++ _) -> false; enough_openssl_crl_support(_) -> true. @@ -1198,7 +1202,9 @@ version_flag('tlsv1.1') -> version_flag('tlsv1.2') -> "-tls1_2"; version_flag(sslv3) -> - "-ssl3". + "-ssl3"; +version_flag(sslv2) -> + "-ssl2". filter_suites(Ciphers0) -> Version = tls_record:highest_protocol_version([]), @@ -1249,3 +1255,25 @@ portable_open_port(Exe, Args) -> ct:pal("open_port({spawn_executable, ~p}, [{args, ~p}, stderr_to_stdout]).", [AbsPath, Args]), open_port({spawn_executable, AbsPath}, [{args, Args}, stderr_to_stdout]). + +supports_ssl_tls_version(Version) -> + VersionFlag = version_flag(Version), + Exe = "openssl", + Args = ["s_client", VersionFlag], + Port = ssl_test_lib:portable_open_port(Exe, Args), + do_supports_ssl_tls_version(Port). + +do_supports_ssl_tls_version(Port) -> + receive + {Port, {data, "unknown option" ++ _}} -> + false; + {Port, {data, Data}} -> + case lists:member("error", string:tokens(Data, ":")) of + true -> + false; + false -> + do_supports_ssl_tls_version(Port) + end + after 500 -> + true + end. diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 13523730b0..bcdefb5fca 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -175,7 +175,12 @@ special_init(TestCase, Config) check_sane_openssl_renegotaite(Config, Version); special_init(ssl2_erlang_server_openssl_client, Config) -> - check_sane_openssl_sslv2(Config); + case ssl_test_lib:supports_ssl_tls_version(sslv2) of + true -> + Config; + false -> + {skip, "sslv2 not supported by openssl"} + end; special_init(TestCase, Config) when TestCase == erlang_client_alpn_openssl_server_alpn; @@ -1756,32 +1761,6 @@ check_sane_openssl_renegotaite(Config) -> Config end. -check_sane_openssl_sslv2(Config) -> - Exe = "openssl", - Args = ["s_client", "-ssl2"], - Port = ssl_test_lib:portable_open_port(Exe, Args), - case supports_sslv2(Port) of - true -> - Config; - false -> - {skip, "sslv2 not supported by openssl"} - end. - -supports_sslv2(Port) -> - receive - {Port, {data, "unknown option -ssl2" ++ _}} -> - false; - {Port, {data, Data}} -> - case lists:member("error", string:tokens(Data, ":")) of - true -> - false; - false -> - supports_sslv2(Port) - end - after 500 -> - true - end. - workaround_openssl_s_clinent() -> %% http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=683159 %% https://bugs.archlinux.org/task/33919 -- cgit v1.2.3